Fossil SCM

Merge updates from trunk.

mistachkin 2014-08-13 20:09 globalStateCmd merge
Commit 0f3084cd16460f4ab336041499681eac678f6bd1
+1787 -1501
--- autosetup/jimsh0.c
+++ autosetup/jimsh0.c
@@ -1,6 +1,6 @@
1
-/* This is single source file, bootstrap version of Jim Tcl. See http://jim.berlios.de/ */
1
+/* This is single source file, bootstrap version of Jim Tcl. See http://jim.tcl.tk/ */
22
#define _GNU_SOURCE
33
#define JIM_TCL_COMPAT
44
#define JIM_REFERENCES
55
#define JIM_ANSIC
66
#define JIM_REGEXP
@@ -47,10 +47,14 @@
4747
#define JIM_VERSION 75
4848
#ifndef JIM_WIN32COMPAT_H
4949
#define JIM_WIN32COMPAT_H
5050
5151
52
+
53
+#ifdef __cplusplus
54
+extern "C" {
55
+#endif
5256
5357
5458
#if defined(_WIN32) || defined(WIN32)
5559
5660
#define HAVE_DLOPEN
@@ -106,17 +110,31 @@
106110
} DIR;
107111
108112
DIR *opendir(const char *name);
109113
int closedir(DIR *dir);
110114
struct dirent *readdir(DIR *dir);
111
-#endif
115
+
116
+#elif defined(__MINGW32__)
117
+
118
+#define strtod __strtod
119
+
120
+#endif
112121
113122
#endif
123
+
124
+#ifdef __cplusplus
125
+}
126
+#endif
114127
115128
#endif
116129
#ifndef UTF8_UTIL_H
117130
#define UTF8_UTIL_H
131
+
132
+#ifdef __cplusplus
133
+extern "C" {
134
+#endif
135
+
118136
119137
120138
#define MAX_UTF8_LEN 4
121139
122140
int utf8_fromunicode(char *p, unsigned uc);
@@ -125,10 +143,11 @@
125143
#include <ctype.h>
126144
127145
128146
#define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B))
129147
#define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
148
+#define utf8_getchars(CP, C) (*(CP) = (C), 1)
130149
#define utf8_upper(C) toupper(C)
131150
#define utf8_title(C) toupper(C)
132151
#define utf8_lower(C) tolower(C)
133152
#define utf8_index(C, I) (I)
134153
#define utf8_charlen(C) 1
@@ -135,10 +154,14 @@
135154
#define utf8_prev_len(S, L) 1
136155
137156
#else
138157
139158
#endif
159
+
160
+#ifdef __cplusplus
161
+}
162
+#endif
140163
141164
#endif
142165
143166
#ifndef __JIM__H
144167
#define __JIM__H
@@ -199,44 +222,34 @@
199222
#define JIM_EVAL 7
200223
201224
#define JIM_MAX_CALLFRAME_DEPTH 1000
202225
#define JIM_MAX_EVAL_DEPTH 2000
203226
204
-#define JIM_NONE 0
205
-#define JIM_ERRMSG 1
206
-
207
-#define JIM_UNSHARED 4
208
-#define JIM_MUSTEXIST 8
209
-
210
-
211
-#define JIM_GLOBAL_ONLY 0x100
227
+
228
+#define JIM_PRIV_FLAG_SHIFT 20
229
+
230
+#define JIM_NONE 0
231
+#define JIM_ERRMSG 1
232
+#define JIM_ENUM_ABBREV 2
233
+#define JIM_UNSHARED 4
234
+#define JIM_MUSTEXIST 8
212235
213236
214237
#define JIM_SUBST_NOVAR 1
215238
#define JIM_SUBST_NOCMD 2
216239
#define JIM_SUBST_NOESC 4
217240
#define JIM_SUBST_FLAG 128
218241
219
-
220
-#define JIM_NOTUSED(V) ((void) V)
221
-
222
-
223
-#define JIM_ENUM_ABBREV 2
224
-
225242
226243
#define JIM_CASESENS 0
227244
#define JIM_NOCASE 1
228245
229246
230247
#define JIM_PATH_LEN 1024
231248
232249
233
-#ifdef JIM_CRLF
234
-#define JIM_NL "\r\n"
235
-#else
236
-#define JIM_NL "\n"
237
-#endif
250
+#define JIM_NOTUSED(V) ((void) V)
238251
239252
#define JIM_LIBPATH "auto_path"
240253
#define JIM_INTERACTIVE "tcl_interactive"
241254
242255
@@ -266,21 +279,22 @@
266279
} Jim_HashTableType;
267280
268281
typedef struct Jim_HashTable {
269282
Jim_HashEntry **table;
270283
const Jim_HashTableType *type;
284
+ void *privdata;
271285
unsigned int size;
272286
unsigned int sizemask;
273287
unsigned int used;
274288
unsigned int collisions;
275
- void *privdata;
289
+ unsigned int uniq;
276290
} Jim_HashTable;
277291
278292
typedef struct Jim_HashTableIterator {
279293
Jim_HashTable *ht;
280
- int index;
281294
Jim_HashEntry *entry, *nextEntry;
295
+ int index;
282296
} Jim_HashTableIterator;
283297
284298
285299
#define JIM_HT_INITIAL_SIZE 16
286300
@@ -289,35 +303,35 @@
289303
if ((ht)->type->valDestructor) \
290304
(ht)->type->valDestructor((ht)->privdata, (entry)->u.val)
291305
292306
#define Jim_SetHashVal(ht, entry, _val_) do { \
293307
if ((ht)->type->valDup) \
294
- entry->u.val = (ht)->type->valDup((ht)->privdata, _val_); \
308
+ (entry)->u.val = (ht)->type->valDup((ht)->privdata, (_val_)); \
295309
else \
296
- entry->u.val = (_val_); \
310
+ (entry)->u.val = (_val_); \
297311
} while(0)
298312
299313
#define Jim_FreeEntryKey(ht, entry) \
300314
if ((ht)->type->keyDestructor) \
301315
(ht)->type->keyDestructor((ht)->privdata, (entry)->key)
302316
303317
#define Jim_SetHashKey(ht, entry, _key_) do { \
304318
if ((ht)->type->keyDup) \
305
- entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \
319
+ (entry)->key = (ht)->type->keyDup((ht)->privdata, (_key_)); \
306320
else \
307
- entry->key = (void *)(_key_); \
321
+ (entry)->key = (void *)(_key_); \
308322
} while(0)
309323
310324
#define Jim_CompareHashKeys(ht, key1, key2) \
311325
(((ht)->type->keyCompare) ? \
312
- (ht)->type->keyCompare((ht)->privdata, key1, key2) : \
326
+ (ht)->type->keyCompare((ht)->privdata, (key1), (key2)) : \
313327
(key1) == (key2))
314328
315
-#define Jim_HashKey(ht, key) (ht)->type->hashFunction(key)
329
+#define Jim_HashKey(ht, key) ((ht)->type->hashFunction(key) + (ht)->uniq)
316330
317331
#define Jim_GetHashEntryKey(he) ((he)->key)
318
-#define Jim_GetHashEntryVal(he) ((he)->val)
332
+#define Jim_GetHashEntryVal(he) ((he)->u.val)
319333
#define Jim_GetHashTableCollisions(ht) ((ht)->collisions)
320334
#define Jim_GetHashTableSize(ht) ((ht)->size)
321335
#define Jim_GetHashTableUsed(ht) ((ht)->used)
322336
323337
@@ -341,19 +355,19 @@
341355
void *ptr1;
342356
void *ptr2;
343357
} twoPtrValue;
344358
345359
struct {
346
- unsigned long callFrameId;
347360
struct Jim_Var *varPtr;
361
+ unsigned long callFrameId;
348362
int global;
349363
} varValue;
350364
351365
struct {
352
- unsigned long procEpoch;
353366
struct Jim_Obj *nsObj;
354367
struct Jim_Cmd *cmdPtr;
368
+ unsigned long procEpoch;
355369
} cmdValue;
356370
357371
struct {
358372
struct Jim_Obj **ele;
359373
int len;
@@ -379,12 +393,12 @@
379393
struct Jim_Obj *varNameObjPtr;
380394
struct Jim_Obj *indexObjPtr;
381395
} dictSubstValue;
382396
383397
struct {
384
- unsigned flags;
385398
void *compre;
399
+ unsigned flags;
386400
} regexpValue;
387401
struct {
388402
int line;
389403
int argc;
390404
} scriptLineValue;
@@ -453,21 +467,24 @@
453467
struct Jim_CallFrame *next;
454468
Jim_Obj *nsObj;
455469
Jim_Obj *fileNameObj;
456470
int line;
457471
Jim_Stack *localCommands;
472
+ int tailcall;
473
+ struct Jim_Obj *tailcallObj;
474
+ struct Jim_Cmd *tailcallCmd;
458475
} Jim_CallFrame;
459476
460477
typedef struct Jim_Var {
461478
Jim_Obj *objPtr;
462479
struct Jim_CallFrame *linkFramePtr;
463480
} Jim_Var;
464481
465482
466
-typedef int (*Jim_CmdProc)(struct Jim_Interp *interp, int argc,
483
+typedef int Jim_CmdProc(struct Jim_Interp *interp, int argc,
467484
Jim_Obj *const *argv);
468
-typedef void (*Jim_DelCmdProc)(struct Jim_Interp *interp, void *privData);
485
+typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData);
469486
470487
471488
472489
typedef struct Jim_Cmd {
473490
int inUse;
@@ -474,12 +491,12 @@
474491
int isproc;
475492
struct Jim_Cmd *prevCmd;
476493
union {
477494
struct {
478495
479
- Jim_CmdProc cmdProc;
480
- Jim_DelCmdProc delProc;
496
+ Jim_CmdProc *cmdProc;
497
+ Jim_DelCmdProc *delProc;
481498
void *privData;
482499
} native;
483500
struct {
484501
485502
Jim_Obj *argListObjPtr;
@@ -589,15 +606,11 @@
589606
Jim_Obj *finalizerCmdNamePtr;
590607
char tag[JIM_REFERENCE_TAGLEN+1];
591608
} Jim_Reference;
592609
593610
594
-
595611
#define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0)
596
-
597
-
598
-
599612
#define Jim_FreeHashTableIterator(iter) Jim_Free(iter)
600613
601614
#define JIM_EXPORT
602615
603616
@@ -608,10 +621,11 @@
608621
JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);
609622
610623
611624
JIM_EXPORT char **Jim_GetEnviron(void);
612625
JIM_EXPORT void Jim_SetEnviron(char **env);
626
+JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *template);
613627
614628
615629
JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);
616630
617631
@@ -739,13 +753,12 @@
739753
JIM_EXPORT int Jim_SetVariableStrWithStr (Jim_Interp *interp,
740754
const char *name, const char *val);
741755
JIM_EXPORT int Jim_SetVariableLink (Jim_Interp *interp,
742756
Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr,
743757
Jim_CallFrame *targetCallFrame);
744
-JIM_EXPORT int Jim_CreateNamespaceVariable(Jim_Interp *interp,
745
- Jim_Obj *varNameObj, Jim_Obj *targetNameObj);
746
-JIM_EXPORT int Jim_DiscardNamespaceVars(Jim_Interp *interp);
758
+JIM_EXPORT Jim_Obj * Jim_MakeGlobalNamespaceName(Jim_Interp *interp,
759
+ Jim_Obj *nameObjPtr);
747760
JIM_EXPORT Jim_Obj * Jim_GetVariable (Jim_Interp *interp,
748761
Jim_Obj *nameObjPtr, int flags);
749762
JIM_EXPORT Jim_Obj * Jim_GetGlobalVariable (Jim_Interp *interp,
750763
Jim_Obj *nameObjPtr, int flags);
751764
JIM_EXPORT Jim_Obj * Jim_GetVariableStr (Jim_Interp *interp,
@@ -804,10 +817,11 @@
804817
JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
805818
Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr);
806819
JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj);
807820
JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr);
808821
JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr);
822
+JIM_EXPORT int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr);
809823
810824
811825
JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr,
812826
int *intPtr);
813827
@@ -869,19 +883,19 @@
869883
870884
871885
JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp);
872886
JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base);
873887
JIM_EXPORT int Jim_IsBigEndian(void);
888
+
874889
#define Jim_CheckSignal(i) ((i)->signal_level && (i)->sigmask)
875890
876891
877892
JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName);
878893
JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp);
879894
880895
881896
JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command);
882
-
883897
884898
885899
JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr);
886900
JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr);
887901
@@ -903,16 +917,16 @@
903917
#define JIM_MODFLAG_HIDDEN 0x0001
904918
#define JIM_MODFLAG_FULLARGV 0x0002
905919
906920
907921
908
-typedef int tclmod_cmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
922
+typedef int jim_subcmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
909923
910924
typedef struct {
911925
const char *cmd;
912926
const char *args;
913
- tclmod_cmd_function *function;
927
+ jim_subcmd_function *function;
914928
short minargs;
915929
short maxargs;
916930
unsigned short flags;
917931
} jim_subcmd_type;
918932
@@ -929,22 +943,16 @@
929943
930944
#endif
931945
#ifndef JIMREGEXP_H
932946
#define JIMREGEXP_H
933947
934
-#ifndef _JIMAUTOCONF_H
935
-#error Need jimautoconf.h
948
+
949
+#ifdef __cplusplus
950
+extern "C" {
936951
#endif
937952
938
-#if defined(HAVE_REGCOMP) && !defined(JIM_REGEXP)
939
-
940
-#include <regex.h>
941
-
942
-#else
943
-
944953
#include <stdlib.h>
945
-
946954
947955
typedef struct {
948956
int rm_so;
949957
int rm_eo;
950958
} regmatch_t;
@@ -1013,10 +1021,12 @@
10131021
int regcomp(regex_t *preg, const char *regex, int cflags);
10141022
int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
10151023
size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);
10161024
void regfree(regex_t *preg);
10171025
1026
+#ifdef __cplusplus
1027
+}
10181028
#endif
10191029
10201030
#endif
10211031
int Jim_bootstrapInit(Jim_Interp *interp)
10221032
{
@@ -1079,10 +1089,15 @@
10791089
"\n"
10801090
"package require readdir\n"
10811091
"\n"
10821092
"\n"
10831093
"proc glob.globdir {dir pattern} {\n"
1094
+" if {[file exists $dir/$pattern]} {\n"
1095
+"\n"
1096
+" return $pattern\n"
1097
+" }\n"
1098
+"\n"
10841099
" set result {}\n"
10851100
" set files [readdir $dir]\n"
10861101
" lappend files . ..\n"
10871102
"\n"
10881103
" foreach name $files {\n"
@@ -1261,10 +1276,12 @@
12611276
{
12621277
if (Jim_PackageProvide(interp, "stdlib", "1.0", JIM_ERRMSG))
12631278
return JIM_ERR;
12641279
12651280
return Jim_EvalSource(interp, "stdlib.tcl", 1,
1281
+"\n"
1282
+"\n"
12661283
"\n"
12671284
"proc lambda {arglist args} {\n"
12681285
" tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n"
12691286
"}\n"
12701287
"\n"
@@ -1290,46 +1307,48 @@
12901307
"}\n"
12911308
"\n"
12921309
"\n"
12931310
"\n"
12941311
"\n"
1295
-"proc stacktrace {} {\n"
1312
+"proc stacktrace {{skip 0}} {\n"
12961313
" set trace {}\n"
1297
-" foreach level [range 1 [info level]] {\n"
1298
-" lassign [info frame -$level] p f l\n"
1299
-" lappend trace $p $f $l\n"
1314
+" incr skip\n"
1315
+" foreach level [range $skip [info level]] {\n"
1316
+" lappend trace {*}[info frame -$level]\n"
13001317
" }\n"
13011318
" return $trace\n"
13021319
"}\n"
13031320
"\n"
13041321
"\n"
13051322
"proc stackdump {stacktrace} {\n"
1306
-" set result {}\n"
1307
-" set count 0\n"
1323
+" set lines {}\n"
13081324
" foreach {l f p} [lreverse $stacktrace] {\n"
1309
-" if {$count} {\n"
1310
-" append result \\n\n"
1311
-" }\n"
1312
-" incr count\n"
1325
+" set line {}\n"
13131326
" if {$p ne \"\"} {\n"
1314
-" append result \"in procedure '$p' \"\n"
1327
+" append line \"in procedure '$p' \"\n"
13151328
" if {$f ne \"\"} {\n"
1316
-" append result \"called \"\n"
1329
+" append line \"called \"\n"
13171330
" }\n"
13181331
" }\n"
13191332
" if {$f ne \"\"} {\n"
1320
-" append result \"at file \\\"$f\\\", line $l\"\n"
1333
+" append line \"at file \\\"$f\\\", line $l\"\n"
1334
+" }\n"
1335
+" if {$line ne \"\"} {\n"
1336
+" lappend lines $line\n"
13211337
" }\n"
13221338
" }\n"
1323
-" return $result\n"
1339
+" join $lines \\n\n"
13241340
"}\n"
13251341
"\n"
13261342
"\n"
13271343
"\n"
13281344
"proc errorInfo {msg {stacktrace \"\"}} {\n"
13291345
" if {$stacktrace eq \"\"} {\n"
1346
+"\n"
13301347
" set stacktrace [info stacktrace]\n"
1348
+"\n"
1349
+" lappend stacktrace {*}[stacktrace 1]\n"
13311350
" }\n"
13321351
" lassign $stacktrace p f l\n"
13331352
" if {$f ne \"\"} {\n"
13341353
" set result \"Runtime Error: $f:$l: \"\n"
13351354
" }\n"
@@ -1356,25 +1375,46 @@
13561375
" }\n"
13571376
" return \"\"\n"
13581377
"}\n"
13591378
"\n"
13601379
"\n"
1361
-"proc {dict with} {dictVar args script} {\n"
1362
-" upvar $dictVar dict\n"
1380
+"proc {dict with} {&dictVar {args key} script} {\n"
13631381
" set keys {}\n"
1364
-" foreach {n v} [dict get $dict {*}$args] {\n"
1382
+" foreach {n v} [dict get $dictVar {*}$key] {\n"
13651383
" upvar $n var_$n\n"
13661384
" set var_$n $v\n"
13671385
" lappend keys $n\n"
13681386
" }\n"
13691387
" catch {uplevel 1 $script} msg opts\n"
1370
-" if {[info exists dict] && [dict exists $dict {*}$args]} {\n"
1388
+" if {[info exists dictVar] && ([llength $key] == 0 || [dict exists $dictVar {*}$key])} {\n"
13711389
" foreach n $keys {\n"
13721390
" if {[info exists var_$n]} {\n"
1373
-" dict set dict {*}$args $n [set var_$n]\n"
1391
+" dict set dictVar {*}$key $n [set var_$n]\n"
1392
+" } else {\n"
1393
+" dict unset dictVar {*}$key $n\n"
1394
+" }\n"
1395
+" }\n"
1396
+" }\n"
1397
+" return {*}$opts $msg\n"
1398
+"}\n"
1399
+"\n"
1400
+"\n"
1401
+"proc {dict update} {&varName args script} {\n"
1402
+" set keys {}\n"
1403
+" foreach {n v} $args {\n"
1404
+" upvar $v var_$v\n"
1405
+" if {[dict exists $varName $n]} {\n"
1406
+" set var_$v [dict get $varName $n]\n"
1407
+" }\n"
1408
+" }\n"
1409
+" catch {uplevel 1 $script} msg opts\n"
1410
+" if {[info exists varName]} {\n"
1411
+" foreach {n v} $args {\n"
1412
+" if {[info exists var_$v]} {\n"
1413
+" dict set varName $n [set var_$v]\n"
13741414
" } else {\n"
1375
-" dict unset dict {*}$args $n\n"
1415
+" dict unset varName $n\n"
13761416
" }\n"
13771417
" }\n"
13781418
" }\n"
13791419
" return {*}$opts $msg\n"
13801420
"}\n"
@@ -1389,10 +1429,69 @@
13891429
" dict set dict $k $v\n"
13901430
" }\n"
13911431
" }\n"
13921432
" return $dict\n"
13931433
"}\n"
1434
+"\n"
1435
+"proc {dict replace} {dictionary {args {key value}}} {\n"
1436
+" if {[llength ${key value}] % 2} {\n"
1437
+" tailcall {dict replace}\n"
1438
+" }\n"
1439
+" tailcall dict merge $dictionary ${key value}\n"
1440
+"}\n"
1441
+"\n"
1442
+"\n"
1443
+"proc {dict lappend} {varName key {args value}} {\n"
1444
+" upvar $varName dict\n"
1445
+" if {[exists dict] && [dict exists $dict $key]} {\n"
1446
+" set list [dict get $dict $key]\n"
1447
+" }\n"
1448
+" lappend list {*}$value\n"
1449
+" dict set dict $key $list\n"
1450
+"}\n"
1451
+"\n"
1452
+"\n"
1453
+"proc {dict append} {varName key {args value}} {\n"
1454
+" upvar $varName dict\n"
1455
+" if {[exists dict] && [dict exists $dict $key]} {\n"
1456
+" set str [dict get $dict $key]\n"
1457
+" }\n"
1458
+" append str {*}$value\n"
1459
+" dict set dict $key $str\n"
1460
+"}\n"
1461
+"\n"
1462
+"\n"
1463
+"proc {dict incr} {varName key {increment 1}} {\n"
1464
+" upvar $varName dict\n"
1465
+" if {[exists dict] && [dict exists $dict $key]} {\n"
1466
+" set value [dict get $dict $key]\n"
1467
+" }\n"
1468
+" incr value $increment\n"
1469
+" dict set dict $key $value\n"
1470
+"}\n"
1471
+"\n"
1472
+"\n"
1473
+"proc {dict remove} {dictionary {args key}} {\n"
1474
+" foreach k $key {\n"
1475
+" dict unset dictionary $k\n"
1476
+" }\n"
1477
+" return $dictionary\n"
1478
+"}\n"
1479
+"\n"
1480
+"\n"
1481
+"proc {dict values} {dictionary {pattern *}} {\n"
1482
+" dict keys [lreverse $dictionary] $pattern\n"
1483
+"}\n"
1484
+"\n"
1485
+"\n"
1486
+"proc {dict for} {vars dictionary script} {\n"
1487
+" if {[llength $vars] != 2} {\n"
1488
+" return -code error \"must have exactly two variable names\"\n"
1489
+" }\n"
1490
+" dict size $dictionary\n"
1491
+" tailcall foreach $vars $dictionary $script\n"
1492
+"}\n"
13941493
);
13951494
}
13961495
int Jim_tclcompatInit(Jim_Interp *interp)
13971496
{
13981497
if (Jim_PackageProvide(interp, "tclcompat", "1.0", JIM_ERRMSG))
@@ -1403,12 +1502,14 @@
14031502
"\n"
14041503
"\n"
14051504
"\n"
14061505
"\n"
14071506
"\n"
1507
+"\n"
14081508
"\n"
14091509
"set env [env]\n"
1510
+"\n"
14101511
"\n"
14111512
"if {[info commands stdout] ne \"\"} {\n"
14121513
"\n"
14131514
" foreach p {gets flush close eof seek tell} {\n"
14141515
" proc $p {chan args} {p} {\n"
@@ -1455,51 +1556,10 @@
14551556
" }\n"
14561557
" }\n"
14571558
" }\n"
14581559
"}\n"
14591560
"\n"
1460
-"\n"
1461
-"proc case {var args} {\n"
1462
-"\n"
1463
-" if {[lindex $args 0] eq \"in\"} {\n"
1464
-" set args [lrange $args 1 end]\n"
1465
-" }\n"
1466
-"\n"
1467
-"\n"
1468
-" if {[llength $args] == 1} {\n"
1469
-" set args [lindex $args 0]\n"
1470
-" }\n"
1471
-"\n"
1472
-"\n"
1473
-" if {[llength $args] % 2 != 0} {\n"
1474
-" return -code error \"extra case pattern with no body\"\n"
1475
-" }\n"
1476
-"\n"
1477
-"\n"
1478
-" local proc case.checker {value pattern} {\n"
1479
-" string match $pattern $value\n"
1480
-" }\n"
1481
-"\n"
1482
-" foreach {value action} $args {\n"
1483
-" if {$value eq \"default\"} {\n"
1484
-" set do_action $action\n"
1485
-" continue\n"
1486
-" } elseif {[lsearch -bool -command case.checker $value $var]} {\n"
1487
-" set do_action $action\n"
1488
-" break\n"
1489
-" }\n"
1490
-" }\n"
1491
-"\n"
1492
-" if {[info exists do_action]} {\n"
1493
-" set rc [catch [list uplevel 1 $do_action] result opts]\n"
1494
-" if {$rc} {\n"
1495
-" incr opts(-level)\n"
1496
-" }\n"
1497
-" return {*}$opts $result\n"
1498
-" }\n"
1499
-"}\n"
1500
-"\n"
15011561
"\n"
15021562
"proc fileevent {args} {\n"
15031563
" tailcall {*}$args\n"
15041564
"}\n"
15051565
"\n"
@@ -1529,13 +1589,25 @@
15291589
" error \"bad option \\\"$force\\\": should be -force\"\n"
15301590
" }\n"
15311591
"\n"
15321592
" set in [open $source]\n"
15331593
"\n"
1534
-" if {$force eq \"\" && [file exists $target]} {\n"
1535
-" $in close\n"
1536
-" error \"error copying \\\"$source\\\" to \\\"$target\\\": file already exists\"\n"
1594
+" if {[file exists $target]} {\n"
1595
+" if {$force eq \"\"} {\n"
1596
+" error \"error copying \\\"$source\\\" to \\\"$target\\\": file already exists\"\n"
1597
+" }\n"
1598
+"\n"
1599
+" if {$source eq $target} {\n"
1600
+" return\n"
1601
+" }\n"
1602
+"\n"
1603
+"\n"
1604
+" file stat $source ss\n"
1605
+" file stat $target ts\n"
1606
+" if {$ss(dev) == $ts(dev) && $ss(ino) == $ts(ino) && $ss(ino)} {\n"
1607
+" return\n"
1608
+" }\n"
15371609
" }\n"
15381610
" set out [open $target w]\n"
15391611
" $in copyto $out\n"
15401612
" $out close\n"
15411613
" } on error {msg opts} {\n"
@@ -1580,18 +1652,18 @@
15801652
" error $error\n"
15811653
" }\n"
15821654
"}\n"
15831655
"\n"
15841656
"\n"
1585
-"local proc pid {{chan {}}} {\n"
1586
-" if {$chan eq \"\"} {\n"
1657
+"local proc pid {{channelId {}}} {\n"
1658
+" if {$channelId eq \"\"} {\n"
15871659
" tailcall upcall pid\n"
15881660
" }\n"
1589
-" if {[catch {$chan tell}]} {\n"
1590
-" return -code error \"can not find channel named \\\"$chan\\\"\"\n"
1661
+" if {[catch {$channelId tell}]} {\n"
1662
+" return -code error \"can not find channel named \\\"$channelId\\\"\"\n"
15911663
" }\n"
1592
-" if {[catch {$chan pid} pids]} {\n"
1664
+" if {[catch {$channelId pid} pids]} {\n"
15931665
" return \"\"\n"
15941666
" }\n"
15951667
" return $pids\n"
15961668
"}\n"
15971669
"\n"
@@ -1680,23 +1752,25 @@
16801752
"}\n"
16811753
);
16821754
}
16831755
16841756
1685
-
16861757
#include <stdio.h>
16871758
#include <string.h>
16881759
#include <errno.h>
16891760
#include <fcntl.h>
1761
+#ifdef HAVE_UNISTD_H
1762
+#include <unistd.h>
1763
+#include <sys/stat.h>
1764
+#endif
16901765
16911766
16921767
#if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H)
16931768
#include <sys/socket.h>
16941769
#include <netinet/in.h>
16951770
#include <arpa/inet.h>
16961771
#include <netdb.h>
1697
-#include <unistd.h>
16981772
#ifdef HAVE_SYS_UN_H
16991773
#include <sys/un.h>
17001774
#endif
17011775
#else
17021776
#define JIM_ANSIC
@@ -1728,15 +1802,12 @@
17281802
typedef struct AioFile
17291803
{
17301804
FILE *fp;
17311805
Jim_Obj *filename;
17321806
int type;
1733
- int OpenFlags;
1807
+ int openFlags;
17341808
int fd;
1735
-#ifdef O_NDELAY
1736
- int flags;
1737
-#endif
17381809
Jim_Obj *rEvent;
17391810
Jim_Obj *wEvent;
17401811
Jim_Obj *eEvent;
17411812
int addr_family;
17421813
} AioFile;
@@ -1760,20 +1831,21 @@
17601831
{
17611832
AioFile *af = privData;
17621833
17631834
JIM_NOTUSED(interp);
17641835
1765
- if (!(af->OpenFlags & AIO_KEEPOPEN)) {
1766
- fclose(af->fp);
1767
- }
1768
-
17691836
Jim_DecrRefCount(interp, af->filename);
17701837
17711838
#ifdef jim_ext_eventloop
17721839
17731840
Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION);
17741841
#endif
1842
+
1843
+ if (!(af->openFlags & AIO_KEEPOPEN)) {
1844
+ fclose(af->fp);
1845
+ }
1846
+
17751847
Jim_Free(af);
17761848
}
17771849
17781850
static int JimCheckStreamError(Jim_Interp *interp, AioFile *af)
17791851
{
@@ -2020,12 +2092,31 @@
20202092
return JIM_OK;
20212093
}
20222094
20232095
static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
20242096
{
2025
- Jim_DeleteCommand(interp, Jim_String(argv[0]));
2026
- return JIM_OK;
2097
+ if (argc == 3) {
2098
+#if !defined(JIM_ANSIC) && defined(HAVE_SHUTDOWN)
2099
+ static const char * const options[] = { "r", "w", NULL };
2100
+ enum { OPT_R, OPT_W, };
2101
+ int option;
2102
+ AioFile *af = Jim_CmdPrivData(interp);
2103
+
2104
+ if (Jim_GetEnum(interp, argv[2], options, &option, NULL, JIM_ERRMSG) != JIM_OK) {
2105
+ return JIM_ERR;
2106
+ }
2107
+ if (shutdown(af->fd, option == OPT_R ? SHUT_RD : SHUT_WR) == 0) {
2108
+ return JIM_OK;
2109
+ }
2110
+ JimAioSetError(interp, NULL);
2111
+#else
2112
+ Jim_SetResultString(interp, "async close not supported", -1);
2113
+#endif
2114
+ return JIM_ERR;
2115
+ }
2116
+
2117
+ return Jim_DeleteCommand(interp, Jim_String(argv[0]));
20272118
}
20282119
20292120
static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
20302121
{
20312122
AioFile *af = Jim_CmdPrivData(interp);
@@ -2072,11 +2163,11 @@
20722163
#ifdef O_NDELAY
20732164
static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
20742165
{
20752166
AioFile *af = Jim_CmdPrivData(interp);
20762167
2077
- int fmode = af->flags;
2168
+ int fmode = fcntl(af->fd, F_GETFL);
20782169
20792170
if (argc) {
20802171
long nb;
20812172
20822173
if (Jim_GetLong(interp, argv[0], &nb) != JIM_OK) {
@@ -2086,12 +2177,11 @@
20862177
fmode |= O_NDELAY;
20872178
}
20882179
else {
20892180
fmode &= ~O_NDELAY;
20902181
}
2091
- fcntl(af->fd, F_SETFL, fmode);
2092
- af->flags = fmode;
2182
+ (void)fcntl(af->fd, F_SETFL, fmode);
20932183
}
20942184
Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0);
20952185
return JIM_OK;
20962186
}
20972187
#endif
@@ -2195,11 +2285,11 @@
21952285
21962286
static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
21972287
{
21982288
AioFile *af = Jim_CmdPrivData(interp);
21992289
2200
- return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->wEvent, argc, argv);
2290
+ return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->eEvent, argc, argv);
22012291
}
22022292
#endif
22032293
22042294
static const jim_subcmd_type aio_command_table[] = {
22052295
{ "read",
@@ -2250,14 +2340,14 @@
22502340
0,
22512341
0,
22522342
22532343
},
22542344
{ "close",
2255
- NULL,
2345
+ "?r(ead)|w(rite)?",
22562346
aio_cmd_close,
22572347
0,
2258
- 0,
2348
+ 1,
22592349
JIM_MODFLAG_FULLARGV,
22602350
22612351
},
22622352
{ "seek",
22632353
"offset ?start|current|end",
@@ -2329,30 +2419,32 @@
23292419
23302420
static int JimAioOpenCommand(Jim_Interp *interp, int argc,
23312421
Jim_Obj *const *argv)
23322422
{
23332423
const char *mode;
2334
- const char *filename;
23352424
23362425
if (argc != 2 && argc != 3) {
23372426
Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?");
23382427
return JIM_ERR;
23392428
}
23402429
23412430
mode = (argc == 3) ? Jim_String(argv[2]) : "r";
2342
- filename = Jim_String(argv[1]);
23432431
23442432
#ifdef jim_ext_tclcompat
2345
-
2346
- if (*filename == '|') {
2347
- Jim_Obj *evalObj[3];
2348
-
2349
- evalObj[0] = Jim_NewStringObj(interp, "popen", -1);
2350
- evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1);
2351
- evalObj[2] = Jim_NewStringObj(interp, mode, -1);
2352
-
2353
- return Jim_EvalObjVector(interp, 3, evalObj);
2433
+ {
2434
+ const char *filename = Jim_String(argv[1]);
2435
+
2436
+
2437
+ if (*filename == '|') {
2438
+ Jim_Obj *evalObj[3];
2439
+
2440
+ evalObj[0] = Jim_NewStringObj(interp, "::popen", -1);
2441
+ evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1);
2442
+ evalObj[2] = Jim_NewStringObj(interp, mode, -1);
2443
+
2444
+ return Jim_EvalObjVector(interp, 3, evalObj);
2445
+ }
23542446
}
23552447
#endif
23562448
return JimMakeChannel(interp, NULL, -1, argv[1], "aio.handle%ld", 0, mode);
23572449
}
23582450
@@ -2359,70 +2451,129 @@
23592451
static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename,
23602452
const char *hdlfmt, int family, const char *mode)
23612453
{
23622454
AioFile *af;
23632455
char buf[AIO_CMD_LEN];
2364
- int OpenFlags = 0;
2456
+ int openFlags = 0;
23652457
2366
- if (filename == NULL) {
2458
+ if (fh) {
23672459
filename = Jim_NewStringObj(interp, hdlfmt, -1);
2460
+ openFlags = AIO_KEEPOPEN;
23682461
}
23692462
23702463
Jim_IncrRefCount(filename);
23712464
23722465
if (fh == NULL) {
2373
- if (fd < 0) {
2374
- fh = fopen(Jim_String(filename), mode);
2375
- }
2376
- else {
2466
+#if !defined(JIM_ANSIC)
2467
+ if (fd >= 0) {
23772468
fh = fdopen(fd, mode);
23782469
}
2379
- }
2380
- else {
2381
- OpenFlags = AIO_KEEPOPEN;
2382
- }
2470
+ else
2471
+#endif
2472
+ fh = fopen(Jim_String(filename), mode);
23832473
2384
- if (fh == NULL) {
2385
- JimAioSetError(interp, filename);
2474
+ if (fh == NULL) {
2475
+ JimAioSetError(interp, filename);
23862476
#if !defined(JIM_ANSIC)
2387
- if (fd >= 0) {
2388
- close(fd);
2477
+ if (fd >= 0) {
2478
+ close(fd);
2479
+ }
2480
+#endif
2481
+ Jim_DecrRefCount(interp, filename);
2482
+ return JIM_ERR;
23892483
}
2390
-#endif
2391
- Jim_DecrRefCount(interp, filename);
2392
- return JIM_ERR;
23932484
}
23942485
23952486
23962487
af = Jim_Alloc(sizeof(*af));
23972488
memset(af, 0, sizeof(*af));
23982489
af->fp = fh;
23992490
af->fd = fileno(fh);
24002491
af->filename = filename;
24012492
#ifdef FD_CLOEXEC
2402
- if ((OpenFlags & AIO_KEEPOPEN) == 0) {
2403
- fcntl(af->fd, F_SETFD, FD_CLOEXEC);
2493
+ if ((openFlags & AIO_KEEPOPEN) == 0) {
2494
+ (void)fcntl(af->fd, F_SETFD, FD_CLOEXEC);
24042495
}
24052496
#endif
2406
- af->OpenFlags = OpenFlags;
2407
-#ifdef O_NDELAY
2408
- af->flags = fcntl(af->fd, F_GETFL);
2409
-#endif
2497
+ af->openFlags = openFlags;
24102498
af->addr_family = family;
24112499
snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp));
24122500
Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);
24132501
2414
- Jim_SetResultString(interp, buf, -1);
2502
+ Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, Jim_NewStringObj(interp, buf, -1)));
24152503
24162504
return JIM_OK;
24172505
}
24182506
2507
+static int JimMakeChannelPair(Jim_Interp *interp, int p[2], Jim_Obj *filename,
2508
+ const char *hdlfmt, int family, const char *mode[2])
2509
+{
2510
+ if (JimMakeChannel(interp, NULL, p[0], filename, hdlfmt, family, mode[0]) == JIM_OK) {
2511
+ Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
2512
+ Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
2513
+
2514
+ if (JimMakeChannel(interp, NULL, p[1], filename, hdlfmt, family, mode[1]) == JIM_OK) {
2515
+ Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
2516
+ Jim_SetResult(interp, objPtr);
2517
+ return JIM_OK;
2518
+ }
2519
+ }
2520
+
2521
+
2522
+ close(p[0]);
2523
+ close(p[1]);
2524
+ JimAioSetError(interp, NULL);
2525
+ return JIM_ERR;
2526
+}
2527
+
2528
+
2529
+int Jim_MakeTempFile(Jim_Interp *interp, const char *template)
2530
+{
2531
+#ifdef HAVE_MKSTEMP
2532
+ int fd;
2533
+ mode_t mask;
2534
+ Jim_Obj *filenameObj;
2535
+
2536
+ if (template == NULL) {
2537
+ const char *tmpdir = getenv("TMPDIR");
2538
+ if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) {
2539
+ tmpdir = "/tmp/";
2540
+ }
2541
+ filenameObj = Jim_NewStringObj(interp, tmpdir, -1);
2542
+ if (tmpdir[0] && tmpdir[strlen(tmpdir) - 1] != '/') {
2543
+ Jim_AppendString(interp, filenameObj, "/", 1);
2544
+ }
2545
+ Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1);
2546
+ }
2547
+ else {
2548
+ filenameObj = Jim_NewStringObj(interp, template, -1);
2549
+ }
2550
+
2551
+ mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
2552
+
2553
+
2554
+ fd = mkstemp(filenameObj->bytes);
2555
+ umask(mask);
2556
+ if (fd < 0) {
2557
+ Jim_SetResultString(interp, "Failed to create tempfile", -1);
2558
+ Jim_FreeNewObj(interp, filenameObj);
2559
+ return -1;
2560
+ }
2561
+
2562
+ Jim_SetResult(interp, filenameObj);
2563
+ return fd;
2564
+#else
2565
+ Jim_SetResultString(interp, "tempfile not supported", -1);
2566
+ return -1;
2567
+#endif
2568
+}
24192569
24202570
FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command)
24212571
{
24222572
Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
24232573
2574
+
24242575
if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
24252576
return ((AioFile *) cmdPtr->u.native.privData)->fp;
24262577
}
24272578
Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command);
24282579
return NULL;
@@ -2443,11 +2594,10 @@
24432594
JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w");
24442595
JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w");
24452596
24462597
return JIM_OK;
24472598
}
2448
-
24492599
24502600
#include <errno.h>
24512601
#include <stdio.h>
24522602
#include <string.h>
24532603
@@ -2479,28 +2629,29 @@
24792629
return JIM_OK;
24802630
}
24812631
Jim_SetResultString(interp, strerror(errno), -1);
24822632
return JIM_ERR;
24832633
}
2484
- Jim_SetResultString(interp, strerror(errno), -1);
2485
-
2486
- Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
2487
-
2488
- while ((entryPtr = readdir(dirPtr)) != NULL) {
2489
- if (entryPtr->d_name[0] == '.') {
2490
- if (entryPtr->d_name[1] == '\0') {
2491
- continue;
2492
- }
2493
- if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0'))
2494
- continue;
2495
- }
2496
- Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp,
2497
- entryPtr->d_name, -1));
2498
- }
2499
- closedir(dirPtr);
2500
-
2501
- return JIM_OK;
2634
+ else {
2635
+ Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
2636
+
2637
+ while ((entryPtr = readdir(dirPtr)) != NULL) {
2638
+ if (entryPtr->d_name[0] == '.') {
2639
+ if (entryPtr->d_name[1] == '\0') {
2640
+ continue;
2641
+ }
2642
+ if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0'))
2643
+ continue;
2644
+ }
2645
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, entryPtr->d_name, -1));
2646
+ }
2647
+ closedir(dirPtr);
2648
+
2649
+ Jim_SetResult(interp, listObj);
2650
+
2651
+ return JIM_OK;
2652
+ }
25022653
}
25032654
25042655
int Jim_readdirInit(Jim_Interp *interp)
25052656
{
25062657
if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG))
@@ -2511,10 +2662,14 @@
25112662
}
25122663
25132664
#include <stdlib.h>
25142665
#include <string.h>
25152666
2667
+#if defined(JIM_REGEXP)
2668
+#else
2669
+ #include <regex.h>
2670
+#endif
25162671
25172672
static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
25182673
{
25192674
regfree(objPtr->internalRep.regexpValue.compre);
25202675
Jim_Free(objPtr->internalRep.regexpValue.compre);
@@ -3058,58 +3213,61 @@
30583213
}
30593214
#endif
30603215
return "unknown";
30613216
}
30623217
3063
-
3064
-static int set_array_int_value(Jim_Interp *interp, Jim_Obj *container, const char *key,
3065
- jim_wide value)
3066
-{
3067
- Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1);
3068
- Jim_Obj *valobj = Jim_NewWideObj(interp, value);
3069
-
3070
- if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) {
3071
- Jim_FreeObj(interp, nameobj);
3072
- Jim_FreeObj(interp, valobj);
3073
- return JIM_ERR;
3074
- }
3075
- return JIM_OK;
3076
-}
3077
-
3078
-static int set_array_string_value(Jim_Interp *interp, Jim_Obj *container, const char *key,
3079
- const char *value)
3080
-{
3081
- Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1);
3082
- Jim_Obj *valobj = Jim_NewStringObj(interp, value, -1);
3083
-
3084
- if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) {
3085
- Jim_FreeObj(interp, nameobj);
3086
- Jim_FreeObj(interp, valobj);
3087
- return JIM_ERR;
3088
- }
3089
- return JIM_OK;
3218
+static void AppendStatElement(Jim_Interp *interp, Jim_Obj *listObj, const char *key, jim_wide value)
3219
+{
3220
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, key, -1));
3221
+ Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value));
30903222
}
30913223
30923224
static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb)
30933225
{
3094
- if (set_array_int_value(interp, varName, "dev", sb->st_dev) != JIM_OK) {
3095
- Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName);
3096
- return JIM_ERR;
3097
- }
3098
- set_array_int_value(interp, varName, "ino", sb->st_ino);
3099
- set_array_int_value(interp, varName, "mode", sb->st_mode);
3100
- set_array_int_value(interp, varName, "nlink", sb->st_nlink);
3101
- set_array_int_value(interp, varName, "uid", sb->st_uid);
3102
- set_array_int_value(interp, varName, "gid", sb->st_gid);
3103
- set_array_int_value(interp, varName, "size", sb->st_size);
3104
- set_array_int_value(interp, varName, "atime", sb->st_atime);
3105
- set_array_int_value(interp, varName, "mtime", sb->st_mtime);
3106
- set_array_int_value(interp, varName, "ctime", sb->st_ctime);
3107
- set_array_string_value(interp, varName, "type", JimGetFileType((int)sb->st_mode));
3108
-
3109
-
3110
- Jim_SetResult(interp, Jim_GetVariable(interp, varName, 0));
3226
+
3227
+ Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
3228
+
3229
+ AppendStatElement(interp, listObj, "dev", sb->st_dev);
3230
+ AppendStatElement(interp, listObj, "ino", sb->st_ino);
3231
+ AppendStatElement(interp, listObj, "mode", sb->st_mode);
3232
+ AppendStatElement(interp, listObj, "nlink", sb->st_nlink);
3233
+ AppendStatElement(interp, listObj, "uid", sb->st_uid);
3234
+ AppendStatElement(interp, listObj, "gid", sb->st_gid);
3235
+ AppendStatElement(interp, listObj, "size", sb->st_size);
3236
+ AppendStatElement(interp, listObj, "atime", sb->st_atime);
3237
+ AppendStatElement(interp, listObj, "mtime", sb->st_mtime);
3238
+ AppendStatElement(interp, listObj, "ctime", sb->st_ctime);
3239
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1));
3240
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1));
3241
+
3242
+
3243
+ if (varName) {
3244
+ Jim_Obj *objPtr = Jim_GetVariable(interp, varName, JIM_NONE);
3245
+ if (objPtr) {
3246
+ if (Jim_DictSize(interp, objPtr) < 0) {
3247
+
3248
+ Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName);
3249
+ Jim_FreeNewObj(interp, listObj);
3250
+ return JIM_ERR;
3251
+ }
3252
+
3253
+ if (Jim_IsShared(objPtr))
3254
+ objPtr = Jim_DuplicateObj(interp, objPtr);
3255
+
3256
+
3257
+ Jim_ListAppendList(interp, objPtr, listObj);
3258
+ Jim_DictSize(interp, objPtr);
3259
+ Jim_InvalidateStringRep(objPtr);
3260
+
3261
+ Jim_FreeNewObj(interp, listObj);
3262
+ listObj = objPtr;
3263
+ }
3264
+ Jim_SetVariable(interp, varName, listObj);
3265
+ }
3266
+
3267
+
3268
+ Jim_SetResult(interp, listObj);
31113269
31123270
return JIM_OK;
31133271
}
31143272
31153273
static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -3264,14 +3422,11 @@
32643422
return JIM_OK;
32653423
}
32663424
32673425
static int file_access(Jim_Interp *interp, Jim_Obj *filename, int mode)
32683426
{
3269
- const char *path = Jim_String(filename);
3270
- int rc = access(path, mode);
3271
-
3272
- Jim_SetResultBool(interp, rc != -1);
3427
+ Jim_SetResultBool(interp, access(Jim_String(filename), mode) != -1);
32733428
32743429
return JIM_OK;
32753430
}
32763431
32773432
static int file_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -3287,10 +3442,11 @@
32873442
static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
32883443
{
32893444
#ifdef X_OK
32903445
return file_access(interp, argv[0], X_OK);
32913446
#else
3447
+
32923448
Jim_SetResultBool(interp, 1);
32933449
return JIM_OK;
32943450
#endif
32953451
}
32963452
@@ -3391,33 +3547,21 @@
33913547
argv++;
33923548
}
33933549
return JIM_OK;
33943550
}
33953551
3396
-#ifdef HAVE_MKSTEMP
33973552
static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
33983553
{
3399
- int fd;
3400
- char *filename;
3401
- const char *template = "/tmp/tcl.tmp.XXXXXX";
3402
-
3403
- if (argc >= 1) {
3404
- template = Jim_String(argv[0]);
3405
- }
3406
- filename = Jim_StrDup(template);
3407
-
3408
- fd = mkstemp(filename);
3409
- if (fd < 0) {
3410
- Jim_SetResultString(interp, "Failed to create tempfile", -1);
3554
+ int fd = Jim_MakeTempFile(interp, (argc >= 1) ? Jim_String(argv[0]) : NULL);
3555
+
3556
+ if (fd < 0) {
34113557
return JIM_ERR;
34123558
}
34133559
close(fd);
34143560
3415
- Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, filename, -1));
34163561
return JIM_OK;
34173562
}
3418
-#endif
34193563
34203564
static int file_cmd_rename(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
34213565
{
34223566
const char *source;
34233567
const char *dest;
@@ -3459,14 +3603,11 @@
34593603
return JIM_ERR;
34603604
}
34613605
return JIM_OK;
34623606
}
34633607
3464
-#ifndef HAVE_LSTAT
3465
-#define lstat stat
3466
-#endif
3467
-
3608
+#ifdef HAVE_LSTAT
34683609
static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb)
34693610
{
34703611
const char *path = Jim_String(filename);
34713612
34723613
if (lstat(path, sb) == -1) {
@@ -3473,10 +3614,13 @@
34733614
Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno));
34743615
return JIM_ERR;
34753616
}
34763617
return JIM_OK;
34773618
}
3619
+#else
3620
+#define file_lstat file_stat
3621
+#endif
34783622
34793623
static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
34803624
{
34813625
struct stat sb;
34823626
@@ -3601,28 +3745,32 @@
36013745
}
36023746
Jim_SetResultString(interp, JimGetFileType((int)sb.st_mode), -1);
36033747
return JIM_OK;
36043748
}
36053749
3750
+#ifdef HAVE_LSTAT
36063751
static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
36073752
{
36083753
struct stat sb;
36093754
36103755
if (file_lstat(interp, argv[0], &sb) != JIM_OK) {
36113756
return JIM_ERR;
36123757
}
3613
- return StoreStatData(interp, argv[1], &sb);
3758
+ return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
36143759
}
3760
+#else
3761
+#define file_cmd_lstat file_cmd_stat
3762
+#endif
36153763
36163764
static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
36173765
{
36183766
struct stat sb;
36193767
36203768
if (file_stat(interp, argv[0], &sb) != JIM_OK) {
36213769
return JIM_ERR;
36223770
}
3623
- return StoreStatData(interp, argv[1], &sb);
3771
+ return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
36243772
}
36253773
36263774
static const jim_subcmd_type file_command_table[] = {
36273775
{ "atime",
36283776
"name",
@@ -3727,19 +3875,17 @@
37273875
file_cmd_mkdir,
37283876
1,
37293877
-1,
37303878
37313879
},
3732
-#ifdef HAVE_MKSTEMP
37333880
{ "tempfile",
37343881
"?template?",
37353882
file_cmd_tempfile,
37363883
0,
37373884
1,
37383885
37393886
},
3740
-#endif
37413887
{ "rename",
37423888
"?-force? source dest",
37433889
file_cmd_rename,
37443890
2,
37453891
3,
@@ -3760,20 +3906,20 @@
37603906
1,
37613907
1,
37623908
37633909
},
37643910
{ "stat",
3765
- "name var",
3911
+ "name ?var?",
37663912
file_cmd_stat,
3767
- 2,
3913
+ 1,
37683914
2,
37693915
37703916
},
37713917
{ "lstat",
3772
- "name var",
3918
+ "name ?var?",
37733919
file_cmd_lstat,
3774
- 2,
3920
+ 1,
37753921
2,
37763922
37773923
},
37783924
{ "type",
37793925
"name",
@@ -3829,15 +3975,15 @@
38293975
return JIM_OK;
38303976
}
38313977
38323978
static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
38333979
{
3834
- const int cwd_len = 2048;
3835
- char *cwd = malloc(cwd_len);
3980
+ char *cwd = Jim_Alloc(MAXPATHLEN);
38363981
3837
- if (getcwd(cwd, cwd_len) == NULL) {
3982
+ if (getcwd(cwd, MAXPATHLEN) == NULL) {
38383983
Jim_SetResultString(interp, "Failed to get pwd", -1);
3984
+ Jim_Free(cwd);
38393985
return JIM_ERR;
38403986
}
38413987
#if defined(__MINGW32__) || defined(_MSC_VER)
38423988
{
38433989
@@ -3848,11 +3994,11 @@
38483994
}
38493995
#endif
38503996
38513997
Jim_SetResultString(interp, cwd, -1);
38523998
3853
- free(cwd);
3999
+ Jim_Free(cwd);
38544000
return JIM_OK;
38554001
}
38564002
38574003
int Jim_fileInit(Jim_Interp *interp)
38584004
{
@@ -3917,10 +4063,11 @@
39174063
39184064
int Jim_execInit(Jim_Interp *interp)
39194065
{
39204066
if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
39214067
return JIM_ERR;
4068
+
39224069
Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL);
39234070
return JIM_OK;
39244071
}
39254072
#else
39264073
@@ -3960,10 +4107,11 @@
39604107
static int JimErrno(void);
39614108
#else
39624109
#include <unistd.h>
39634110
#include <fcntl.h>
39644111
#include <sys/wait.h>
4112
+ #include <sys/stat.h>
39654113
39664114
typedef int fdtype;
39674115
typedef int pidtype;
39684116
#define JimPipe pipe
39694117
#define JimErrno() errno
@@ -4034,23 +4182,12 @@
40344182
Jim_RemoveTrailingNewline(strObj);
40354183
fclose(fh);
40364184
return JIM_OK;
40374185
}
40384186
4039
-static void JimTrimTrailingNewline(Jim_Interp *interp)
4040
-{
4041
- int len;
4042
- const char *p = Jim_GetString(Jim_GetResult(interp), &len);
4043
-
4044
- if (len > 0 && p[len - 1] == '\n') {
4045
- Jim_SetResultString(interp, p, len - 1);
4046
- }
4047
-}
4048
-
40494187
static char **JimBuildEnv(Jim_Interp *interp)
40504188
{
4051
-#if defined(jim_ext_tclcompat)
40524189
int i;
40534190
int size;
40544191
int num;
40554192
int n;
40564193
char **envptr;
@@ -4064,10 +4201,11 @@
40644201
40654202
40664203
40674204
num = Jim_ListLength(interp, objPtr);
40684205
if (num % 2) {
4206
+
40694207
num--;
40704208
}
40714209
size = Jim_Length(objPtr) + 2;
40724210
40734211
envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size);
@@ -4090,22 +4228,17 @@
40904228
}
40914229
envptr[n] = NULL;
40924230
*envdata = 0;
40934231
40944232
return envptr;
4095
-#else
4096
- return Jim_GetEnviron();
4097
-#endif
40984233
}
40994234
41004235
static void JimFreeEnv(char **env, char **original_environ)
41014236
{
4102
-#ifdef jim_ext_tclcompat
41034237
if (env != original_environ) {
41044238
Jim_Free(env);
41054239
}
4106
-#endif
41074240
}
41084241
41094242
static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus)
41104243
{
41114244
Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0);
@@ -4154,19 +4287,19 @@
41544287
}
41554288
41564289
41574290
struct WaitInfo
41584291
{
4159
- pidtype pid;
4292
+ pidtype pid;
41604293
int status;
41614294
int flags;
41624295
};
41634296
41644297
struct WaitInfoTable {
4165
- struct WaitInfo *info;
4166
- int size;
4167
- int used;
4298
+ struct WaitInfo *info;
4299
+ int size;
4300
+ int used;
41684301
};
41694302
41704303
41714304
#define WI_DETACHED 2
41724305
@@ -4189,14 +4322,12 @@
41894322
return table;
41904323
}
41914324
41924325
static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
41934326
{
4194
- fdtype outputId; /* File id for output pipe. -1
4195
- * means command overrode. */
4196
- fdtype errorId; /* File id for temporary file
4197
- * containing error output. */
4327
+ fdtype outputId;
4328
+ fdtype errorId;
41984329
pidtype *pidPtr;
41994330
int numPids, result;
42004331
42014332
if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) {
42024333
Jim_Obj *listObj;
@@ -4243,26 +4374,32 @@
42434374
42444375
static void JimReapDetachedPids(struct WaitInfoTable *table)
42454376
{
42464377
struct WaitInfo *waitPtr;
42474378
int count;
4379
+ int dest;
42484380
42494381
if (!table) {
42504382
return;
42514383
}
42524384
4253
- for (waitPtr = table->info, count = table->used; count > 0; waitPtr++, count--) {
4385
+ waitPtr = table->info;
4386
+ dest = 0;
4387
+ for (count = table->used; count > 0; waitPtr++, count--) {
42544388
if (waitPtr->flags & WI_DETACHED) {
42554389
int status;
42564390
pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG);
4257
- if (pid != JIM_BAD_PID) {
4258
- if (waitPtr != &table->info[table->used - 1]) {
4259
- *waitPtr = table->info[table->used - 1];
4260
- }
4391
+ if (pid == waitPtr->pid) {
4392
+
42614393
table->used--;
4394
+ continue;
42624395
}
42634396
}
4397
+ if (waitPtr != &table->info[dest]) {
4398
+ table->info[dest] = *waitPtr;
4399
+ }
4400
+ dest++;
42644401
}
42654402
}
42664403
42674404
static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr)
42684405
{
@@ -4284,11 +4421,10 @@
42844421
}
42854422
42864423
42874424
return JIM_BAD_PID;
42884425
}
4289
-
42904426
42914427
static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr)
42924428
{
42934429
int j;
42944430
struct WaitInfoTable *table = Jim_CmdPrivData(interp);
@@ -4609,27 +4745,23 @@
46094745
}
46104746
outputId = pipeIds[1];
46114747
}
46124748
46134749
4750
+ if (pipe_dup_err) {
4751
+ errorId = outputId;
4752
+ }
4753
+
4754
+
46144755
46154756
#ifdef __MINGW32__
46164757
pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId);
46174758
if (pid == JIM_BAD_PID) {
46184759
Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]);
46194760
goto error;
46204761
}
46214762
#else
4622
- if (table->info == NULL) {
4623
- (void)signal(SIGPIPE, SIG_IGN);
4624
- }
4625
-
4626
-
4627
- if (pipe_dup_err) {
4628
- errorId = outputId;
4629
- }
4630
-
46314763
pid = vfork();
46324764
if (pid < 0) {
46334765
Jim_SetResultErrno(interp, "couldn't fork child process");
46344766
goto error;
46354767
}
@@ -4642,14 +4774,17 @@
46424774
46434775
for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) {
46444776
close(i);
46454777
}
46464778
4779
+
4780
+ (void)signal(SIGPIPE, SIG_DFL);
4781
+
46474782
execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron());
46484783
46494784
4650
- fprintf(stderr, "couldn't exec \"%s\"", arg_array[firstArg]);
4785
+ fprintf(stderr, "couldn't exec \"%s\"\n", arg_array[firstArg]);
46514786
_exit(127);
46524787
}
46534788
#endif
46544789
46554790
@@ -4751,19 +4886,24 @@
47514886
if (JimAppendStreamToString(interp, errorId, Jim_GetResult(interp)) != JIM_OK) {
47524887
result = JIM_ERR;
47534888
}
47544889
}
47554890
4756
- JimTrimTrailingNewline(interp);
4891
+ Jim_RemoveTrailingNewline(Jim_GetResult(interp));
47574892
47584893
return result;
47594894
}
47604895
47614896
int Jim_execInit(Jim_Interp *interp)
47624897
{
47634898
if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
47644899
return JIM_ERR;
4900
+
4901
+#ifdef SIGPIPE
4902
+ (void)signal(SIGPIPE, SIG_IGN);
4903
+#endif
4904
+
47654905
Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable);
47664906
return JIM_OK;
47674907
}
47684908
47694909
#if defined(__MINGW32__)
@@ -5088,28 +5228,26 @@
50885228
{
50895229
STARTUPINFO startInfo;
50905230
PROCESS_INFORMATION procInfo;
50915231
HANDLE hProcess, h;
50925232
char execPath[MAX_PATH];
5093
- char *originalName;
50945233
pidtype pid = JIM_BAD_PID;
50955234
Jim_Obj *cmdLineObj;
50965235
50975236
if (JimWinFindExecutable(argv[0], execPath) < 0) {
50985237
return JIM_BAD_PID;
50995238
}
5100
- originalName = argv[0];
51015239
argv[0] = execPath;
51025240
51035241
hProcess = GetCurrentProcess();
51045242
cmdLineObj = JimWinBuildCommandLine(interp, argv);
51055243
51065244
51075245
ZeroMemory(&startInfo, sizeof(startInfo));
51085246
startInfo.cb = sizeof(startInfo);
51095247
startInfo.dwFlags = STARTF_USESTDHANDLES;
5110
- startInfo.hStdInput = INVALID_HANDLE_VALUE;
5248
+ startInfo.hStdInput = INVALID_HANDLE_VALUE;
51115249
startInfo.hStdOutput= INVALID_HANDLE_VALUE;
51125250
startInfo.hStdError = INVALID_HANDLE_VALUE;
51135251
51145252
if (inputId == JIM_BAD_FD) {
51155253
if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) {
@@ -5182,18 +5320,17 @@
51825320
return lseek(fd, 0L, SEEK_SET);
51835321
}
51845322
51855323
static int JimCreateTemp(Jim_Interp *interp, const char *contents, int len)
51865324
{
5187
- char inName[] = "/tmp/tcl.tmp.XXXXXX";
5325
+ int fd = Jim_MakeTempFile(interp, NULL);
51885326
5189
- int fd = mkstemp(inName);
51905327
if (fd == JIM_BAD_FD) {
51915328
Jim_SetResultErrno(interp, "couldn't create temp file");
51925329
return -1;
51935330
}
5194
- unlink(inName);
5331
+ unlink(Jim_String(Jim_GetResult(interp)));
51955332
if (contents) {
51965333
if (write(fd, contents, len) != len) {
51975334
Jim_SetResultErrno(interp, "couldn't write temp file");
51985335
close(fd);
51995336
return -1;
@@ -5217,11 +5354,10 @@
52175354
}
52185355
#endif
52195356
#endif
52205357
52215358
5222
-
52235359
#ifndef _XOPEN_SOURCE
52245360
#define _XOPEN_SOURCE 500
52255361
#endif
52265362
52275363
#include <stdlib.h>
@@ -5239,11 +5375,11 @@
52395375
52405376
char buf[100];
52415377
time_t t;
52425378
long seconds;
52435379
5244
- const char *format = "%a %b %d %H:%M:%S %Z %Y";
5380
+ const char *format = "%a %b %d %H:%M:%S %Z %Y";
52455381
52465382
if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) {
52475383
return -1;
52485384
}
52495385
@@ -5254,11 +5390,14 @@
52545390
if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) {
52555391
return JIM_ERR;
52565392
}
52575393
t = seconds;
52585394
5259
- strftime(buf, sizeof(buf), format, localtime(&t));
5395
+ if (strftime(buf, sizeof(buf), format, localtime(&t)) == 0) {
5396
+ Jim_SetResultString(interp, "format string too long", -1);
5397
+ return JIM_ERR;
5398
+ }
52605399
52615400
Jim_SetResultString(interp, buf, -1);
52625401
52635402
return JIM_OK;
52645403
}
@@ -5374,11 +5513,10 @@
53745513
53755514
Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL);
53765515
return JIM_OK;
53775516
}
53785517
5379
-
53805518
#include <limits.h>
53815519
#include <stdlib.h>
53825520
#include <string.h>
53835521
#include <stdio.h>
53845522
#include <errno.h>
@@ -5392,33 +5530,29 @@
53925530
}
53935531
53945532
static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
53955533
{
53965534
Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5535
+ Jim_Obj *patternObj;
53975536
53985537
if (!objPtr) {
53995538
return JIM_OK;
54005539
}
54015540
5402
- if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
5403
-
5404
- if (Jim_IsList(objPtr)) {
5405
- if (Jim_ListLength(interp, objPtr) % 2 != 0) {
5406
-
5407
- return JIM_ERR;
5408
- }
5409
- }
5410
- else if (Jim_DictSize(interp, objPtr) < 0) {
5411
-
5412
- return JIM_ERR;
5413
- }
5414
- Jim_SetResult(interp, objPtr);
5415
- return JIM_OK;
5541
+ patternObj = (argc == 1) ? NULL : argv[1];
5542
+
5543
+
5544
+ if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) {
5545
+ if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) {
5546
+
5547
+ Jim_SetResult(interp, objPtr);
5548
+ return JIM_OK;
5549
+ }
54165550
}
54175551
54185552
5419
- return Jim_DictValues(interp, objPtr, argv[1]);
5553
+ return Jim_DictValues(interp, objPtr, patternObj);
54205554
}
54215555
54225556
static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
54235557
{
54245558
Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
@@ -5443,10 +5577,15 @@
54435577
Jim_UnsetVariable(interp, argv[0], JIM_NONE);
54445578
return JIM_OK;
54455579
}
54465580
54475581
objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5582
+
5583
+ if (objPtr == NULL) {
5584
+
5585
+ return JIM_OK;
5586
+ }
54485587
54495588
if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
54505589
return JIM_ERR;
54515590
}
54525591
@@ -5480,10 +5619,20 @@
54805619
54815620
Jim_SetResultInt(interp, len);
54825621
54835622
return JIM_OK;
54845623
}
5624
+
5625
+static int array_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5626
+{
5627
+ Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5628
+ if (objPtr) {
5629
+ return Jim_DictInfo(interp, objPtr);
5630
+ }
5631
+ Jim_SetResultFormatted(interp, "\"%#s\" isn't an array", argv[0], NULL);
5632
+ return JIM_ERR;
5633
+}
54855634
54865635
static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
54875636
{
54885637
int i;
54895638
int len;
@@ -5498,10 +5647,13 @@
54985647
54995648
dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
55005649
if (!dictObj) {
55015650
55025651
return Jim_SetVariable(interp, argv[0], listObj);
5652
+ }
5653
+ else if (Jim_DictSize(interp, dictObj) < 0) {
5654
+ return JIM_ERR;
55035655
}
55045656
55055657
if (Jim_IsShared(dictObj)) {
55065658
dictObj = Jim_DuplicateObj(interp, dictObj);
55075659
}
@@ -5551,10 +5703,17 @@
55515703
"arrayName",
55525704
array_cmd_size,
55535705
1,
55545706
1,
55555707
5708
+ },
5709
+ { "stat",
5710
+ "arrayName",
5711
+ array_cmd_stat,
5712
+ 1,
5713
+ 1,
5714
+
55565715
},
55575716
{ "unset",
55585717
"arrayName ?pattern?",
55595718
array_cmd_unset,
55605719
1,
@@ -5597,11 +5756,10 @@
55975756
Jim_arrayInit(interp);
55985757
Jim_stdlibInit(interp);
55995758
Jim_tclcompatInit(interp);
56005759
return JIM_OK;
56015760
}
5602
-
56035761
#define JIM_OPTIMIZATION
56045762
56055763
#include <stdio.h>
56065764
#include <stdlib.h>
56075765
@@ -5661,21 +5819,20 @@
56615819
#define JIM_INTEGER_SPACE 24
56625820
56635821
const char *jim_tt_name(int type);
56645822
56655823
#ifdef JIM_DEBUG_PANIC
5666
-static void JimPanicDump(int panic_condition, const char *fmt, ...);
5824
+static void JimPanicDump(int fail_condition, const char *fmt, ...);
56675825
#define JimPanic(X) JimPanicDump X
56685826
#else
56695827
#define JimPanic(X)
56705828
#endif
56715829
56725830
56735831
static char JimEmptyStringRep[] = "";
56745832
5675
-static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf);
5676
-static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags);
5833
+static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action);
56775834
static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
56785835
int flags);
56795836
static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands);
56805837
static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr);
56815838
static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
@@ -5922,44 +6079,10 @@
59226079
}
59236080
return n;
59246081
}
59256082
#endif
59266083
5927
-static int JimWideToString(char *buf, jim_wide wideValue)
5928
-{
5929
- int pos = 0;
5930
-
5931
- if (wideValue == 0) {
5932
- buf[pos++] = '0';
5933
- }
5934
- else {
5935
- char tmp[JIM_INTEGER_SPACE];
5936
- int num = 0;
5937
- int i;
5938
-
5939
- if (wideValue < 0) {
5940
- buf[pos++] = '-';
5941
-
5942
- i = wideValue % 10;
5943
- tmp[num++] = (i > 0) ? (10 - i) : -i;
5944
- wideValue /= -10;
5945
- }
5946
-
5947
- while (wideValue) {
5948
- tmp[num++] = wideValue % 10;
5949
- wideValue /= 10;
5950
- }
5951
-
5952
- for (i = 0; i < num; i++) {
5953
- buf[pos++] = '0' + tmp[num - i - 1];
5954
- }
5955
- }
5956
- buf[pos] = 0;
5957
-
5958
- return pos;
5959
-}
5960
-
59616084
static int JimCheckConversion(const char *str, const char *endptr)
59626085
{
59636086
if (str[0] == '\0' || str == endptr) {
59646087
return JIM_ERR;
59656088
}
@@ -6070,48 +6193,10 @@
60706193
}
60716194
60726195
return JimCheckConversion(str, endptr);
60736196
}
60746197
6075
-int Jim_DoubleToString(char *buf, double doubleValue)
6076
-{
6077
- int len;
6078
- int i;
6079
-
6080
- len = sprintf(buf, "%.12g", doubleValue);
6081
-
6082
-
6083
- for (i = 0; i < len; i++) {
6084
- if (buf[i] == '.' || buf[i] == 'e') {
6085
-#if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
6086
- char *e = strchr(buf, 'e');
6087
- if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
6088
-
6089
- e += 2;
6090
- memmove(e, e + 1, len - (e - buf));
6091
- return len - 1;
6092
- }
6093
-#endif
6094
- return len;
6095
- }
6096
-
6097
- if (buf[i] == 'i' || buf[i] == 'I' || buf[i] == 'n' || buf[i] == 'N') {
6098
- buf[i] = toupper(UCHAR(buf[i]));
6099
- if (buf[i] == 'n' || buf[i] == 'N')
6100
- buf[i+2] = toupper(UCHAR(buf[i+2]));
6101
- buf[i + 3] = 0;
6102
- return i + 3;
6103
- }
6104
- }
6105
-
6106
- buf[i++] = '.';
6107
- buf[i++] = '0';
6108
- buf[i] = '\0';
6109
-
6110
- return i;
6111
-}
6112
-
61136198
int Jim_StringToDouble(const char *str, double *doublePtr)
61146199
{
61156200
char *endptr;
61166201
61176202
@@ -6133,23 +6218,23 @@
61336218
}
61346219
return res;
61356220
}
61366221
61376222
#ifdef JIM_DEBUG_PANIC
6138
-void JimPanicDump(int condition, const char *fmt, ...)
6223
+static void JimPanicDump(int condition, const char *fmt, ...)
61396224
{
61406225
va_list ap;
61416226
61426227
if (!condition) {
61436228
return;
61446229
}
61456230
61466231
va_start(ap, fmt);
61476232
6148
- fprintf(stderr, JIM_NL "JIM INTERPRETER PANIC: ");
6233
+ fprintf(stderr, "\nJIM INTERPRETER PANIC: ");
61496234
vfprintf(stderr, fmt, ap);
6150
- fprintf(stderr, JIM_NL JIM_NL);
6235
+ fprintf(stderr, "\n\n");
61516236
va_end(ap);
61526237
61536238
#ifdef HAVE_BACKTRACE
61546239
{
61556240
void *array[40];
@@ -6157,13 +6242,13 @@
61576242
char **strings;
61586243
61596244
size = backtrace(array, 40);
61606245
strings = backtrace_symbols(array, size);
61616246
for (i = 0; i < size; i++)
6162
- fprintf(stderr, "[backtrace] %s" JIM_NL, strings[i]);
6163
- fprintf(stderr, "[backtrace] Include the above lines and the output" JIM_NL);
6164
- fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report." JIM_NL);
6247
+ fprintf(stderr, "[backtrace] %s\n", strings[i]);
6248
+ fprintf(stderr, "[backtrace] Include the above lines and the output\n");
6249
+ fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report.\n");
61656250
}
61666251
#endif
61676252
61686253
exit(1);
61696254
}
@@ -6237,18 +6322,24 @@
62376322
h += (h << 3) + *buf++;
62386323
return h;
62396324
}
62406325
62416326
6327
+
62426328
62436329
static void JimResetHashTable(Jim_HashTable *ht)
62446330
{
62456331
ht->table = NULL;
62466332
ht->size = 0;
62476333
ht->sizemask = 0;
62486334
ht->used = 0;
62496335
ht->collisions = 0;
6336
+#ifdef JIM_RANDOMISE_HASH
6337
+ ht->uniq = (rand() ^ time(NULL) ^ clock());
6338
+#else
6339
+ ht->uniq = 0;
6340
+#endif
62506341
}
62516342
62526343
static void JimInitHashTableIterator(Jim_HashTable *ht, Jim_HashTableIterator *iter)
62536344
{
62546345
iter->ht = ht;
@@ -6286,10 +6377,12 @@
62866377
62876378
Jim_InitHashTable(&n, ht->type, ht->privdata);
62886379
n.size = realsize;
62896380
n.sizemask = realsize - 1;
62906381
n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *));
6382
+
6383
+ n.uniq = ht->uniq;
62916384
62926385
62936386
memset(n.table, 0, realsize * sizeof(Jim_HashEntry *));
62946387
62956388
n.used = ht->used;
@@ -6342,20 +6435,27 @@
63426435
int existed;
63436436
Jim_HashEntry *entry;
63446437
63456438
entry = JimInsertHashEntry(ht, key, 1);
63466439
if (entry->key) {
6347
-
6348
- Jim_FreeEntryVal(ht, entry);
6440
+ if (ht->type->valDestructor && ht->type->valDup) {
6441
+ void *newval = ht->type->valDup(ht->privdata, val);
6442
+ ht->type->valDestructor(ht->privdata, entry->u.val);
6443
+ entry->u.val = newval;
6444
+ }
6445
+ else {
6446
+ Jim_FreeEntryVal(ht, entry);
6447
+ Jim_SetHashVal(ht, entry, val);
6448
+ }
63496449
existed = 1;
63506450
}
63516451
else {
63526452
63536453
Jim_SetHashKey(ht, entry, key);
6454
+ Jim_SetHashVal(ht, entry, val);
63546455
existed = 0;
63556456
}
6356
- Jim_SetHashVal(ht, entry, val);
63576457
63586458
return existed;
63596459
}
63606460
63616461
@@ -6520,11 +6620,11 @@
65206620
return Jim_GenHashFunction(key, strlen(key));
65216621
}
65226622
65236623
static void *JimStringCopyHTDup(void *privdata, const void *key)
65246624
{
6525
- return strdup(key);
6625
+ return Jim_StrDup(key);
65266626
}
65276627
65286628
static int JimStringCopyHTKeyCompare(void *privdata, const void *key1, const void *key2)
65296629
{
65306630
return strcmp(key1, key2) == 0;
@@ -6620,11 +6720,11 @@
66206720
freeFunc(stack->vector[i]);
66216721
}
66226722
66236723
66246724
6625
-#define JIM_TT_NONE 0
6725
+#define JIM_TT_NONE 0
66266726
#define JIM_TT_STR 1
66276727
#define JIM_TT_ESC 2
66286728
#define JIM_TT_VAR 3
66296729
#define JIM_TT_DICTSUGAR 4
66306730
#define JIM_TT_CMD 5
@@ -6652,10 +6752,15 @@
66526752
66536753
66546754
#define JIM_PS_DEF 0
66556755
#define JIM_PS_QUOTE 1
66566756
#define JIM_PS_DICTSUGAR 2
6757
+
6758
+struct JimParseMissing {
6759
+ int ch;
6760
+ int line;
6761
+};
66576762
66586763
struct JimParserCtx
66596764
{
66606765
const char *p;
66616766
int len;
@@ -6665,17 +6770,11 @@
66656770
int tline;
66666771
int tt;
66676772
int eof;
66686773
int state;
66696774
int comment;
6670
- char missing;
6671
- int missingline;
6672
-};
6673
-
6674
-struct JimParseResult {
6675
- char missing;
6676
- int line;
6775
+ struct JimParseMissing missing;
66776776
};
66786777
66796778
static int JimParseScript(struct JimParserCtx *pc);
66806779
static int JimParseSep(struct JimParserCtx *pc);
66816780
static int JimParseEol(struct JimParserCtx *pc);
@@ -6685,11 +6784,10 @@
66856784
static int JimParseBrace(struct JimParserCtx *pc);
66866785
static int JimParseStr(struct JimParserCtx *pc);
66876786
static int JimParseComment(struct JimParserCtx *pc);
66886787
static void JimParseSubCmd(struct JimParserCtx *pc);
66896788
static int JimParseSubQuote(struct JimParserCtx *pc);
6690
-static void JimParseSubCmd(struct JimParserCtx *pc);
66916789
static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc);
66926790
66936791
static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int linenr)
66946792
{
66956793
pc->p = prg;
@@ -6700,12 +6798,12 @@
67006798
pc->tt = JIM_TT_NONE;
67016799
pc->eof = 0;
67026800
pc->state = JIM_PS_DEF;
67036801
pc->linenr = linenr;
67046802
pc->comment = 1;
6705
- pc->missing = ' ';
6706
- pc->missingline = linenr;
6803
+ pc->missing.ch = ' ';
6804
+ pc->missing.line = linenr;
67076805
}
67086806
67096807
static int JimParseScript(struct JimParserCtx *pc)
67106808
{
67116809
while (1) {
@@ -6837,12 +6935,12 @@
68376935
break;
68386936
}
68396937
pc->p++;
68406938
pc->len--;
68416939
}
6842
- pc->missing = '{';
6843
- pc->missingline = pc->tline;
6940
+ pc->missing.ch = '{';
6941
+ pc->missing.line = pc->tline;
68446942
pc->tend = pc->p - 1;
68456943
}
68466944
68476945
static int JimParseSubQuote(struct JimParserCtx *pc)
68486946
{
@@ -6884,12 +6982,12 @@
68846982
break;
68856983
}
68866984
pc->p++;
68876985
pc->len--;
68886986
}
6889
- pc->missing = '"';
6890
- pc->missingline = line;
6987
+ pc->missing.ch = '"';
6988
+ pc->missing.line = line;
68916989
pc->tend = pc->p - 1;
68926990
return tt;
68936991
}
68946992
68956993
static void JimParseSubCmd(struct JimParserCtx *pc)
@@ -6943,12 +7041,12 @@
69437041
}
69447042
startofword = isspace(UCHAR(*pc->p));
69457043
pc->p++;
69467044
pc->len--;
69477045
}
6948
- pc->missing = '[';
6949
- pc->missingline = line;
7046
+ pc->missing.ch = '[';
7047
+ pc->missing.line = line;
69507048
pc->tend = pc->p - 1;
69517049
}
69527050
69537051
static int JimParseBrace(struct JimParserCtx *pc)
69547052
{
@@ -7088,19 +7186,19 @@
70887186
if (*pc->p == '"') {
70897187
pc->state = JIM_PS_QUOTE;
70907188
pc->p++;
70917189
pc->len--;
70927190
7093
- pc->missingline = pc->tline;
7191
+ pc->missing.line = pc->tline;
70947192
}
70957193
}
70967194
pc->tstart = pc->p;
70977195
pc->tline = pc->linenr;
70987196
while (1) {
70997197
if (pc->len == 0) {
71007198
if (pc->state == JIM_PS_QUOTE) {
7101
- pc->missing = '"';
7199
+ pc->missing.ch = '"';
71027200
}
71037201
pc->tend = pc->p - 1;
71047202
pc->tt = JIM_TT_ESC;
71057203
return JIM_OK;
71067204
}
@@ -7116,10 +7214,14 @@
71167214
pc->linenr++;
71177215
}
71187216
pc->p++;
71197217
pc->len--;
71207218
}
7219
+ else if (pc->len == 1) {
7220
+
7221
+ pc->missing.ch = '\\';
7222
+ }
71217223
break;
71227224
case '(':
71237225
71247226
if (pc->len > 1 && pc->p[1] != '$') {
71257227
break;
@@ -7176,17 +7278,26 @@
71767278
}
71777279
71787280
static int JimParseComment(struct JimParserCtx *pc)
71797281
{
71807282
while (*pc->p) {
7181
- if (*pc->p == '\n') {
7283
+ if (*pc->p == '\\') {
7284
+ pc->p++;
7285
+ pc->len--;
7286
+ if (pc->len == 0) {
7287
+ pc->missing.ch = '\\';
7288
+ return JIM_OK;
7289
+ }
7290
+ if (*pc->p == '\n') {
7291
+ pc->linenr++;
7292
+ }
7293
+ }
7294
+ else if (*pc->p == '\n') {
7295
+ pc->p++;
7296
+ pc->len--;
71827297
pc->linenr++;
7183
- if (*(pc->p - 1) != '\\') {
7184
- pc->p++;
7185
- pc->len--;
7186
- return JIM_OK;
7187
- }
7298
+ break;
71887299
}
71897300
pc->p++;
71907301
pc->len--;
71917302
}
71927303
return JIM_OK;
@@ -7404,13 +7515,13 @@
74047515
JimParserInit(&parser, s, len, 1);
74057516
while (!parser.eof) {
74067517
JimParseScript(&parser);
74077518
}
74087519
if (stateCharPtr) {
7409
- *stateCharPtr = parser.missing;
7520
+ *stateCharPtr = parser.missing.ch;
74107521
}
7411
- return parser.missing == ' ';
7522
+ return parser.missing.ch == ' ';
74127523
}
74137524
74147525
static int JimParseListSep(struct JimParserCtx *pc);
74157526
static int JimParseListStr(struct JimParserCtx *pc);
74167527
static int JimParseListQuote(struct JimParserCtx *pc);
@@ -7662,10 +7773,16 @@
76627773
JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
76637774
objPtr->typePtr->updateStringProc(objPtr);
76647775
}
76657776
return objPtr->bytes;
76667777
}
7778
+
7779
+static void JimSetStringBytes(Jim_Obj *objPtr, const char *str)
7780
+{
7781
+ objPtr->bytes = Jim_StrDup(str);
7782
+ objPtr->length = strlen(str);
7783
+}
76677784
76687785
static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
76697786
static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
76707787
76717788
static const Jim_ObjType dictSubstObjType = {
@@ -7703,11 +7820,10 @@
77037820
static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
77047821
{
77057822
JIM_NOTUSED(interp);
77067823
77077824
dupPtr->internalRep.strValue.maxLength = srcPtr->length;
7708
-
77097825
dupPtr->internalRep.strValue.charLength = srcPtr->internalRep.strValue.charLength;
77107826
}
77117827
77127828
static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
77137829
{
@@ -7752,18 +7868,17 @@
77527868
if (len == -1)
77537869
len = strlen(s);
77547870
77557871
if (len == 0) {
77567872
objPtr->bytes = JimEmptyStringRep;
7757
- objPtr->length = 0;
77587873
}
77597874
else {
77607875
objPtr->bytes = Jim_Alloc(len + 1);
7761
- objPtr->length = len;
77627876
memcpy(objPtr->bytes, s, len);
77637877
objPtr->bytes[len] = '\0';
77647878
}
7879
+ objPtr->length = len;
77657880
77667881
77677882
objPtr->typePtr = NULL;
77687883
return objPtr;
77697884
}
@@ -7791,11 +7906,11 @@
77917906
Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len)
77927907
{
77937908
Jim_Obj *objPtr = Jim_NewObj(interp);
77947909
77957910
objPtr->bytes = s;
7796
- objPtr->length = len == -1 ? strlen(s) : len;
7911
+ objPtr->length = (len == -1) ? strlen(s) : len;
77977912
objPtr->typePtr = NULL;
77987913
return objPtr;
77997914
}
78007915
78017916
static void StringAppendString(Jim_Obj *objPtr, const char *str, int len)
@@ -7820,17 +7935,17 @@
78207935
}
78217936
objPtr->internalRep.strValue.maxLength = needlen;
78227937
}
78237938
memcpy(objPtr->bytes + objPtr->length, str, len);
78247939
objPtr->bytes[objPtr->length + len] = '\0';
7940
+
78257941
if (objPtr->internalRep.strValue.charLength >= 0) {
78267942
78277943
objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len);
78287944
}
78297945
objPtr->length += len;
78307946
}
7831
-
78327947
78337948
void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len)
78347949
{
78357950
JimPanic((Jim_IsShared(objPtr), "Jim_AppendString called with shared object"));
78367951
SetStringFromAny(interp, objPtr);
@@ -7838,13 +7953,11 @@
78387953
}
78397954
78407955
void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr)
78417956
{
78427957
int len;
7843
- const char *str;
7844
-
7845
- str = Jim_GetString(appendObjPtr, &len);
7958
+ const char *str = Jim_GetString(appendObjPtr, &len);
78467959
Jim_AppendString(interp, objPtr, str, len);
78477960
}
78487961
78497962
void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...)
78507963
{
@@ -7851,11 +7964,11 @@
78517964
va_list ap;
78527965
78537966
SetStringFromAny(interp, objPtr);
78547967
va_start(ap, objPtr);
78557968
while (1) {
7856
- char *s = va_arg(ap, char *);
7969
+ const char *s = va_arg(ap, const char *);
78577970
78587971
if (s == NULL)
78597972
break;
78607973
Jim_AppendString(interp, objPtr, s, -1);
78617974
}
@@ -7862,20 +7975,20 @@
78627975
va_end(ap);
78637976
}
78647977
78657978
int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr)
78667979
{
7867
- const char *aStr, *bStr;
7868
- int aLen, bLen;
7869
-
7870
- if (aObjPtr == bObjPtr)
7980
+ if (aObjPtr == bObjPtr) {
78717981
return 1;
7872
- aStr = Jim_GetString(aObjPtr, &aLen);
7873
- bStr = Jim_GetString(bObjPtr, &bLen);
7874
- if (aLen != bLen)
7875
- return 0;
7876
- return JimStringCompare(aStr, aLen, bStr, bLen) == 0;
7982
+ }
7983
+ else {
7984
+ int Alen, Blen;
7985
+ const char *sA = Jim_GetString(aObjPtr, &Alen);
7986
+ const char *sB = Jim_GetString(bObjPtr, &Blen);
7987
+
7988
+ return Alen == Blen && memcmp(sA, sB, Alen) == 0;
7989
+ }
78777990
}
78787991
78797992
int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase)
78807993
{
78817994
return JimGlobMatch(Jim_String(patternObjPtr), Jim_String(objPtr), nocase);
@@ -8036,11 +8149,11 @@
80368149
static void JimStrCopyUpperLower(char *dest, const char *str, int uc)
80378150
{
80388151
while (*str) {
80398152
int c;
80408153
str += utf8_tounicode(str, &c);
8041
- dest += utf8_fromunicode(dest, uc ? utf8_upper(c) : utf8_lower(c));
8154
+ dest += utf8_getchars(dest, uc ? utf8_upper(c) : utf8_lower(c));
80428155
}
80438156
*dest = 0;
80448157
}
80458158
80468159
static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr)
@@ -8096,11 +8209,11 @@
80968209
len *= 2;
80978210
#endif
80988211
buf = p = Jim_Alloc(len + 1);
80998212
81008213
str += utf8_tounicode(str, &c);
8101
- p += utf8_fromunicode(p, utf8_title(c));
8214
+ p += utf8_getchars(p, utf8_title(c));
81028215
81038216
JimStrCopyUpperLower(p, str, 0);
81048217
81058218
return Jim_NewStringObjNoAlloc(interp, buf, -1);
81068219
}
@@ -8203,10 +8316,11 @@
82038316
if (nontrim == NULL) {
82048317
82058318
return Jim_NewEmptyStringObj(interp);
82068319
}
82078320
if (nontrim == strObjPtr->bytes + len) {
8321
+
82088322
return strObjPtr;
82098323
}
82108324
82118325
if (Jim_IsShared(strObjPtr)) {
82128326
strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes));
@@ -8226,14 +8340,14 @@
82268340
Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr);
82278341
82288342
82298343
strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr);
82308344
8231
- if (objPtr != strObjPtr) {
8345
+
8346
+ if (objPtr != strObjPtr && objPtr->refCount == 0) {
82328347
8233
- Jim_IncrRefCount(objPtr);
8234
- Jim_DecrRefCount(interp, objPtr);
8348
+ Jim_FreeNewObj(interp, objPtr);
82358349
}
82368350
82378351
return strObjPtr;
82388352
}
82398353
@@ -8270,26 +8384,26 @@
82708384
return JIM_ERR;
82718385
}
82728386
82738387
str = Jim_GetString(strObjPtr, &len);
82748388
if (len == 0) {
8275
- Jim_SetResultInt(interp, !strict);
8389
+ Jim_SetResultBool(interp, !strict);
82768390
return JIM_OK;
82778391
}
82788392
82798393
switch (strclass) {
82808394
case STR_IS_INTEGER:
82818395
{
82828396
jim_wide w;
8283
- Jim_SetResultInt(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK);
8397
+ Jim_SetResultBool(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK);
82848398
return JIM_OK;
82858399
}
82868400
82878401
case STR_IS_DOUBLE:
82888402
{
82898403
double d;
8290
- Jim_SetResultInt(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE);
8404
+ Jim_SetResultBool(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE);
82918405
return JIM_OK;
82928406
}
82938407
82948408
case STR_IS_ALPHA: isclassfunc = isalpha; break;
82958409
case STR_IS_ALNUM: isclassfunc = isalnum; break;
@@ -8307,15 +8421,15 @@
83078421
return JIM_ERR;
83088422
}
83098423
83108424
for (i = 0; i < len; i++) {
83118425
if (!isclassfunc(str[i])) {
8312
- Jim_SetResultInt(interp, 0);
8426
+ Jim_SetResultBool(interp, 0);
83138427
return JIM_OK;
83148428
}
83158429
}
8316
- Jim_SetResultInt(interp, 1);
8430
+ Jim_SetResultBool(interp, 1);
83178431
return JIM_OK;
83188432
}
83198433
83208434
83218435
@@ -8327,17 +8441,19 @@
83278441
JIM_TYPE_REFERENCES,
83288442
};
83298443
83308444
int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str)
83318445
{
8332
- if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str)
8446
+ if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) {
83338447
return 1;
8448
+ }
83348449
else {
83358450
const char *objStr = Jim_String(objPtr);
83368451
83378452
if (strcmp(str, objStr) != 0)
83388453
return 0;
8454
+
83398455
if (objPtr->typePtr != &comparedStringObjType) {
83408456
Jim_FreeIntRep(interp, objPtr);
83418457
objPtr->typePtr = &comparedStringObjType;
83428458
}
83438459
objPtr->internalRep.ptr = (char *)str;
@@ -8379,24 +8495,23 @@
83798495
83808496
static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr,
83818497
Jim_Obj *fileNameObj, int lineNumber)
83828498
{
83838499
JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object"));
8384
- JimPanic((objPtr->typePtr == &sourceObjType, "JimSetSourceInfo called with non-source object"));
8500
+ JimPanic((objPtr->typePtr != NULL, "JimSetSourceInfo called with typed object"));
83858501
Jim_IncrRefCount(fileNameObj);
83868502
objPtr->internalRep.sourceValue.fileNameObj = fileNameObj;
83878503
objPtr->internalRep.sourceValue.lineNumber = lineNumber;
83888504
objPtr->typePtr = &sourceObjType;
83898505
}
83908506
8391
-
83928507
static const Jim_ObjType scriptLineObjType = {
83938508
"scriptline",
83948509
NULL,
83958510
NULL,
83968511
NULL,
8397
- 0,
8512
+ JIM_NONE,
83988513
};
83998514
84008515
static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line)
84018516
{
84028517
Jim_Obj *objPtr;
@@ -8413,15 +8528,14 @@
84138528
objPtr->internalRep.scriptLineValue.line = line;
84148529
84158530
return objPtr;
84168531
}
84178532
8418
-#define JIM_CMDSTRUCT_EXPAND -1
8419
-
84208533
static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
84218534
static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
8422
-static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result);
8535
+static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
8536
+static int JimParseCheckMissing(Jim_Interp *interp, int ch);
84238537
84248538
static const Jim_ObjType scriptObjType = {
84258539
"script",
84268540
FreeScriptInternalRep,
84278541
DupScriptInternalRep,
@@ -8429,34 +8543,33 @@
84298543
JIM_TYPE_REFERENCES,
84308544
};
84318545
84328546
typedef struct ScriptToken
84338547
{
8434
- int type;
84358548
Jim_Obj *objPtr;
8549
+ int type;
84368550
} ScriptToken;
84378551
84388552
typedef struct ScriptObj
84398553
{
8440
- int len;
84418554
ScriptToken *token;
8555
+ Jim_Obj *fileNameObj;
8556
+ int len;
84428557
int substFlags;
84438558
int inUse; /* Used to share a ScriptObj. Currently
84448559
only used by Jim_EvalObj() as protection against
84458560
shimmering of the currently evaluated object. */
8446
- Jim_Obj *fileNameObj;
84478561
int firstline;
84488562
int linenr;
84498563
} ScriptObj;
84508564
84518565
void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
84528566
{
84538567
int i;
84548568
struct ScriptObj *script = (void *)objPtr->internalRep.ptr;
84558569
8456
- script->inUse--;
8457
- if (script->inUse != 0)
8570
+ if (--script->inUse != 0)
84588571
return;
84598572
for (i = 0; i < script->len; i++) {
84608573
Jim_DecrRefCount(interp, script->token[i].objPtr);
84618574
}
84628575
Jim_Free(script->token);
@@ -8467,11 +8580,10 @@
84678580
void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
84688581
{
84698582
JIM_NOTUSED(interp);
84708583
JIM_NOTUSED(srcPtr);
84718584
8472
-
84738585
dupPtr->typePtr = NULL;
84748586
}
84758587
84768588
typedef struct
84778589
{
@@ -8666,11 +8778,11 @@
86668778
token--;
86678779
}
86688780
86698781
script->len = token - script->token;
86708782
8671
- assert(script->len < count);
8783
+ JimPanic((script->len >= count, "allocated script array is too short"));
86728784
86738785
#ifdef DEBUG_SHOW_SCRIPT
86748786
printf("==== Script (%s) ====\n", Jim_String(script->fileNameObj));
86758787
for (i = 0; i < script->len; i++) {
86768788
const ScriptToken *t = &script->token[i];
@@ -8677,10 +8789,35 @@
86778789
printf("[%2d] %s %s\n", i, jim_tt_name(t->type), Jim_String(t->objPtr));
86788790
}
86798791
#endif
86808792
86818793
}
8794
+
8795
+static int JimParseCheckMissing(Jim_Interp *interp, int ch)
8796
+{
8797
+ const char *msg;
8798
+
8799
+ switch (ch) {
8800
+ case '\\':
8801
+ case ' ':
8802
+ return JIM_OK;
8803
+
8804
+ case '[':
8805
+ msg = "unmatched \"[\"";
8806
+ break;
8807
+ case '{':
8808
+ msg = "missing close-brace";
8809
+ break;
8810
+ case '"':
8811
+ default:
8812
+ msg = "missing quote";
8813
+ break;
8814
+ }
8815
+
8816
+ Jim_SetResultString(interp, msg, -1);
8817
+ return JIM_ERR;
8818
+}
86828819
86838820
static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
86848821
ParseTokenList *tokenlist)
86858822
{
86868823
int i;
@@ -8699,18 +8836,19 @@
86998836
}
87008837
87018838
script->len = i;
87028839
}
87038840
8704
-static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result)
8841
+static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
87058842
{
87068843
int scriptTextLen;
87078844
const char *scriptText = Jim_GetString(objPtr, &scriptTextLen);
87088845
struct JimParserCtx parser;
87098846
struct ScriptObj *script;
87108847
ParseTokenList tokenlist;
87118848
int line = 1;
8849
+ int retcode = JIM_OK;
87128850
87138851
87148852
if (objPtr->typePtr == &sourceObjType) {
87158853
line = objPtr->internalRep.sourceValue.lineNumber;
87168854
}
@@ -8722,16 +8860,12 @@
87228860
while (!parser.eof) {
87238861
JimParseScript(&parser);
87248862
ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
87258863
parser.tline);
87268864
}
8727
- if (result && parser.missing != ' ') {
8728
- ScriptTokenListFree(&tokenlist);
8729
- result->missing = parser.missing;
8730
- result->line = parser.missingline;
8731
- return JIM_ERR;
8732
- }
8865
+
8866
+ retcode = JimParseCheckMissing(interp, parser.missing.ch);
87338867
87348868
87358869
ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0);
87368870
87378871
@@ -8742,10 +8876,11 @@
87428876
script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
87438877
}
87448878
else {
87458879
script->fileNameObj = interp->emptyObj;
87468880
}
8881
+ script->linenr = parser.missing.line;
87478882
Jim_IncrRefCount(script->fileNameObj);
87488883
87498884
ScriptObjAddTokens(interp, script, &tokenlist);
87508885
87518886
@@ -8754,11 +8889,11 @@
87548889
87558890
Jim_FreeIntRep(interp, objPtr);
87568891
Jim_SetIntRepPtr(objPtr, script);
87578892
objPtr->typePtr = &scriptObjType;
87588893
8759
- return JIM_OK;
8894
+ return retcode;
87608895
}
87618896
87628897
ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr)
87638898
{
87648899
if (objPtr == interp->emptyObj) {
@@ -8765,11 +8900,13 @@
87658900
87668901
objPtr = interp->nullScriptObj;
87678902
}
87688903
87698904
if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) {
8770
- SetScriptFromAny(interp, objPtr, NULL);
8905
+ if (JimSetScriptFromAny(interp, objPtr) == JIM_ERR) {
8906
+ return NULL;
8907
+ }
87718908
}
87728909
return (ScriptObj *) Jim_GetIntRepPtr(objPtr);
87738910
}
87748911
87758912
static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr)
@@ -8850,10 +8987,26 @@
88508987
nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
88518988
Jim_AppendStrings(interp, nsObj, "::", name, NULL);
88528989
}
88538990
return nsObj;
88548991
}
8992
+
8993
+Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
8994
+{
8995
+ Jim_Obj *resultObj;
8996
+
8997
+ const char *name = Jim_String(nameObjPtr);
8998
+ if (name[0] == ':' && name[1] == ':') {
8999
+ return nameObjPtr;
9000
+ }
9001
+ Jim_IncrRefCount(nameObjPtr);
9002
+ resultObj = Jim_NewStringObj(interp, "::", -1);
9003
+ Jim_AppendObj(interp, resultObj, nameObjPtr);
9004
+ Jim_DecrRefCount(interp, nameObjPtr);
9005
+
9006
+ return resultObj;
9007
+}
88559008
88569009
static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr)
88579010
{
88589011
Jim_Obj *objPtr = interp->emptyObj;
88599012
@@ -8877,10 +9030,15 @@
88779030
88789031
#else
88799032
88809033
#define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME))
88819034
#define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY)
9035
+
9036
+Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
9037
+{
9038
+ return nameObjPtr;
9039
+}
88829040
#endif
88839041
88849042
static int JimCreateCommand(Jim_Interp *interp, const char *name, Jim_Cmd *cmd)
88859043
{
88869044
Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, name);
@@ -8889,12 +9047,12 @@
88899047
Jim_InterpIncrProcEpoch(interp);
88909048
}
88919049
88929050
if (he && interp->local) {
88939051
8894
- cmd->prevCmd = he->u.val;
8895
- he->u.val = cmd;
9052
+ cmd->prevCmd = Jim_GetHashEntryVal(he);
9053
+ Jim_SetHashVal(&interp->commands, he, cmd);
88969054
}
88979055
else {
88989056
if (he) {
88999057
89009058
Jim_DeleteHashEntry(&interp->commands, name);
@@ -8933,19 +9091,19 @@
89339091
}
89349092
89359093
cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable));
89369094
Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp);
89379095
for (i = 0; i < len; i++) {
8938
- Jim_Obj *objPtr = NULL, *initObjPtr = NULL, *nameObjPtr = NULL;
9096
+ Jim_Obj *objPtr, *initObjPtr, *nameObjPtr;
89399097
Jim_Var *varPtr;
89409098
int subLen;
89419099
8942
- Jim_ListIndex(interp, staticsListObjPtr, i, &objPtr, JIM_NONE);
9100
+ objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i);
89439101
89449102
subLen = Jim_ListLength(interp, objPtr);
89459103
if (subLen == 1 || subLen == 2) {
8946
- Jim_ListIndex(interp, objPtr, 0, &nameObjPtr, JIM_NONE);
9104
+ nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0);
89479105
if (subLen == 1) {
89489106
initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
89499107
if (initObjPtr == NULL) {
89509108
Jim_SetResultFormatted(interp,
89519109
"variable for initialization of static \"%#s\" not found in the local context",
@@ -8952,11 +9110,11 @@
89529110
nameObjPtr);
89539111
return JIM_ERR;
89549112
}
89559113
}
89569114
else {
8957
- Jim_ListIndex(interp, objPtr, 1, &initObjPtr, JIM_NONE);
9115
+ initObjPtr = Jim_ListGetIndex(interp, objPtr, 1);
89589116
}
89599117
if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) {
89609118
return JIM_ERR;
89619119
}
89629120
@@ -9038,11 +9196,11 @@
90389196
Jim_Obj *nameObjPtr;
90399197
Jim_Obj *defaultObjPtr;
90409198
int len;
90419199
90429200
9043
- Jim_ListIndex(interp, argListObjPtr, i, &argPtr, JIM_NONE);
9201
+ argPtr = Jim_ListGetIndex(interp, argListObjPtr, i);
90449202
len = Jim_ListLength(interp, argPtr);
90459203
if (len == 0) {
90469204
Jim_SetResultString(interp, "argument with no name", -1);
90479205
err:
90489206
JimDecrCmdRefCount(interp, cmdPtr);
@@ -9053,12 +9211,12 @@
90539211
goto err;
90549212
}
90559213
90569214
if (len == 2) {
90579215
9058
- Jim_ListIndex(interp, argPtr, 0, &nameObjPtr, JIM_NONE);
9059
- Jim_ListIndex(interp, argPtr, 1, &defaultObjPtr, JIM_NONE);
9216
+ nameObjPtr = Jim_ListGetIndex(interp, argPtr, 0);
9217
+ defaultObjPtr = Jim_ListGetIndex(interp, argPtr, 1);
90609218
}
90619219
else {
90629220
90639221
nameObjPtr = argPtr;
90649222
defaultObjPtr = NULL;
@@ -9132,11 +9290,11 @@
91329290
else if (Jim_FindHashEntry(&interp->commands, fqnew)) {
91339291
Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName);
91349292
}
91359293
else {
91369294
9137
- cmdPtr = he->u.val;
9295
+ cmdPtr = Jim_GetHashEntryVal(he);
91389296
JimIncrCmdRefCount(cmdPtr);
91399297
JimUpdateProcNamespace(interp, cmdPtr, fqnew);
91409298
Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr);
91419299
91429300
@@ -9217,11 +9375,11 @@
92179375
return NULL;
92189376
}
92199377
#ifdef jim_ext_namespace
92209378
found:
92219379
#endif
9222
- cmd = (Jim_Cmd *)he->u.val;
9380
+ cmd = Jim_GetHashEntryVal(he);
92239381
92249382
92259383
Jim_FreeIntRep(interp, objPtr);
92269384
objPtr->typePtr = &commandObjType;
92279385
objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch;
@@ -9323,11 +9481,11 @@
93239481
93249482
93259483
Jim_FreeIntRep(interp, objPtr);
93269484
objPtr->typePtr = &variableObjType;
93279485
objPtr->internalRep.varValue.callFrameId = framePtr->id;
9328
- objPtr->internalRep.varValue.varPtr = he->u.val;
9486
+ objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he);
93299487
objPtr->internalRep.varValue.global = global;
93309488
return JIM_OK;
93319489
}
93329490
93339491
@@ -9641,11 +9799,11 @@
96419799
}
96429800
96439801
retval = Jim_DeleteHashEntry(&framePtr->vars, name);
96449802
if (retval == JIM_OK) {
96459803
9646
- JimChangeCallFrameId(interp, framePtr);
9804
+ framePtr->id = interp->callFrameEpoch++;
96479805
}
96489806
}
96499807
}
96509808
if (retval != JIM_OK && (flags & JIM_ERRMSG)) {
96519809
Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such variable", nameObjPtr);
@@ -9725,28 +9883,17 @@
97259883
return NULL;
97269884
}
97279885
97289886
ret = Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
97299887
if (ret != JIM_OK) {
9730
- resObjPtr = NULL;
9731
- if (ret < 0) {
9732
- Jim_SetResultFormatted(interp,
9733
- "can't read \"%#s(%#s)\": variable isn't array", varObjPtr, keyObjPtr);
9734
- }
9735
- else {
9736
- Jim_SetResultFormatted(interp,
9737
- "can't read \"%#s(%#s)\": no such element in array", varObjPtr, keyObjPtr);
9738
- }
9888
+ Jim_SetResultFormatted(interp,
9889
+ "can't read \"%#s(%#s)\": %s array", varObjPtr, keyObjPtr,
9890
+ ret < 0 ? "variable isn't" : "no such element in");
97399891
}
97409892
else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) {
9741
- dictObjPtr = Jim_DuplicateObj(interp, dictObjPtr);
9742
- if (Jim_SetVariable(interp, varObjPtr, dictObjPtr) != JIM_OK) {
9743
-
9744
- JimPanic((1, "SetVariable failed for JIM_UNSHARED"));
9745
- }
97469893
9747
- Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
9894
+ Jim_SetVariable(interp, varObjPtr, Jim_DuplicateObj(interp, dictObjPtr));
97489895
}
97499896
97509897
return resObjPtr;
97519898
}
97529899
@@ -9843,68 +9990,67 @@
98439990
Jim_CallFrame *cf;
98449991
98459992
if (interp->freeFramesList) {
98469993
cf = interp->freeFramesList;
98479994
interp->freeFramesList = cf->next;
9995
+
9996
+ cf->argv = NULL;
9997
+ cf->argc = 0;
9998
+ cf->procArgsObjPtr = NULL;
9999
+ cf->procBodyObjPtr = NULL;
10000
+ cf->next = NULL;
10001
+ cf->staticVars = NULL;
10002
+ cf->localCommands = NULL;
10003
+ cf->tailcall = 0;
10004
+ cf->tailcallObj = NULL;
10005
+ cf->tailcallCmd = NULL;
984810006
}
984910007
else {
985010008
cf = Jim_Alloc(sizeof(*cf));
9851
- cf->vars.table = NULL;
10009
+ memset(cf, 0, sizeof(*cf));
10010
+
10011
+ Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp);
985210012
}
985310013
985410014
cf->id = interp->callFrameEpoch++;
985510015
cf->parent = parent;
985610016
cf->level = parent ? parent->level + 1 : 0;
9857
- cf->argv = NULL;
9858
- cf->argc = 0;
9859
- cf->procArgsObjPtr = NULL;
9860
- cf->procBodyObjPtr = NULL;
9861
- cf->next = NULL;
9862
- cf->staticVars = NULL;
9863
- cf->localCommands = NULL;
9864
-
986510017
cf->nsObj = nsObj;
986610018
Jim_IncrRefCount(nsObj);
9867
- if (cf->vars.table == NULL)
9868
- Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp);
10019
+
986910020
return cf;
987010021
}
987110022
9872
-
9873
-static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf)
9874
-{
9875
- cf->id = interp->callFrameEpoch++;
9876
-}
9877
-
987810023
static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands)
987910024
{
988010025
988110026
if (localCommands) {
988210027
Jim_Obj *cmdNameObj;
988310028
988410029
while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) {
988510030
Jim_HashEntry *he;
988610031
Jim_Obj *fqObjName;
10032
+ Jim_HashTable *ht = &interp->commands;
988710033
988810034
const char *fqname = JimQualifyName(interp, Jim_String(cmdNameObj), &fqObjName);
988910035
9890
- he = Jim_FindHashEntry(&interp->commands, fqname);
10036
+ he = Jim_FindHashEntry(ht, fqname);
989110037
989210038
if (he) {
9893
- Jim_Cmd *cmd = he->u.val;
10039
+ Jim_Cmd *cmd = Jim_GetHashEntryVal(he);
989410040
if (cmd->prevCmd) {
989510041
Jim_Cmd *prevCmd = cmd->prevCmd;
989610042
cmd->prevCmd = NULL;
989710043
989810044
989910045
JimDecrCmdRefCount(interp, cmd);
990010046
990110047
9902
- he->u.val = prevCmd;
10048
+ Jim_SetHashVal(ht, he, prevCmd);
990310049
}
990410050
else {
9905
- Jim_DeleteHashEntry(&interp->commands, fqname);
10051
+ Jim_DeleteHashEntry(ht, fqname);
990610052
Jim_InterpIncrProcEpoch(interp);
990710053
}
990810054
}
990910055
Jim_DecrRefCount(interp, cmdNameObj);
991010056
JimFreeQualifiedName(interp, fqObjName);
@@ -9914,47 +10060,45 @@
991410060
}
991510061
return JIM_OK;
991610062
}
991710063
991810064
9919
-#define JIM_FCF_NONE 0
9920
-#define JIM_FCF_NOHT 1
9921
-static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags)
9922
-{
10065
+#define JIM_FCF_FULL 0
10066
+#define JIM_FCF_REUSE 1
10067
+static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action)
10068
+ {
10069
+ JimDeleteLocalProcs(interp, cf->localCommands);
10070
+
992310071
if (cf->procArgsObjPtr)
992410072
Jim_DecrRefCount(interp, cf->procArgsObjPtr);
992510073
if (cf->procBodyObjPtr)
992610074
Jim_DecrRefCount(interp, cf->procBodyObjPtr);
992710075
Jim_DecrRefCount(interp, cf->nsObj);
9928
- if (!(flags & JIM_FCF_NOHT))
10076
+ if (action == JIM_FCF_FULL || cf->vars.size != JIM_HT_INITIAL_SIZE)
992910077
Jim_FreeHashTable(&cf->vars);
993010078
else {
993110079
int i;
993210080
Jim_HashEntry **table = cf->vars.table, *he;
993310081
993410082
for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) {
993510083
he = table[i];
993610084
while (he != NULL) {
993710085
Jim_HashEntry *nextEntry = he->next;
9938
- Jim_Var *varPtr = (void *)he->u.val;
10086
+ Jim_Var *varPtr = Jim_GetHashEntryVal(he);
993910087
994010088
Jim_DecrRefCount(interp, varPtr->objPtr);
9941
- Jim_Free(he->u.val);
9942
- Jim_Free((void *)he->key);
10089
+ Jim_Free(Jim_GetHashEntryKey(he));
10090
+ Jim_Free(varPtr);
994310091
Jim_Free(he);
994410092
table[i] = NULL;
994510093
he = nextEntry;
994610094
}
994710095
}
994810096
cf->vars.used = 0;
994910097
}
9950
-
9951
- JimDeleteLocalProcs(interp, cf->localCommands);
9952
-
995310098
cf->next = interp->freeFramesList;
995410099
interp->freeFramesList = cf;
9955
-
995610100
}
995710101
995810102
995910103
#ifdef JIM_REFERENCES
996010104
@@ -10031,21 +10175,16 @@
1003110175
NULL,
1003210176
UpdateStringOfReference,
1003310177
JIM_TYPE_REFERENCES,
1003410178
};
1003510179
10036
-void UpdateStringOfReference(struct Jim_Obj *objPtr)
10180
+static void UpdateStringOfReference(struct Jim_Obj *objPtr)
1003710181
{
10038
- int len;
1003910182
char buf[JIM_REFERENCE_SPACE + 1];
10040
- Jim_Reference *refPtr;
1004110183
10042
- refPtr = objPtr->internalRep.refValue.refPtr;
10043
- len = JimFormatReference(buf, refPtr, objPtr->internalRep.refValue.id);
10044
- objPtr->bytes = Jim_Alloc(len + 1);
10045
- memcpy(objPtr->bytes, buf, len + 1);
10046
- objPtr->length = len;
10184
+ JimFormatReference(buf, objPtr->internalRep.refValue.refPtr, objPtr->internalRep.refValue.id);
10185
+ JimSetStringBytes(objPtr, buf);
1004710186
}
1004810187
1004910188
static int isrefchar(int c)
1005010189
{
1005110190
return (c == '_' || isalnum(c));
@@ -10096,11 +10235,11 @@
1009610235
he = Jim_FindHashEntry(&interp->references, &value);
1009710236
if (he == NULL) {
1009810237
Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr);
1009910238
return JIM_ERR;
1010010239
}
10101
- refPtr = he->u.val;
10240
+ refPtr = Jim_GetHashEntryVal(he);
1010210241
1010310242
Jim_FreeIntRep(interp, objPtr);
1010410243
objPtr->typePtr = &referenceObjType;
1010510244
objPtr->internalRep.refValue.id = value;
1010610245
objPtr->internalRep.refValue.refPtr = refPtr;
@@ -10279,13 +10418,20 @@
1027910418
return i;
1028010419
}
1028110420
1028210421
void Jim_FreeInterp(Jim_Interp *i)
1028310422
{
10284
- Jim_CallFrame *cf = i->framePtr, *prevcf, *nextcf;
10423
+ Jim_CallFrame *cf, *cfx;
10424
+
1028510425
Jim_Obj *objPtr, *nextObjPtr;
1028610426
10427
+
10428
+ for (cf = i->framePtr; cf; cf = cfx) {
10429
+ cfx = cf->parent;
10430
+ JimFreeCallFrame(i, cf, JIM_FCF_FULL);
10431
+ }
10432
+
1028710433
Jim_DecrRefCount(i, i->emptyObj);
1028810434
Jim_DecrRefCount(i, i->trueObj);
1028910435
Jim_DecrRefCount(i, i->falseObj);
1029010436
Jim_DecrRefCount(i, i->result);
1029110437
Jim_DecrRefCount(i, i->stackTrace);
@@ -10300,61 +10446,54 @@
1030010446
#endif
1030110447
Jim_FreeHashTable(&i->packages);
1030210448
Jim_Free(i->prngState);
1030310449
Jim_FreeHashTable(&i->assocData);
1030410450
10305
-
10306
- while (cf) {
10307
- prevcf = cf->parent;
10308
- JimFreeCallFrame(i, cf, JIM_FCF_NONE);
10309
- cf = prevcf;
10310
- }
10451
+#ifdef JIM_MAINTAINER
1031110452
if (i->liveList != NULL) {
1031210453
objPtr = i->liveList;
1031310454
10314
- printf(JIM_NL "-------------------------------------" JIM_NL);
10315
- printf("Objects still in the free list:" JIM_NL);
10455
+ printf("\n-------------------------------------\n");
10456
+ printf("Objects still in the free list:\n");
1031610457
while (objPtr) {
1031710458
const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string";
1031810459
1031910460
if (objPtr->bytes && strlen(objPtr->bytes) > 20) {
10320
- printf("%p (%d) %-10s: '%.20s...'" JIM_NL,
10461
+ printf("%p (%d) %-10s: '%.20s...'\n",
1032110462
(void *)objPtr, objPtr->refCount, type, objPtr->bytes);
1032210463
}
1032310464
else {
10324
- printf("%p (%d) %-10s: '%s'" JIM_NL,
10465
+ printf("%p (%d) %-10s: '%s'\n",
1032510466
(void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)");
1032610467
}
1032710468
if (objPtr->typePtr == &sourceObjType) {
10328
- printf("FILE %s LINE %d" JIM_NL,
10469
+ printf("FILE %s LINE %d\n",
1032910470
Jim_String(objPtr->internalRep.sourceValue.fileNameObj),
1033010471
objPtr->internalRep.sourceValue.lineNumber);
1033110472
}
1033210473
objPtr = objPtr->nextObjPtr;
1033310474
}
10334
- printf("-------------------------------------" JIM_NL JIM_NL);
10475
+ printf("-------------------------------------\n\n");
1033510476
JimPanic((1, "Live list non empty freeing the interpreter! Leak?"));
1033610477
}
10478
+#endif
10479
+
1033710480
1033810481
objPtr = i->freeList;
1033910482
while (objPtr) {
1034010483
nextObjPtr = objPtr->nextObjPtr;
1034110484
Jim_Free(objPtr);
1034210485
objPtr = nextObjPtr;
1034310486
}
10487
+
1034410488
10345
- cf = i->freeFramesList;
10346
- while (cf) {
10347
- nextcf = cf->next;
10348
- if (cf->vars.table != NULL)
10349
- Jim_Free(cf->vars.table);
10489
+ for (cf = i->freeFramesList; cf; cf = cfx) {
10490
+ cfx = cf->next;
10491
+ if (cf->vars.table)
10492
+ Jim_FreeHashTable(&cf->vars);
1035010493
Jim_Free(cf);
10351
- cf = nextcf;
1035210494
}
10353
-#ifdef jim_ext_load
10354
- Jim_FreeLoadHandles(i);
10355
-#endif
1035610495
1035710496
1035810497
Jim_Free(i);
1035910498
}
1036010499
@@ -10455,11 +10594,10 @@
1045510594
interp->addStackTrace = 1;
1045610595
}
1045710596
}
1045810597
}
1045910598
10460
-
1046110599
static void JimAppendStackTrace(Jim_Interp *interp, const char *procname,
1046210600
Jim_Obj *fileNameObj, int linenr)
1046310601
{
1046410602
if (strcmp(procname, "unknown") == 0) {
1046510603
procname = "";
@@ -10513,12 +10651,11 @@
1051310651
void *Jim_GetAssocData(Jim_Interp *interp, const char *key)
1051410652
{
1051510653
Jim_HashEntry *entryPtr = Jim_FindHashEntry(&interp->assocData, key);
1051610654
1051710655
if (entryPtr != NULL) {
10518
- AssocDataValue *assocEntryPtr = (AssocDataValue *) entryPtr->u.val;
10519
-
10656
+ AssocDataValue *assocEntryPtr = Jim_GetHashEntryVal(entryPtr);
1052010657
return assocEntryPtr->data;
1052110658
}
1052210659
return NULL;
1052310660
}
1052410661
@@ -10552,20 +10689,44 @@
1055210689
};
1055310690
1055410691
1055510692
static void UpdateStringOfInt(struct Jim_Obj *objPtr)
1055610693
{
10557
- int len;
1055810694
char buf[JIM_INTEGER_SPACE + 1];
10695
+ jim_wide wideValue = JimWideValue(objPtr);
10696
+ int pos = 0;
1055910697
10560
- len = JimWideToString(buf, JimWideValue(objPtr));
10561
- objPtr->bytes = Jim_Alloc(len + 1);
10562
- memcpy(objPtr->bytes, buf, len + 1);
10563
- objPtr->length = len;
10698
+ if (wideValue == 0) {
10699
+ buf[pos++] = '0';
10700
+ }
10701
+ else {
10702
+ char tmp[JIM_INTEGER_SPACE];
10703
+ int num = 0;
10704
+ int i;
10705
+
10706
+ if (wideValue < 0) {
10707
+ buf[pos++] = '-';
10708
+ i = wideValue % 10;
10709
+ tmp[num++] = (i > 0) ? (10 - i) : -i;
10710
+ wideValue /= -10;
10711
+ }
10712
+
10713
+ while (wideValue) {
10714
+ tmp[num++] = wideValue % 10;
10715
+ wideValue /= 10;
10716
+ }
10717
+
10718
+ for (i = 0; i < num; i++) {
10719
+ buf[pos++] = '0' + tmp[num - i - 1];
10720
+ }
10721
+ }
10722
+ buf[pos] = 0;
10723
+
10724
+ JimSetStringBytes(objPtr, buf);
1056410725
}
1056510726
10566
-int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
10727
+static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
1056710728
{
1056810729
jim_wide wideValue;
1056910730
const char *str;
1057010731
1057110732
if (objPtr->typePtr == &coercedDoubleObjType) {
@@ -10653,22 +10814,65 @@
1065310814
NULL,
1065410815
UpdateStringOfDouble,
1065510816
JIM_TYPE_NONE,
1065610817
};
1065710818
10658
-void UpdateStringOfDouble(struct Jim_Obj *objPtr)
10659
-{
10660
- int len;
10661
- char buf[JIM_DOUBLE_SPACE + 1];
10662
-
10663
- len = Jim_DoubleToString(buf, objPtr->internalRep.doubleValue);
10664
- objPtr->bytes = Jim_Alloc(len + 1);
10665
- memcpy(objPtr->bytes, buf, len + 1);
10666
- objPtr->length = len;
10819
+#ifndef HAVE_ISNAN
10820
+#undef isnan
10821
+#define isnan(X) ((X) != (X))
10822
+#endif
10823
+#ifndef HAVE_ISINF
10824
+#undef isinf
10825
+#define isinf(X) (1.0 / (X) == 0.0)
10826
+#endif
10827
+
10828
+static void UpdateStringOfDouble(struct Jim_Obj *objPtr)
10829
+{
10830
+ double value = objPtr->internalRep.doubleValue;
10831
+
10832
+ if (isnan(value)) {
10833
+ JimSetStringBytes(objPtr, "NaN");
10834
+ return;
10835
+ }
10836
+ if (isinf(value)) {
10837
+ if (value < 0) {
10838
+ JimSetStringBytes(objPtr, "-Inf");
10839
+ }
10840
+ else {
10841
+ JimSetStringBytes(objPtr, "Inf");
10842
+ }
10843
+ return;
10844
+ }
10845
+ {
10846
+ char buf[JIM_DOUBLE_SPACE + 1];
10847
+ int i;
10848
+ int len = sprintf(buf, "%.12g", value);
10849
+
10850
+
10851
+ for (i = 0; i < len; i++) {
10852
+ if (buf[i] == '.' || buf[i] == 'e') {
10853
+#if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
10854
+ char *e = strchr(buf, 'e');
10855
+ if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
10856
+
10857
+ e += 2;
10858
+ memmove(e, e + 1, len - (e - buf));
10859
+ }
10860
+#endif
10861
+ break;
10862
+ }
10863
+ }
10864
+ if (buf[i] == '\0') {
10865
+ buf[i++] = '.';
10866
+ buf[i++] = '0';
10867
+ buf[i] = '\0';
10868
+ }
10869
+ JimSetStringBytes(objPtr, buf);
10870
+ }
1066710871
}
1066810872
10669
-int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
10873
+static int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
1067010874
{
1067110875
double doubleValue;
1067210876
jim_wide wideValue;
1067310877
const char *str;
1067410878
@@ -10876,15 +11080,15 @@
1087611080
return JIM_ELESTR_SIMPLE;
1087711081
}
1087811082
return JIM_ELESTR_QUOTE;
1087911083
}
1088011084
10881
-static int BackslashQuoteString(const char *s, char *q)
11085
+static int BackslashQuoteString(const char *s, int len, char *q)
1088211086
{
1088311087
char *p = q;
1088411088
10885
- while (*s) {
11089
+ while (len--) {
1088611090
switch (*s) {
1088711091
case ' ':
1088811092
case '$':
1088911093
case '"':
1089011094
case '[':
@@ -10996,11 +11200,11 @@
1099611200
case JIM_ELESTR_QUOTE:
1099711201
if (i == 0 && strRep[0] == '#') {
1099811202
*p++ = '\\';
1099911203
realLength++;
1100011204
}
11001
- qlen = BackslashQuoteString(strRep, p);
11205
+ qlen = BackslashQuoteString(strRep, len, p);
1100211206
p += qlen;
1100311207
realLength += qlen;
1100411208
break;
1100511209
}
1100611210
@@ -11032,11 +11236,11 @@
1103211236
1103311237
if (objPtr->typePtr == &listObjType) {
1103411238
return JIM_OK;
1103511239
}
1103611240
11037
- if (Jim_IsDict(objPtr) && !Jim_IsShared(objPtr)) {
11241
+ if (Jim_IsDict(objPtr) && objPtr->bytes == NULL) {
1103811242
Jim_Obj **listObjPtrPtr;
1103911243
int len;
1104011244
int i;
1104111245
1104211246
listObjPtrPtr = JimDictPairs(objPtr, &len);
@@ -11136,15 +11340,17 @@
1113611340
Jim_Interp *interp;
1113711341
enum {
1113811342
JIM_LSORT_ASCII,
1113911343
JIM_LSORT_NOCASE,
1114011344
JIM_LSORT_INTEGER,
11345
+ JIM_LSORT_REAL,
1114111346
JIM_LSORT_COMMAND
1114211347
} type;
1114311348
int order;
1114411349
int index;
1114511350
int indexed;
11351
+ int unique;
1114611352
int (*subfn)(Jim_Obj **, Jim_Obj **);
1114711353
};
1114811354
1114911355
static struct lsort_info *sort_info;
1115011356
@@ -11179,10 +11385,27 @@
1117911385
longjmp(sort_info->jmpbuf, JIM_ERR);
1118011386
}
1118111387
1118211388
return JimSign(lhs - rhs) * sort_info->order;
1118311389
}
11390
+
11391
+static int ListSortReal(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
11392
+{
11393
+ double lhs = 0, rhs = 0;
11394
+
11395
+ if (Jim_GetDouble(sort_info->interp, *lhsObj, &lhs) != JIM_OK ||
11396
+ Jim_GetDouble(sort_info->interp, *rhsObj, &rhs) != JIM_OK) {
11397
+ longjmp(sort_info->jmpbuf, JIM_ERR);
11398
+ }
11399
+ if (lhs == rhs) {
11400
+ return 0;
11401
+ }
11402
+ if (lhs > rhs) {
11403
+ return sort_info->order;
11404
+ }
11405
+ return -sort_info->order;
11406
+}
1118411407
1118511408
static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
1118611409
{
1118711410
Jim_Obj *compare_script;
1118811411
int rc;
@@ -11201,10 +11424,34 @@
1120111424
}
1120211425
1120311426
return JimSign(ret) * sort_info->order;
1120411427
}
1120511428
11429
+static void ListRemoveDuplicates(Jim_Obj *listObjPtr, int (*comp)(Jim_Obj **lhs, Jim_Obj **rhs))
11430
+{
11431
+ int src;
11432
+ int dst = 0;
11433
+ Jim_Obj **ele = listObjPtr->internalRep.listValue.ele;
11434
+
11435
+ for (src = 1; src < listObjPtr->internalRep.listValue.len; src++) {
11436
+ if (comp(&ele[dst], &ele[src]) == 0) {
11437
+
11438
+ Jim_DecrRefCount(sort_info->interp, ele[dst]);
11439
+ }
11440
+ else {
11441
+
11442
+ dst++;
11443
+ }
11444
+ ele[dst] = ele[src];
11445
+ }
11446
+
11447
+ ele[++dst] = ele[src];
11448
+
11449
+
11450
+ listObjPtr->internalRep.listValue.len = dst;
11451
+}
11452
+
1120611453
1120711454
static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info)
1120811455
{
1120911456
struct lsort_info *prev_info;
1121011457
@@ -11212,11 +11459,11 @@
1121211459
int (*fn) (Jim_Obj **, Jim_Obj **);
1121311460
Jim_Obj **vector;
1121411461
int len;
1121511462
int rc;
1121611463
11217
- JimPanic((Jim_IsShared(listObjPtr), "Jim_ListSortElements called with shared object"));
11464
+ JimPanic((Jim_IsShared(listObjPtr), "ListSortElements called with shared object"));
1121811465
SetListFromAny(interp, listObjPtr);
1121911466
1122011467
1122111468
prev_info = sort_info;
1122211469
sort_info = info;
@@ -11231,10 +11478,13 @@
1123111478
fn = ListSortStringNoCase;
1123211479
break;
1123311480
case JIM_LSORT_INTEGER:
1123411481
fn = ListSortInteger;
1123511482
break;
11483
+ case JIM_LSORT_REAL:
11484
+ fn = ListSortReal;
11485
+ break;
1123611486
case JIM_LSORT_COMMAND:
1123711487
fn = ListSortCommand;
1123811488
break;
1123911489
default:
1124011490
fn = NULL;
@@ -11247,12 +11497,17 @@
1124711497
fn = ListSortIndexHelper;
1124811498
}
1124911499
1125011500
if ((rc = setjmp(info->jmpbuf)) == 0) {
1125111501
qsort(vector, len, sizeof(Jim_Obj *), (qsort_comparator *) fn);
11502
+
11503
+ if (info->unique && len > 1) {
11504
+ ListRemoveDuplicates(listObjPtr, fn);
11505
+ }
11506
+
11507
+ Jim_InvalidateStringRep(listObjPtr);
1125211508
}
11253
- Jim_InvalidateStringRep(listObjPtr);
1125411509
sort_info = prev_info;
1125511510
1125611511
return rc;
1125711512
}
1125811513
@@ -11377,11 +11632,11 @@
1137711632
listPtr->internalRep.listValue.ele[idx] = newObjPtr;
1137811633
Jim_IncrRefCount(newObjPtr);
1137911634
return JIM_OK;
1138011635
}
1138111636
11382
-int Jim_SetListIndex(Jim_Interp *interp, Jim_Obj *varNamePtr,
11637
+int Jim_ListSetIndex(Jim_Interp *interp, Jim_Obj *varNamePtr,
1138311638
Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr)
1138411639
{
1138511640
Jim_Obj *varObjPtr, *objPtr, *listObjPtr;
1138611641
int shared, i, idx;
1138711642
@@ -11425,14 +11680,11 @@
1142511680
int i;
1142611681
int listLen = Jim_ListLength(interp, listObjPtr);
1142711682
Jim_Obj *resObjPtr = Jim_NewEmptyStringObj(interp);
1142811683
1142911684
for (i = 0; i < listLen; ) {
11430
- Jim_Obj *objPtr;
11431
-
11432
- Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE);
11433
- Jim_AppendObj(interp, resObjPtr, objPtr);
11685
+ Jim_AppendObj(interp, resObjPtr, Jim_ListGetIndex(interp, listObjPtr, i));
1143411686
if (++i != listLen) {
1143511687
Jim_AppendString(interp, resObjPtr, joinStr, joinStrLen);
1143611688
}
1143711689
}
1143811690
return resObjPtr;
@@ -11458,43 +11710,42 @@
1145811710
int len = 0, objLen;
1145911711
char *bytes, *p;
1146011712
1146111713
1146211714
for (i = 0; i < objc; i++) {
11463
- Jim_GetString(objv[i], &objLen);
11464
- len += objLen;
11715
+ len += Jim_Length(objv[i]);
1146511716
}
1146611717
if (objc)
1146711718
len += objc - 1;
1146811719
1146911720
p = bytes = Jim_Alloc(len + 1);
1147011721
for (i = 0; i < objc; i++) {
1147111722
const char *s = Jim_GetString(objv[i], &objLen);
1147211723
1147311724
11474
- while (objLen && (*s == ' ' || *s == '\t' || *s == '\n')) {
11725
+ while (objLen && isspace(UCHAR(*s))) {
1147511726
s++;
1147611727
objLen--;
1147711728
len--;
1147811729
}
1147911730
11480
- while (objLen && (s[objLen - 1] == ' ' ||
11481
- s[objLen - 1] == '\n' || s[objLen - 1] == '\t')) {
11731
+ while (objLen && isspace(UCHAR(s[objLen - 1]))) {
1148211732
1148311733
if (objLen > 1 && s[objLen - 2] == '\\') {
1148411734
break;
1148511735
}
1148611736
objLen--;
1148711737
len--;
1148811738
}
1148911739
memcpy(p, s, objLen);
1149011740
p += objLen;
11491
- if (objLen && i + 1 != objc) {
11492
- *p++ = ' ';
11493
- }
11494
- else if (i + 1 != objc) {
11495
- len--;
11741
+ if (i + 1 != objc) {
11742
+ if (objLen)
11743
+ *p++ = ' ';
11744
+ else {
11745
+ len--;
11746
+ }
1149611747
}
1149711748
}
1149811749
*p = '\0';
1149911750
return Jim_NewStringObjNoAlloc(interp, bytes, len);
1150011751
}
@@ -11534,20 +11785,26 @@
1153411785
1153511786
static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2)
1153611787
{
1153711788
return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2);
1153811789
}
11790
+
11791
+static void *JimObjectHTKeyValDup(void *privdata, const void *val)
11792
+{
11793
+ Jim_IncrRefCount((Jim_Obj *)val);
11794
+ return (void *)val;
11795
+}
1153911796
1154011797
static void JimObjectHTKeyValDestructor(void *interp, void *val)
1154111798
{
1154211799
Jim_DecrRefCount(interp, (Jim_Obj *)val);
1154311800
}
1154411801
1154511802
static const Jim_HashTableType JimDictHashTableType = {
1154611803
JimObjectHTHashFunction,
11547
- NULL,
11548
- NULL,
11804
+ JimObjectHTKeyValDup,
11805
+ JimObjectHTKeyValDup,
1154911806
JimObjectHTKeyCompare,
1155011807
JimObjectHTKeyValDestructor,
1155111808
JimObjectHTKeyValDestructor
1155211809
};
1155311810
@@ -11580,16 +11837,11 @@
1158011837
if (ht->size != 0)
1158111838
Jim_ExpandHashTable(dupHt, ht->size);
1158211839
1158311840
JimInitHashTableIterator(ht, &htiter);
1158411841
while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
11585
- const Jim_Obj *keyObjPtr = he->key;
11586
- Jim_Obj *valObjPtr = he->u.val;
11587
-
11588
- Jim_IncrRefCount((Jim_Obj *)keyObjPtr);
11589
- Jim_IncrRefCount(valObjPtr);
11590
- Jim_AddHashEntry(dupHt, keyObjPtr, valObjPtr);
11842
+ Jim_AddHashEntry(dupHt, he->key, he->u.val);
1159111843
}
1159211844
1159311845
dupPtr->internalRep.ptr = dupHt;
1159411846
dupPtr->typePtr = &dictObjType;
1159511847
}
@@ -11607,12 +11859,12 @@
1160711859
1160811860
objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
1160911861
JimInitHashTableIterator(ht, &htiter);
1161011862
i = 0;
1161111863
while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
11612
- objv[i++] = (Jim_Obj *)he->key;
11613
- objv[i++] = he->u.val;
11864
+ objv[i++] = Jim_GetHashEntryKey(he);
11865
+ objv[i++] = Jim_GetHashEntryVal(he);
1161411866
}
1161511867
*len = i;
1161611868
return objv;
1161711869
}
1161811870
@@ -11620,10 +11872,11 @@
1162011872
{
1162111873
1162211874
int len;
1162311875
Jim_Obj **objv = JimDictPairs(objPtr, &len);
1162411876
11877
+
1162511878
JimMakeListStringRep(objPtr, objv, len);
1162611879
1162711880
Jim_Free(objv);
1162811881
}
1162911882
@@ -11633,11 +11886,13 @@
1163311886
1163411887
if (objPtr->typePtr == &dictObjType) {
1163511888
return JIM_OK;
1163611889
}
1163711890
11638
- Jim_String(objPtr);
11891
+ if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) {
11892
+ Jim_String(objPtr);
11893
+ }
1163911894
1164011895
1164111896
listlen = Jim_ListLength(interp, objPtr);
1164211897
if (listlen % 2) {
1164311898
Jim_SetResultString(interp, "missing value to go with key", -1);
@@ -11650,28 +11905,14 @@
1165011905
1165111906
ht = Jim_Alloc(sizeof(*ht));
1165211907
Jim_InitHashTable(ht, &JimDictHashTableType, interp);
1165311908
1165411909
for (i = 0; i < listlen; i += 2) {
11655
- Jim_Obj *keyObjPtr;
11656
- Jim_Obj *valObjPtr;
11657
-
11658
- Jim_ListIndex(interp, objPtr, i, &keyObjPtr, JIM_NONE);
11659
- Jim_ListIndex(interp, objPtr, i + 1, &valObjPtr, JIM_NONE);
11660
-
11661
- Jim_IncrRefCount(keyObjPtr);
11662
- Jim_IncrRefCount(valObjPtr);
11663
-
11664
- if (Jim_AddHashEntry(ht, keyObjPtr, valObjPtr) != JIM_OK) {
11665
- Jim_HashEntry *he;
11666
-
11667
- he = Jim_FindHashEntry(ht, keyObjPtr);
11668
- Jim_DecrRefCount(interp, keyObjPtr);
11669
-
11670
- Jim_DecrRefCount(interp, (Jim_Obj *)he->u.val);
11671
- he->u.val = valObjPtr;
11672
- }
11910
+ Jim_Obj *keyObjPtr = Jim_ListGetIndex(interp, objPtr, i);
11911
+ Jim_Obj *valObjPtr = Jim_ListGetIndex(interp, objPtr, i + 1);
11912
+
11913
+ Jim_ReplaceHashEntry(ht, keyObjPtr, valObjPtr);
1167311914
}
1167411915
1167511916
Jim_FreeIntRep(interp, objPtr);
1167611917
objPtr->typePtr = &dictObjType;
1167711918
objPtr->internalRep.ptr = ht;
@@ -11688,31 +11929,23 @@
1168811929
Jim_HashTable *ht = objPtr->internalRep.ptr;
1168911930
1169011931
if (valueObjPtr == NULL) {
1169111932
return Jim_DeleteHashEntry(ht, keyObjPtr);
1169211933
}
11693
- Jim_IncrRefCount(keyObjPtr);
11694
- Jim_IncrRefCount(valueObjPtr);
11695
- if (Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr)) {
11696
-
11697
- Jim_DecrRefCount(interp, keyObjPtr);
11698
- }
11934
+ Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr);
1169911935
return JIM_OK;
1170011936
}
1170111937
1170211938
int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
1170311939
Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
1170411940
{
11705
- int retcode;
11706
-
1170711941
JimPanic((Jim_IsShared(objPtr), "Jim_DictAddElement called with shared object"));
1170811942
if (SetDictFromAny(interp, objPtr) != JIM_OK) {
1170911943
return JIM_ERR;
1171011944
}
11711
- retcode = DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr);
1171211945
Jim_InvalidateStringRep(objPtr);
11713
- return retcode;
11946
+ return DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr);
1171411947
}
1171511948
1171611949
Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len)
1171711950
{
1171811951
Jim_Obj *objPtr;
@@ -11839,10 +12072,11 @@
1183912072
}
1184012073
objPtr = Jim_NewDictObj(interp, NULL, 0);
1184112074
DictAddElement(interp, dictObjPtr, keyv[i], objPtr);
1184212075
}
1184312076
}
12077
+
1184412078
Jim_InvalidateStringRep(objPtr);
1184512079
Jim_InvalidateStringRep(varObjPtr);
1184612080
if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
1184712081
goto err;
1184812082
}
@@ -11864,28 +12098,29 @@
1186412098
NULL,
1186512099
UpdateStringOfIndex,
1186612100
JIM_TYPE_NONE,
1186712101
};
1186812102
11869
-void UpdateStringOfIndex(struct Jim_Obj *objPtr)
11870
-{
11871
- int len;
11872
- char buf[JIM_INTEGER_SPACE + 1];
11873
-
11874
- if (objPtr->internalRep.intValue >= 0)
11875
- len = sprintf(buf, "%d", objPtr->internalRep.intValue);
11876
- else if (objPtr->internalRep.intValue == -1)
11877
- len = sprintf(buf, "end");
12103
+static void UpdateStringOfIndex(struct Jim_Obj *objPtr)
12104
+{
12105
+ if (objPtr->internalRep.intValue == -1) {
12106
+ JimSetStringBytes(objPtr, "end");
12107
+ }
1187812108
else {
11879
- len = sprintf(buf, "end%d", objPtr->internalRep.intValue + 1);
12109
+ char buf[JIM_INTEGER_SPACE + 1];
12110
+ if (objPtr->internalRep.intValue >= 0) {
12111
+ sprintf(buf, "%d", objPtr->internalRep.intValue);
12112
+ }
12113
+ else {
12114
+
12115
+ sprintf(buf, "end%d", objPtr->internalRep.intValue + 1);
12116
+ }
12117
+ JimSetStringBytes(objPtr, buf);
1188012118
}
11881
- objPtr->bytes = Jim_Alloc(len + 1);
11882
- memcpy(objPtr->bytes, buf, len + 1);
11883
- objPtr->length = len;
1188412119
}
1188512120
11886
-int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
12121
+static int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
1188712122
{
1188812123
int idx, end = 0;
1188912124
const char *str;
1189012125
char *endptr;
1189112126
@@ -11953,14 +12188,17 @@
1195312188
{
1195412189
1195512190
if (objPtr->typePtr == &intObjType) {
1195612191
jim_wide val = JimWideValue(objPtr);
1195712192
11958
- if (!(val < LONG_MIN) && !(val > LONG_MAX)) {
11959
- *indexPtr = (val < 0) ? -INT_MAX : (long)val;;
11960
- return JIM_OK;
11961
- }
12193
+ if (val < 0)
12194
+ *indexPtr = -INT_MAX;
12195
+ else if (val > INT_MAX)
12196
+ *indexPtr = INT_MAX;
12197
+ else
12198
+ *indexPtr = (int)val;
12199
+ return JIM_OK;
1196212200
}
1196312201
if (objPtr->typePtr != &indexObjType && SetIndexFromAny(interp, objPtr) == JIM_ERR)
1196412202
return JIM_ERR;
1196512203
*indexPtr = objPtr->internalRep.intValue;
1196612204
return JIM_OK;
@@ -11980,12 +12218,10 @@
1198012218
NULL
1198112219
};
1198212220
1198312221
#define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes))
1198412222
11985
-static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
11986
-
1198712223
static const Jim_ObjType returnCodeObjType = {
1198812224
"return-code",
1198912225
NULL,
1199012226
NULL,
1199112227
NULL,
@@ -12000,11 +12236,11 @@
1200012236
else {
1200112237
return jimReturnCodes[code];
1200212238
}
1200312239
}
1200412240
12005
-int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
12241
+static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
1200612242
{
1200712243
int returnCode;
1200812244
jim_wide wideValue;
1200912245
1201012246
@@ -12152,24 +12388,21 @@
1215212388
return e->stack[--e->stacklen];
1215312389
}
1215412390
1215512391
static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e)
1215612392
{
12157
- int intresult = 0;
12393
+ int intresult = 1;
1215812394
int rc = JIM_OK;
1215912395
Jim_Obj *A = ExprPop(e);
1216012396
double dA, dC = 0;
1216112397
jim_wide wA, wC = 0;
1216212398
1216312399
if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) {
12164
- intresult = 1;
12165
-
1216612400
switch (e->opcode) {
1216712401
case JIM_EXPROP_FUNC_INT:
12168
- wC = wA;
12169
- break;
1217012402
case JIM_EXPROP_FUNC_ROUND:
12403
+ case JIM_EXPROP_UNARYPLUS:
1217112404
wC = wA;
1217212405
break;
1217312406
case JIM_EXPROP_FUNC_DOUBLE:
1217412407
dC = wA;
1217512408
intresult = 0;
@@ -12178,13 +12411,10 @@
1217812411
wC = wA >= 0 ? wA : -wA;
1217912412
break;
1218012413
case JIM_EXPROP_UNARYMINUS:
1218112414
wC = -wA;
1218212415
break;
12183
- case JIM_EXPROP_UNARYPLUS:
12184
- wC = wA;
12185
- break;
1218612416
case JIM_EXPROP_NOT:
1218712417
wC = !wA;
1218812418
break;
1218912419
default:
1219012420
abort();
@@ -12192,31 +12422,29 @@
1219212422
}
1219312423
else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) {
1219412424
switch (e->opcode) {
1219512425
case JIM_EXPROP_FUNC_INT:
1219612426
wC = dA;
12197
- intresult = 1;
1219812427
break;
1219912428
case JIM_EXPROP_FUNC_ROUND:
1220012429
wC = dA < 0 ? (dA - 0.5) : (dA + 0.5);
12201
- intresult = 1;
1220212430
break;
1220312431
case JIM_EXPROP_FUNC_DOUBLE:
12432
+ case JIM_EXPROP_UNARYPLUS:
1220412433
dC = dA;
12434
+ intresult = 0;
1220512435
break;
1220612436
case JIM_EXPROP_FUNC_ABS:
1220712437
dC = dA >= 0 ? dA : -dA;
12438
+ intresult = 0;
1220812439
break;
1220912440
case JIM_EXPROP_UNARYMINUS:
1221012441
dC = -dA;
12211
- break;
12212
- case JIM_EXPROP_UNARYPLUS:
12213
- dC = dA;
12442
+ intresult = 0;
1221412443
break;
1221512444
case JIM_EXPROP_NOT:
1221612445
wC = !dA;
12217
- intresult = 1;
1221812446
break;
1221912447
default:
1222012448
abort();
1222112449
}
1222212450
}
@@ -12427,11 +12655,11 @@
1242712655
1242812656
1242912657
1243012658
static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
1243112659
{
12432
- int intresult = 0;
12660
+ int intresult = 1;
1243312661
int rc = JIM_OK;
1243412662
double dA, dB, dC = 0;
1243512663
jim_wide wA, wB, wC = 0;
1243612664
1243712665
Jim_Obj *B = ExprPop(e);
@@ -12441,12 +12669,10 @@
1244112669
(B->typePtr != &doubleObjType || B->bytes) &&
1244212670
JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) {
1244312671
1244412672
1244512673
12446
- intresult = 1;
12447
-
1244812674
switch (e->opcode) {
1244912675
case JIM_EXPROP_POW:
1245012676
case JIM_EXPROP_FUNC_POW:
1245112677
wC = JimPowWide(wA, wB);
1245212678
break;
@@ -12496,10 +12722,11 @@
1249612722
default:
1249712723
abort();
1249812724
}
1249912725
}
1250012726
else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) {
12727
+ intresult = 0;
1250112728
switch (e->opcode) {
1250212729
case JIM_EXPROP_POW:
1250312730
case JIM_EXPROP_FUNC_POW:
1250412731
#ifdef JIM_MATH_FUNCTIONS
1250512732
dC = pow(dA, dB);
@@ -12561,12 +12788,10 @@
1256112788
1256212789
1256312790
1256412791
int i = Jim_StringCompareObj(interp, A, B, 0);
1256512792
12566
- intresult = 1;
12567
-
1256812793
switch (e->opcode) {
1256912794
case JIM_EXPROP_LT:
1257012795
wC = i < 0;
1257112796
break;
1257212797
case JIM_EXPROP_GT:
@@ -12610,15 +12835,11 @@
1261012835
int listlen;
1261112836
int i;
1261212837
1261312838
listlen = Jim_ListLength(interp, listObjPtr);
1261412839
for (i = 0; i < listlen; i++) {
12615
- Jim_Obj *objPtr;
12616
-
12617
- Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE);
12618
-
12619
- if (Jim_StringEqObj(objPtr, valObj)) {
12840
+ if (Jim_StringEqObj(Jim_ListGetIndex(interp, listObjPtr, i), valObj)) {
1262012841
return 1;
1262112842
}
1262212843
}
1262312844
return 0;
1262412845
}
@@ -12630,23 +12851,16 @@
1263012851
1263112852
jim_wide wC;
1263212853
1263312854
switch (e->opcode) {
1263412855
case JIM_EXPROP_STREQ:
12635
- case JIM_EXPROP_STRNE: {
12636
- int Alen, Blen;
12637
- const char *sA = Jim_GetString(A, &Alen);
12638
- const char *sB = Jim_GetString(B, &Blen);
12639
-
12640
- if (e->opcode == JIM_EXPROP_STREQ) {
12641
- wC = (Alen == Blen && memcmp(sA, sB, Alen) == 0);
12642
- }
12643
- else {
12644
- wC = (Alen != Blen || memcmp(sA, sB, Alen) != 0);
12856
+ case JIM_EXPROP_STRNE:
12857
+ wC = Jim_StringEqObj(A, B);
12858
+ if (e->opcode == JIM_EXPROP_STRNE) {
12859
+ wC = !wC;
1264512860
}
1264612861
break;
12647
- }
1264812862
case JIM_EXPROP_STRIN:
1264912863
wC = JimSearchList(interp, B, A);
1265012864
break;
1265112865
case JIM_EXPROP_STRNI:
1265212866
wC = !JimSearchList(interp, B, A);
@@ -12818,96 +13032,98 @@
1281813032
LAZY_OP,
1281913033
LAZY_LEFT,
1282013034
LAZY_RIGHT
1282113035
};
1282213036
12823
-#define OPRINIT(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1}
13037
+#define OPRINIT(N, P, A, F) {N, F, P, A, LAZY_NONE, sizeof(N) - 1}
13038
+#define OPRINIT_LAZY(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1}
1282413039
1282513040
static const struct Jim_ExprOperator Jim_ExprOperators[] = {
12826
- OPRINIT("*", 110, 2, JimExprOpBin, LAZY_NONE),
12827
- OPRINIT("/", 110, 2, JimExprOpBin, LAZY_NONE),
12828
- OPRINIT("%", 110, 2, JimExprOpIntBin, LAZY_NONE),
12829
-
12830
- OPRINIT("-", 100, 2, JimExprOpBin, LAZY_NONE),
12831
- OPRINIT("+", 100, 2, JimExprOpBin, LAZY_NONE),
12832
-
12833
- OPRINIT("<<", 90, 2, JimExprOpIntBin, LAZY_NONE),
12834
- OPRINIT(">>", 90, 2, JimExprOpIntBin, LAZY_NONE),
12835
-
12836
- OPRINIT("<<<", 90, 2, JimExprOpIntBin, LAZY_NONE),
12837
- OPRINIT(">>>", 90, 2, JimExprOpIntBin, LAZY_NONE),
12838
-
12839
- OPRINIT("<", 80, 2, JimExprOpBin, LAZY_NONE),
12840
- OPRINIT(">", 80, 2, JimExprOpBin, LAZY_NONE),
12841
- OPRINIT("<=", 80, 2, JimExprOpBin, LAZY_NONE),
12842
- OPRINIT(">=", 80, 2, JimExprOpBin, LAZY_NONE),
12843
-
12844
- OPRINIT("==", 70, 2, JimExprOpBin, LAZY_NONE),
12845
- OPRINIT("!=", 70, 2, JimExprOpBin, LAZY_NONE),
12846
-
12847
- OPRINIT("&", 50, 2, JimExprOpIntBin, LAZY_NONE),
12848
- OPRINIT("^", 49, 2, JimExprOpIntBin, LAZY_NONE),
12849
- OPRINIT("|", 48, 2, JimExprOpIntBin, LAZY_NONE),
12850
-
12851
- OPRINIT("&&", 10, 2, NULL, LAZY_OP),
12852
- OPRINIT(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT),
12853
- OPRINIT(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT),
12854
-
12855
- OPRINIT("||", 9, 2, NULL, LAZY_OP),
12856
- OPRINIT(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT),
12857
- OPRINIT(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT),
12858
-
12859
- OPRINIT("?", 5, 2, JimExprOpNull, LAZY_OP),
12860
- OPRINIT(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT),
12861
- OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
12862
-
12863
- OPRINIT(":", 5, 2, JimExprOpNull, LAZY_OP),
12864
- OPRINIT(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT),
12865
- OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
12866
-
12867
- OPRINIT("**", 250, 2, JimExprOpBin, LAZY_NONE),
12868
-
12869
- OPRINIT("eq", 60, 2, JimExprOpStrBin, LAZY_NONE),
12870
- OPRINIT("ne", 60, 2, JimExprOpStrBin, LAZY_NONE),
12871
-
12872
- OPRINIT("in", 55, 2, JimExprOpStrBin, LAZY_NONE),
12873
- OPRINIT("ni", 55, 2, JimExprOpStrBin, LAZY_NONE),
12874
-
12875
- OPRINIT("!", 150, 1, JimExprOpNumUnary, LAZY_NONE),
12876
- OPRINIT("~", 150, 1, JimExprOpIntUnary, LAZY_NONE),
12877
- OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE),
12878
- OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE),
12879
-
12880
-
12881
-
12882
- OPRINIT("int", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12883
- OPRINIT("abs", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12884
- OPRINIT("double", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12885
- OPRINIT("round", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12886
- OPRINIT("rand", 200, 0, JimExprOpNone, LAZY_NONE),
12887
- OPRINIT("srand", 200, 1, JimExprOpIntUnary, LAZY_NONE),
13041
+ OPRINIT("*", 110, 2, JimExprOpBin),
13042
+ OPRINIT("/", 110, 2, JimExprOpBin),
13043
+ OPRINIT("%", 110, 2, JimExprOpIntBin),
13044
+
13045
+ OPRINIT("-", 100, 2, JimExprOpBin),
13046
+ OPRINIT("+", 100, 2, JimExprOpBin),
13047
+
13048
+ OPRINIT("<<", 90, 2, JimExprOpIntBin),
13049
+ OPRINIT(">>", 90, 2, JimExprOpIntBin),
13050
+
13051
+ OPRINIT("<<<", 90, 2, JimExprOpIntBin),
13052
+ OPRINIT(">>>", 90, 2, JimExprOpIntBin),
13053
+
13054
+ OPRINIT("<", 80, 2, JimExprOpBin),
13055
+ OPRINIT(">", 80, 2, JimExprOpBin),
13056
+ OPRINIT("<=", 80, 2, JimExprOpBin),
13057
+ OPRINIT(">=", 80, 2, JimExprOpBin),
13058
+
13059
+ OPRINIT("==", 70, 2, JimExprOpBin),
13060
+ OPRINIT("!=", 70, 2, JimExprOpBin),
13061
+
13062
+ OPRINIT("&", 50, 2, JimExprOpIntBin),
13063
+ OPRINIT("^", 49, 2, JimExprOpIntBin),
13064
+ OPRINIT("|", 48, 2, JimExprOpIntBin),
13065
+
13066
+ OPRINIT_LAZY("&&", 10, 2, NULL, LAZY_OP),
13067
+ OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT),
13068
+ OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT),
13069
+
13070
+ OPRINIT_LAZY("||", 9, 2, NULL, LAZY_OP),
13071
+ OPRINIT_LAZY(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT),
13072
+ OPRINIT_LAZY(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT),
13073
+
13074
+ OPRINIT_LAZY("?", 5, 2, JimExprOpNull, LAZY_OP),
13075
+ OPRINIT_LAZY(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT),
13076
+ OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
13077
+
13078
+ OPRINIT_LAZY(":", 5, 2, JimExprOpNull, LAZY_OP),
13079
+ OPRINIT_LAZY(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT),
13080
+ OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
13081
+
13082
+ OPRINIT("**", 250, 2, JimExprOpBin),
13083
+
13084
+ OPRINIT("eq", 60, 2, JimExprOpStrBin),
13085
+ OPRINIT("ne", 60, 2, JimExprOpStrBin),
13086
+
13087
+ OPRINIT("in", 55, 2, JimExprOpStrBin),
13088
+ OPRINIT("ni", 55, 2, JimExprOpStrBin),
13089
+
13090
+ OPRINIT("!", 150, 1, JimExprOpNumUnary),
13091
+ OPRINIT("~", 150, 1, JimExprOpIntUnary),
13092
+ OPRINIT(NULL, 150, 1, JimExprOpNumUnary),
13093
+ OPRINIT(NULL, 150, 1, JimExprOpNumUnary),
13094
+
13095
+
13096
+
13097
+ OPRINIT("int", 200, 1, JimExprOpNumUnary),
13098
+ OPRINIT("abs", 200, 1, JimExprOpNumUnary),
13099
+ OPRINIT("double", 200, 1, JimExprOpNumUnary),
13100
+ OPRINIT("round", 200, 1, JimExprOpNumUnary),
13101
+ OPRINIT("rand", 200, 0, JimExprOpNone),
13102
+ OPRINIT("srand", 200, 1, JimExprOpIntUnary),
1288813103
1288913104
#ifdef JIM_MATH_FUNCTIONS
12890
- OPRINIT("sin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12891
- OPRINIT("cos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12892
- OPRINIT("tan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12893
- OPRINIT("asin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12894
- OPRINIT("acos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12895
- OPRINIT("atan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12896
- OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12897
- OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12898
- OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12899
- OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12900
- OPRINIT("floor", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12901
- OPRINIT("exp", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12902
- OPRINIT("log", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12903
- OPRINIT("log10", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12904
- OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12905
- OPRINIT("pow", 200, 2, JimExprOpBin, LAZY_NONE),
13105
+ OPRINIT("sin", 200, 1, JimExprOpDoubleUnary),
13106
+ OPRINIT("cos", 200, 1, JimExprOpDoubleUnary),
13107
+ OPRINIT("tan", 200, 1, JimExprOpDoubleUnary),
13108
+ OPRINIT("asin", 200, 1, JimExprOpDoubleUnary),
13109
+ OPRINIT("acos", 200, 1, JimExprOpDoubleUnary),
13110
+ OPRINIT("atan", 200, 1, JimExprOpDoubleUnary),
13111
+ OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary),
13112
+ OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary),
13113
+ OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary),
13114
+ OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary),
13115
+ OPRINIT("floor", 200, 1, JimExprOpDoubleUnary),
13116
+ OPRINIT("exp", 200, 1, JimExprOpDoubleUnary),
13117
+ OPRINIT("log", 200, 1, JimExprOpDoubleUnary),
13118
+ OPRINIT("log10", 200, 1, JimExprOpDoubleUnary),
13119
+ OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary),
13120
+ OPRINIT("pow", 200, 2, JimExprOpBin),
1290613121
#endif
1290713122
};
1290813123
#undef OPRINIT
13124
+#undef OPRINIT_LAZY
1290913125
1291013126
#define JIM_EXPR_OPERATORS_NUM \
1291113127
(sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))
1291213128
1291313129
static int JimParseExpression(struct JimParserCtx *pc)
@@ -12919,13 +13135,16 @@
1291913135
}
1292013136
pc->p++;
1292113137
pc->len--;
1292213138
}
1292313139
13140
+
13141
+ pc->tline = pc->linenr;
13142
+ pc->tstart = pc->p;
13143
+
1292413144
if (pc->len == 0) {
12925
- pc->tstart = pc->tend = pc->p;
12926
- pc->tline = pc->linenr;
13145
+ pc->tend = pc->p;
1292713146
pc->tt = JIM_TT_EOL;
1292813147
pc->eof = 1;
1292913148
return JIM_OK;
1293013149
}
1293113150
switch (*(pc->p)) {
@@ -12936,12 +13155,11 @@
1293613155
pc->tt = JIM_TT_SUBEXPR_END;
1293713156
goto singlechar;
1293813157
case ',':
1293913158
pc->tt = JIM_TT_SUBEXPR_COMMA;
1294013159
singlechar:
12941
- pc->tstart = pc->tend = pc->p;
12942
- pc->tline = pc->linenr;
13160
+ pc->tend = pc->p;
1294313161
pc->p++;
1294413162
pc->len--;
1294513163
break;
1294613164
case '[':
1294713165
return JimParseCmd(pc);
@@ -12987,82 +13205,44 @@
1298713205
return JIM_OK;
1298813206
}
1298913207
1299013208
static int JimParseExprNumber(struct JimParserCtx *pc)
1299113209
{
12992
- int allowdot = 1;
12993
- int base = 10;
13210
+ char *end;
1299413211
1299513212
1299613213
pc->tt = JIM_TT_EXPR_INT;
12997
- pc->tstart = pc->p;
12998
- pc->tline = pc->linenr;
12999
-
13000
-
13001
- if (pc->p[0] == '0') {
13002
- switch (pc->p[1]) {
13003
- case 'x':
13004
- case 'X':
13005
- base = 16;
13006
- allowdot = 0;
13007
- pc->p += 2;
13008
- pc->len -= 2;
13009
- break;
13010
- case 'o':
13011
- case 'O':
13012
- base = 8;
13013
- allowdot = 0;
13014
- pc->p += 2;
13015
- pc->len -= 2;
13016
- break;
13017
- case 'b':
13018
- case 'B':
13019
- base = 2;
13020
- allowdot = 0;
13021
- pc->p += 2;
13022
- pc->len -= 2;
13023
- break;
13024
- }
13025
- }
13026
-
13027
- while (isdigit(UCHAR(*pc->p))
13028
- || (base == 16 && isxdigit(UCHAR(*pc->p)))
13029
- || (base == 8 && *pc->p >= '0' && *pc->p <= '7')
13030
- || (base == 2 && (*pc->p == '0' || *pc->p == '1'))
13031
- || (allowdot && *pc->p == '.')
13032
- ) {
13033
- if (*pc->p == '.') {
13034
- allowdot = 0;
13035
- pc->tt = JIM_TT_EXPR_DOUBLE;
13036
- }
13037
- pc->p++;
13038
- pc->len--;
13039
- if (base == 10 && (*pc->p == 'e' || *pc->p == 'E') && (pc->p[1] == '-' || pc->p[1] == '+'
13040
- || isdigit(UCHAR(pc->p[1])))) {
13041
- pc->p += 2;
13042
- pc->len -= 2;
13043
- pc->tt = JIM_TT_EXPR_DOUBLE;
13214
+
13215
+ jim_strtoull(pc->p, (char **)&pc->p);
13216
+
13217
+ if (strchr("eENnIi.", *pc->p) || pc->p == pc->tstart) {
13218
+ if (strtod(pc->tstart, &end)) { }
13219
+ if (end == pc->tstart)
13220
+ return JIM_ERR;
13221
+ if (end > pc->p) {
13222
+
13223
+ pc->tt = JIM_TT_EXPR_DOUBLE;
13224
+ pc->p = end;
1304413225
}
1304513226
}
1304613227
pc->tend = pc->p - 1;
13228
+ pc->len -= (pc->p - pc->tstart);
1304713229
return JIM_OK;
1304813230
}
1304913231
1305013232
static int JimParseExprIrrational(struct JimParserCtx *pc)
1305113233
{
13052
- const char *Tokens[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL };
13053
- const char **token;
13054
-
13055
- for (token = Tokens; *token != NULL; token++) {
13056
- int len = strlen(*token);
13057
-
13058
- if (strncmp(*token, pc->p, len) == 0) {
13059
- pc->tstart = pc->p;
13060
- pc->tend = pc->p + len - 1;
13061
- pc->p += len;
13062
- pc->len -= len;
13063
- pc->tline = pc->linenr;
13234
+ const char *irrationals[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL };
13235
+ int i;
13236
+
13237
+ for (i = 0; irrationals[i]; i++) {
13238
+ const char *irr = irrationals[i];
13239
+
13240
+ if (strncmp(irr, pc->p, 3) == 0) {
13241
+ pc->p += 3;
13242
+ pc->len -= 3;
13243
+ pc->tend = pc->p - 1;
1306413244
pc->tt = JIM_TT_EXPR_DOUBLE;
1306513245
return JIM_OK;
1306613246
}
1306713247
}
1306813248
return JIM_ERR;
@@ -13102,15 +13282,13 @@
1310213282
}
1310313283
if (*p != '(') {
1310413284
return JIM_ERR;
1310513285
}
1310613286
}
13107
- pc->tstart = pc->p;
1310813287
pc->tend = pc->p + bestLen - 1;
1310913288
pc->p += bestLen;
1311013289
pc->len -= bestLen;
13111
- pc->tline = pc->linenr;
1311213290
1311313291
pc->tt = bestIdx;
1311413292
return JIM_OK;
1311513293
}
1311613294
@@ -13608,17 +13786,23 @@
1360813786
}
1360913787
1361013788
#ifdef DEBUG_SHOW_EXPR_TOKENS
1361113789
{
1361213790
int i;
13613
- printf("==== Expr Tokens ====\n");
13791
+ printf("==== Expr Tokens (%s) ====\n", Jim_String(fileNameObj));
1361413792
for (i = 0; i < tokenlist.count; i++) {
1361513793
printf("[%2d]@%d %s '%.*s'\n", i, tokenlist.list[i].line, jim_tt_name(tokenlist.list[i].type),
1361613794
tokenlist.list[i].len, tokenlist.list[i].token);
1361713795
}
1361813796
}
1361913797
#endif
13798
+
13799
+ if (JimParseCheckMissing(interp, parser.missing.ch) == JIM_ERR) {
13800
+ ScriptTokenListFree(&tokenlist);
13801
+ Jim_DecrRefCount(interp, fileNameObj);
13802
+ return JIM_ERR;
13803
+ }
1362013804
1362113805
1362213806
expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj);
1362313807
1362413808
@@ -13665,10 +13849,24 @@
1366513849
return NULL;
1366613850
}
1366713851
}
1366813852
return (ExprByteCode *) Jim_GetIntRepPtr(objPtr);
1366913853
}
13854
+
13855
+#ifdef JIM_OPTIMIZATION
13856
+static Jim_Obj *JimExprIntValOrVar(Jim_Interp *interp, const ScriptToken *token)
13857
+{
13858
+ if (token->type == JIM_TT_EXPR_INT)
13859
+ return token->objPtr;
13860
+ else if (token->type == JIM_TT_VAR)
13861
+ return Jim_GetVariable(interp, token->objPtr, JIM_NONE);
13862
+ else if (token->type == JIM_TT_DICTSUGAR)
13863
+ return JimExpandDictSugar(interp, token->objPtr);
13864
+ else
13865
+ return NULL;
13866
+}
13867
+#endif
1367013868
1367113869
#define JIM_EE_STATICSTACK_LEN 10
1367213870
1367313871
int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr)
1367413872
{
@@ -13688,102 +13886,69 @@
1368813886
Jim_Obj *objPtr;
1368913887
1369013888
1369113889
switch (expr->len) {
1369213890
case 1:
13693
- if (expr->token[0].type == JIM_TT_EXPR_INT) {
13694
- *exprResultPtrPtr = expr->token[0].objPtr;
13695
- Jim_IncrRefCount(*exprResultPtrPtr);
13696
- return JIM_OK;
13697
- }
13698
- if (expr->token[0].type == JIM_TT_VAR) {
13699
- objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_ERRMSG);
13700
- if (objPtr) {
13701
- *exprResultPtrPtr = objPtr;
13702
- Jim_IncrRefCount(*exprResultPtrPtr);
13703
- return JIM_OK;
13704
- }
13891
+ objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
13892
+ if (objPtr) {
13893
+ Jim_IncrRefCount(objPtr);
13894
+ *exprResultPtrPtr = objPtr;
13895
+ return JIM_OK;
1370513896
}
1370613897
break;
1370713898
1370813899
case 2:
13709
- if (expr->token[1].type == JIM_EXPROP_NOT && expr->token[0].type == JIM_TT_VAR) {
13710
- jim_wide wideValue;
13900
+ if (expr->token[1].type == JIM_EXPROP_NOT) {
13901
+ objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
1371113902
13712
- objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE);
13713
- if (objPtr && JimIsWide(objPtr)
13714
- && Jim_GetWide(interp, objPtr, &wideValue) == JIM_OK) {
13715
- *exprResultPtrPtr = wideValue ? interp->falseObj : interp->trueObj;
13903
+ if (objPtr && JimIsWide(objPtr)) {
13904
+ *exprResultPtrPtr = JimWideValue(objPtr) ? interp->falseObj : interp->trueObj;
1371613905
Jim_IncrRefCount(*exprResultPtrPtr);
1371713906
return JIM_OK;
1371813907
}
1371913908
}
1372013909
break;
1372113910
1372213911
case 3:
13723
- if (expr->token[0].type == JIM_TT_VAR && (expr->token[1].type == JIM_TT_EXPR_INT
13724
- || expr->token[1].type == JIM_TT_VAR)) {
13725
- switch (expr->token[2].type) {
13726
- case JIM_EXPROP_LT:
13727
- case JIM_EXPROP_LTE:
13728
- case JIM_EXPROP_GT:
13729
- case JIM_EXPROP_GTE:
13730
- case JIM_EXPROP_NUMEQ:
13731
- case JIM_EXPROP_NUMNE:{
13732
-
13733
- jim_wide wideValueA;
13734
- jim_wide wideValueB;
13735
-
13736
- objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE);
13737
- if (objPtr && JimIsWide(objPtr)
13738
- && Jim_GetWide(interp, objPtr, &wideValueA) == JIM_OK) {
13739
- if (expr->token[1].type == JIM_TT_VAR) {
13740
- objPtr =
13741
- Jim_GetVariable(interp, expr->token[1].objPtr,
13742
- JIM_NONE);
13743
- }
13744
- else {
13745
- objPtr = expr->token[1].objPtr;
13746
- }
13747
- if (objPtr && JimIsWide(objPtr)
13748
- && Jim_GetWide(interp, objPtr, &wideValueB) == JIM_OK) {
13749
- int cmpRes;
13750
-
13751
- switch (expr->token[2].type) {
13752
- case JIM_EXPROP_LT:
13753
- cmpRes = wideValueA < wideValueB;
13754
- break;
13755
- case JIM_EXPROP_LTE:
13756
- cmpRes = wideValueA <= wideValueB;
13757
- break;
13758
- case JIM_EXPROP_GT:
13759
- cmpRes = wideValueA > wideValueB;
13760
- break;
13761
- case JIM_EXPROP_GTE:
13762
- cmpRes = wideValueA >= wideValueB;
13763
- break;
13764
- case JIM_EXPROP_NUMEQ:
13765
- cmpRes = wideValueA == wideValueB;
13766
- break;
13767
- case JIM_EXPROP_NUMNE:
13768
- cmpRes = wideValueA != wideValueB;
13769
- break;
13770
- default:
13771
- cmpRes = 0;
13772
- }
13773
- *exprResultPtrPtr =
13774
- cmpRes ? interp->trueObj : interp->falseObj;
13775
- Jim_IncrRefCount(*exprResultPtrPtr);
13776
- return JIM_OK;
13777
- }
13778
- }
13779
- }
13780
- }
13781
- }
13782
- break;
13783
- }
13784
- }
13912
+ objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
13913
+ if (objPtr && JimIsWide(objPtr)) {
13914
+ Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, &expr->token[1]);
13915
+ if (objPtr2 && JimIsWide(objPtr2)) {
13916
+ jim_wide wideValueA = JimWideValue(objPtr);
13917
+ jim_wide wideValueB = JimWideValue(objPtr2);
13918
+ int cmpRes;
13919
+ switch (expr->token[2].type) {
13920
+ case JIM_EXPROP_LT:
13921
+ cmpRes = wideValueA < wideValueB;
13922
+ break;
13923
+ case JIM_EXPROP_LTE:
13924
+ cmpRes = wideValueA <= wideValueB;
13925
+ break;
13926
+ case JIM_EXPROP_GT:
13927
+ cmpRes = wideValueA > wideValueB;
13928
+ break;
13929
+ case JIM_EXPROP_GTE:
13930
+ cmpRes = wideValueA >= wideValueB;
13931
+ break;
13932
+ case JIM_EXPROP_NUMEQ:
13933
+ cmpRes = wideValueA == wideValueB;
13934
+ break;
13935
+ case JIM_EXPROP_NUMNE:
13936
+ cmpRes = wideValueA != wideValueB;
13937
+ break;
13938
+ default:
13939
+ goto noopt;
13940
+ }
13941
+ *exprResultPtrPtr = cmpRes ? interp->trueObj : interp->falseObj;
13942
+ Jim_IncrRefCount(*exprResultPtrPtr);
13943
+ return JIM_OK;
13944
+ }
13945
+ }
13946
+ break;
13947
+ }
13948
+ }
13949
+noopt:
1378513950
#endif
1378613951
1378713952
expr->inUse++;
1378813953
1378913954
@@ -13952,16 +14117,13 @@
1395214117
memcpy(newVec, srcPtr->internalRep.ptr, size);
1395314118
dupPtr->internalRep.ptr = newVec;
1395414119
dupPtr->typePtr = &scanFmtStringObjType;
1395514120
}
1395614121
13957
-void UpdateStringOfScanFmt(Jim_Obj *objPtr)
14122
+static void UpdateStringOfScanFmt(Jim_Obj *objPtr)
1395814123
{
13959
- char *bytes = ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep;
13960
-
13961
- objPtr->bytes = Jim_StrDup(bytes);
13962
- objPtr->length = strlen(bytes);
14124
+ JimSetStringBytes(objPtr, ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep);
1396314125
}
1396414126
1396514127
1396614128
static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
1396714129
{
@@ -14171,11 +14333,10 @@
1417114333
Jim_Obj *tmpObj = NULL;
1417214334
1417314335
1417414336
*valObjPtr = 0;
1417514337
if (descr->prefix) {
14176
-
1417714338
for (i = 0; pos < strLen && descr->prefix[i]; ++i) {
1417814339
1417914340
if (isspace(UCHAR(descr->prefix[i])))
1418014341
while (pos < strLen && isspace(UCHAR(str[pos])))
1418114342
++pos;
@@ -14512,34 +14673,55 @@
1451214673
}
1451314674
1451414675
static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
1451514676
{
1451614677
int retcode;
14517
- Jim_Cmd *cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
14678
+ Jim_Cmd *cmdPtr;
1451814679
14519
- if (cmdPtr == NULL) {
14520
- return JimUnknown(interp, objc, objv);
14680
+#if 0
14681
+ printf("invoke");
14682
+ int j;
14683
+ for (j = 0; j < objc; j++) {
14684
+ printf(" '%s'", Jim_String(objv[j]));
1452114685
}
14686
+ printf("\n");
14687
+#endif
14688
+
14689
+ if (interp->framePtr->tailcallCmd) {
14690
+
14691
+ cmdPtr = interp->framePtr->tailcallCmd;
14692
+ interp->framePtr->tailcallCmd = NULL;
14693
+ }
14694
+ else {
14695
+ cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
14696
+ if (cmdPtr == NULL) {
14697
+ return JimUnknown(interp, objc, objv);
14698
+ }
14699
+ JimIncrCmdRefCount(cmdPtr);
14700
+ }
14701
+
1452214702
if (interp->evalDepth == interp->maxEvalDepth) {
1452314703
Jim_SetResultString(interp, "Infinite eval recursion", -1);
14524
- return JIM_ERR;
14704
+ retcode = JIM_ERR;
14705
+ goto out;
1452514706
}
1452614707
interp->evalDepth++;
1452714708
1452814709
14529
- JimIncrCmdRefCount(cmdPtr);
1453014710
Jim_SetEmptyResult(interp);
1453114711
if (cmdPtr->isproc) {
1453214712
retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
1453314713
}
1453414714
else {
1453514715
interp->cmdPrivData = cmdPtr->u.native.privData;
1453614716
retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
1453714717
}
14538
- JimDecrCmdRefCount(interp, cmdPtr);
1453914718
interp->evalDepth--;
1454014719
14720
+out:
14721
+ JimDecrCmdRefCount(interp, cmdPtr);
14722
+
1454114723
return retcode;
1454214724
}
1454314725
1454414726
int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
1454514727
{
@@ -14717,10 +14899,15 @@
1471714899
objPtr->typePtr = &interpolatedObjType;
1471814900
objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr;
1471914901
objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2];
1472014902
Jim_IncrRefCount(intv[2]);
1472114903
}
14904
+ else if (tokens && intv[0] && intv[0]->typePtr == &sourceObjType) {
14905
+
14906
+ JimSetSourceInfo(interp, objPtr, intv[0]->internalRep.sourceValue.fileNameObj, intv[0]->internalRep.sourceValue.lineNumber);
14907
+ }
14908
+
1472214909
1472314910
s = objPtr->bytes = Jim_Alloc(totlen + 1);
1472414911
objPtr->length = totlen;
1472514912
for (i = 0; i < tokens; i++) {
1472614913
if (intv[i]) {
@@ -14772,10 +14959,14 @@
1477214959
return JimEvalObjList(interp, scriptObjPtr);
1477314960
}
1477414961
1477514962
Jim_IncrRefCount(scriptObjPtr);
1477614963
script = Jim_GetScript(interp, scriptObjPtr);
14964
+ if (script == NULL) {
14965
+ Jim_DecrRefCount(interp, scriptObjPtr);
14966
+ return JIM_ERR;
14967
+ }
1477714968
1477814969
Jim_SetEmptyResult(interp);
1477914970
1478014971
token = script->token;
1478114972
@@ -15046,26 +15237,20 @@
1504615237
retcode = Jim_EvalObj(interp, scriptObj);
1504715238
}
1504815239
1504915240
1505015241
interp->framePtr = interp->framePtr->parent;
15051
- if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) {
15052
- JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE);
15053
- }
15054
- else {
15055
- JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT);
15056
- }
15242
+ JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
1505715243
1505815244
return retcode;
1505915245
}
1506015246
#endif
1506115247
1506215248
static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv)
1506315249
{
1506415250
Jim_CallFrame *callFramePtr;
1506515251
int i, d, retcode, optargs;
15066
- Jim_Stack *localCommands;
1506715252
ScriptObj *script;
1506815253
1506915254
1507015255
if (argc - 1 < cmd->u.proc.reqArity ||
1507115256
(cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) {
@@ -15145,37 +15330,42 @@
1514515330
1514615331
1514715332
retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr);
1514815333
1514915334
badargset:
15335
+
1515015336
15151
-
15152
- localCommands = callFramePtr->localCommands;
15153
- callFramePtr->localCommands = NULL;
15154
-
1515515337
interp->framePtr = interp->framePtr->parent;
15156
- if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) {
15157
- JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE);
15158
- }
15159
- else {
15160
- JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT);
15161
- }
15162
-
15163
-
15164
- while (retcode == JIM_EVAL) {
15165
- Jim_Obj *resultScriptObjPtr = Jim_GetResult(interp);
15166
-
15167
- Jim_IncrRefCount(resultScriptObjPtr);
15168
-
15169
- JimPanic((!Jim_IsList(resultScriptObjPtr), "tailcall (JIM_EVAL) returned non-list"));
15170
-
15171
- retcode = JimEvalObjList(interp, resultScriptObjPtr);
15172
- if (retcode == JIM_RETURN) {
15173
- interp->returnLevel++;
15174
- }
15175
- Jim_DecrRefCount(interp, resultScriptObjPtr);
15176
- }
15338
+ JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
15339
+
15340
+ if (interp->framePtr->tailcallObj) {
15341
+
15342
+ if (interp->framePtr->tailcall++ == 0) {
15343
+
15344
+ do {
15345
+ Jim_Obj *tailcallObj = interp->framePtr->tailcallObj;
15346
+
15347
+ interp->framePtr->tailcallObj = NULL;
15348
+
15349
+ if (retcode == JIM_EVAL) {
15350
+ retcode = Jim_EvalObjList(interp, tailcallObj);
15351
+ if (retcode == JIM_RETURN) {
15352
+ interp->returnLevel++;
15353
+ }
15354
+ }
15355
+ Jim_DecrRefCount(interp, tailcallObj);
15356
+ } while (interp->framePtr->tailcallObj);
15357
+
15358
+
15359
+ if (interp->framePtr->tailcallCmd) {
15360
+ JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd);
15361
+ interp->framePtr->tailcallCmd = NULL;
15362
+ }
15363
+ }
15364
+ interp->framePtr->tailcall--;
15365
+ }
15366
+
1517715367
1517815368
if (retcode == JIM_RETURN) {
1517915369
if (--interp->returnLevel <= 0) {
1518015370
retcode = interp->returnCode;
1518115371
interp->returnCode = JIM_OK;
@@ -15187,13 +15377,10 @@
1518715377
Jim_DecrRefCount(interp, interp->errorProc);
1518815378
interp->errorProc = argv[0];
1518915379
Jim_IncrRefCount(interp->errorProc);
1519015380
}
1519115381
15192
-
15193
- JimDeleteLocalProcs(interp, localCommands);
15194
-
1519515382
return retcode;
1519615383
}
1519715384
1519815385
int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script)
1519915386
{
@@ -15261,11 +15448,10 @@
1526115448
Jim_Obj *scriptObjPtr;
1526215449
Jim_Obj *prevScriptObj;
1526315450
struct stat sb;
1526415451
int retcode;
1526515452
int readlen;
15266
- struct JimParseResult result;
1526715453
1526815454
if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) {
1526915455
Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno));
1527015456
return JIM_ERR;
1527115457
}
@@ -15288,31 +15474,13 @@
1528815474
scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen);
1528915475
JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1);
1529015476
Jim_IncrRefCount(scriptObjPtr);
1529115477
1529215478
15293
- if (SetScriptFromAny(interp, scriptObjPtr, &result) == JIM_ERR) {
15294
- const char *msg;
15295
- char linebuf[20];
15296
-
15297
- switch (result.missing) {
15298
- case '[':
15299
- msg = "unmatched \"[\"";
15300
- break;
15301
- case '{':
15302
- msg = "missing close-brace";
15303
- break;
15304
- case '"':
15305
- default:
15306
- msg = "missing quote";
15307
- break;
15308
- }
15309
-
15310
- snprintf(linebuf, sizeof(linebuf), "%d", result.line);
15311
-
15312
- Jim_SetResultFormatted(interp, "%s in \"%s\" at line %s",
15313
- msg, filename, linebuf);
15479
+ if (Jim_GetScript(interp, scriptObjPtr) == NULL) {
15480
+
15481
+ JimAddErrorToStack(interp, JIM_ERR, (ScriptObj *)Jim_GetIntRepPtr(scriptObjPtr));
1531415482
Jim_DecrRefCount(interp, scriptObjPtr);
1531515483
return JIM_ERR;
1531615484
}
1531715485
1531815486
prevScriptObj = interp->currentScriptObj;
@@ -15475,11 +15643,11 @@
1547515643
}
1547615644
1547715645
typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr,
1547815646
Jim_HashEntry *he, int type);
1547915647
15480
-#define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL)
15648
+#define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL)
1548115649
1548215650
static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
1548315651
JimHashtableIteratorCallbackType *callback, int type)
1548415652
{
1548515653
Jim_HashEntry *he;
@@ -15510,11 +15678,11 @@
1551015678
#define JIM_CMDLIST_CHANNELS 2
1551115679
1551215680
static void JimCommandMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
1551315681
Jim_HashEntry *he, int type)
1551415682
{
15515
- Jim_Cmd *cmdPtr = (Jim_Cmd *)he->u.val;
15683
+ Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he);
1551615684
Jim_Obj *objPtr;
1551715685
1551815686
if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) {
1551915687
1552015688
return;
@@ -15543,11 +15711,11 @@
1554315711
#define JIM_VARLIST_VALUES 0x1000
1554415712
1554515713
static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
1554615714
Jim_HashEntry *he, int type)
1554715715
{
15548
- Jim_Var *varPtr = (Jim_Var *)he->u.val;
15716
+ Jim_Var *varPtr = Jim_GetHashEntryVal(he);
1554915717
1555015718
if (type != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) {
1555115719
Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1));
1555215720
if (type & JIM_VARLIST_VALUES) {
1555315721
Jim_ListAppendElement(interp, listObjPtr, varPtr->objPtr);
@@ -15865,11 +16033,11 @@
1586516033
1586616034
expr = JimGetExpression(interp, argv[2]);
1586716035
incrScript = Jim_GetScript(interp, argv[3]);
1586816036
1586916037
15870
- if (incrScript->len != 3 || !expr || expr->len != 3) {
16038
+ if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) {
1587116039
goto evalstart;
1587216040
}
1587316041
1587416042
if (incrScript->token[1].type != JIM_TT_ESC ||
1587516043
expr->token[0].type != JIM_TT_VAR ||
@@ -16088,11 +16256,11 @@
1608816256
}
1608916257
1609016258
1609116259
static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap)
1609216260
{
16093
- int result = JIM_ERR;
16261
+ int result = JIM_OK;
1609416262
int i, numargs;
1609516263
Jim_ListIter twoiters[2];
1609616264
Jim_ListIter *iters;
1609716265
Jim_Obj *script;
1609816266
Jim_Obj *resultObj;
@@ -16111,13 +16279,16 @@
1611116279
iters = Jim_Alloc(numargs * sizeof(*iters));
1611216280
}
1611316281
for (i = 0; i < numargs; i++) {
1611416282
JimListIterInit(&iters[i], argv[i + 1]);
1611516283
if (i % 2 == 0 && JimListIterDone(interp, &iters[i])) {
16116
- Jim_SetResultString(interp, "foreach varlist is empty", -1);
16117
- return JIM_ERR;
16284
+ result = JIM_ERR;
1611816285
}
16286
+ }
16287
+ if (result != JIM_OK) {
16288
+ Jim_SetResultString(interp, "foreach varlist is empty", -1);
16289
+ return result;
1611916290
}
1612016291
1612116292
if (doMap) {
1612216293
resultObj = Jim_NewListObj(interp, NULL, 0);
1612316294
}
@@ -16430,12 +16601,12 @@
1643016601
{
1643116602
Jim_Obj *objPtr, *listObjPtr;
1643216603
int i;
1643316604
int idx;
1643416605
16435
- if (argc < 3) {
16436
- Jim_WrongNumArgs(interp, 1, argv, "list index ?...?");
16606
+ if (argc < 2) {
16607
+ Jim_WrongNumArgs(interp, 1, argv, "list ?index ...?");
1643716608
return JIM_ERR;
1643816609
}
1643916610
objPtr = argv[1];
1644016611
Jim_IncrRefCount(objPtr);
1644116612
for (i = 2; i < argc; i++) {
@@ -16547,14 +16718,13 @@
1654716718
Jim_IncrRefCount(commandObj);
1654816719
}
1654916720
1655016721
listlen = Jim_ListLength(interp, argv[0]);
1655116722
for (i = 0; i < listlen; i++) {
16552
- Jim_Obj *objPtr;
1655316723
int eq = 0;
16724
+ Jim_Obj *objPtr = Jim_ListGetIndex(interp, argv[0], i);
1655416725
16555
- Jim_ListIndex(interp, argv[0], i, &objPtr, JIM_NONE);
1655616726
switch (opt_match) {
1655716727
case OPT_EXACT:
1655816728
eq = Jim_StringCompareObj(interp, argv[1], objPtr, opt_nocase) == 0;
1655916729
break;
1656016730
@@ -16744,29 +16914,27 @@
1674416914
if (argc < 3) {
1674516915
Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal");
1674616916
return JIM_ERR;
1674716917
}
1674816918
else if (argc == 3) {
16919
+
1674916920
if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
1675016921
return JIM_ERR;
1675116922
Jim_SetResult(interp, argv[2]);
1675216923
return JIM_OK;
1675316924
}
16754
- if (Jim_SetListIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1])
16755
- == JIM_ERR)
16756
- return JIM_ERR;
16757
- return JIM_OK;
16925
+ return Jim_ListSetIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1]);
1675816926
}
1675916927
1676016928
1676116929
static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[])
1676216930
{
1676316931
static const char * const options[] = {
16764
- "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-index", NULL
16932
+ "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-real", "-index", "-unique", NULL
1676516933
};
1676616934
enum
16767
- { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_INDEX };
16935
+ { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE };
1676816936
Jim_Obj *resObj;
1676916937
int i;
1677016938
int retCode;
1677116939
1677216940
struct lsort_info info;
@@ -16777,17 +16945,18 @@
1677716945
}
1677816946
1677916947
info.type = JIM_LSORT_ASCII;
1678016948
info.order = 1;
1678116949
info.indexed = 0;
16950
+ info.unique = 0;
1678216951
info.command = NULL;
1678316952
info.interp = interp;
1678416953
1678516954
for (i = 1; i < (argc - 1); i++) {
1678616955
int option;
1678716956
16788
- if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG)
16957
+ if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ENUM_ABBREV | JIM_ERRMSG)
1678916958
!= JIM_OK)
1679016959
return JIM_ERR;
1679116960
switch (option) {
1679216961
case OPT_ASCII:
1679316962
info.type = JIM_LSORT_ASCII;
@@ -16796,16 +16965,22 @@
1679616965
info.type = JIM_LSORT_NOCASE;
1679716966
break;
1679816967
case OPT_INTEGER:
1679916968
info.type = JIM_LSORT_INTEGER;
1680016969
break;
16970
+ case OPT_REAL:
16971
+ info.type = JIM_LSORT_REAL;
16972
+ break;
1680116973
case OPT_INCREASING:
1680216974
info.order = 1;
1680316975
break;
1680416976
case OPT_DECREASING:
1680516977
info.order = -1;
1680616978
break;
16979
+ case OPT_UNIQUE:
16980
+ info.unique = 1;
16981
+ break;
1680716982
case OPT_COMMAND:
1680816983
if (i >= (argc - 2)) {
1680916984
Jim_SetResultString(interp, "\"-command\" option must be followed by comparison command", -1);
1681016985
return JIM_ERR;
1681116986
}
@@ -16915,20 +17090,20 @@
1691517090
static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1691617091
{
1691717092
if (argc >= 2) {
1691817093
int retcode;
1691917094
Jim_CallFrame *savedCallFrame, *targetCallFrame;
16920
- Jim_Obj *objPtr;
17095
+ int savedTailcall;
1692117096
const char *str;
1692217097
1692317098
1692417099
savedCallFrame = interp->framePtr;
1692517100
1692617101
1692717102
str = Jim_String(argv[1]);
1692817103
if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') {
16929
- targetCallFrame =Jim_GetCallFrameByLevel(interp, argv[1]);
17104
+ targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
1693017105
argc--;
1693117106
argv++;
1693217107
}
1693317108
else {
1693417109
targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL);
@@ -16935,25 +17110,25 @@
1693517110
}
1693617111
if (targetCallFrame == NULL) {
1693717112
return JIM_ERR;
1693817113
}
1693917114
if (argc < 2) {
16940
- argv--;
16941
- Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
17115
+ Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?");
1694217116
return JIM_ERR;
1694317117
}
1694417118
1694517119
interp->framePtr = targetCallFrame;
17120
+
17121
+ savedTailcall = interp->framePtr->tailcall;
17122
+ interp->framePtr->tailcall = 0;
1694617123
if (argc == 2) {
1694717124
retcode = Jim_EvalObj(interp, argv[1]);
1694817125
}
1694917126
else {
16950
- objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1);
16951
- Jim_IncrRefCount(objPtr);
16952
- retcode = Jim_EvalObj(interp, objPtr);
16953
- Jim_DecrRefCount(interp, objPtr);
17127
+ retcode = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
1695417128
}
17129
+ interp->framePtr->tailcall = savedTailcall;
1695517130
interp->framePtr = savedCallFrame;
1695617131
return retcode;
1695717132
}
1695817133
else {
1695917134
Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
@@ -17064,12 +17239,39 @@
1706417239
}
1706517240
1706617241
1706717242
static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1706817243
{
17069
- Jim_SetResult(interp, Jim_NewListObj(interp, argv + 1, argc - 1));
17070
- return JIM_EVAL;
17244
+ if (interp->framePtr->level == 0) {
17245
+ Jim_SetResultString(interp, "tailcall can only be called from a proc or lambda", -1);
17246
+ return JIM_ERR;
17247
+ }
17248
+ else if (argc >= 2) {
17249
+
17250
+ Jim_CallFrame *cf = interp->framePtr->parent;
17251
+
17252
+ Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
17253
+ if (cmdPtr == NULL) {
17254
+ return JIM_ERR;
17255
+ }
17256
+
17257
+ JimPanic((cf->tailcallCmd != NULL, "Already have a tailcallCmd"));
17258
+
17259
+
17260
+ JimIncrCmdRefCount(cmdPtr);
17261
+ cf->tailcallCmd = cmdPtr;
17262
+
17263
+
17264
+ JimPanic((cf->tailcallObj != NULL, "Already have a tailcallobj"));
17265
+
17266
+ cf->tailcallObj = Jim_NewListObj(interp, argv + 1, argc - 1);
17267
+ Jim_IncrRefCount(cf->tailcallObj);
17268
+
17269
+
17270
+ return JIM_EVAL;
17271
+ }
17272
+ return JIM_OK;
1707117273
}
1707217274
1707317275
static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1707417276
{
1707517277
Jim_Obj *cmdList;
@@ -17354,11 +17556,11 @@
1735417556
for (i = 0; i < numMaps; i += 2) {
1735517557
Jim_Obj *objPtr;
1735617558
const char *k;
1735717559
int kl;
1735817560
17359
- Jim_ListIndex(interp, mapListObjPtr, i, &objPtr, JIM_NONE);
17561
+ objPtr = Jim_ListGetIndex(interp, mapListObjPtr, i);
1736017562
k = Jim_String(objPtr);
1736117563
kl = Jim_Utf8Length(interp, objPtr);
1736217564
1736317565
if (strLen >= kl && kl) {
1736417566
int rc;
@@ -17366,12 +17568,11 @@
1736617568
if (rc == 0) {
1736717569
if (noMatchStart) {
1736817570
Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart);
1736917571
noMatchStart = NULL;
1737017572
}
17371
- Jim_ListIndex(interp, mapListObjPtr, i + 1, &objPtr, JIM_NONE);
17372
- Jim_AppendObj(interp, resultObjPtr, objPtr);
17573
+ Jim_AppendObj(interp, resultObjPtr, Jim_ListGetIndex(interp, mapListObjPtr, i + 1));
1737317574
str += utf8_index(str, kl);
1737417575
strLen -= kl;
1737517576
break;
1737617577
}
1737717578
}
@@ -17851,15 +18052,17 @@
1785118052
1785218053
exitCode = JIM_SIGNAL;
1785318054
}
1785418055
else {
1785518056
exitCode = Jim_EvalObj(interp, argv[0]);
18057
+
18058
+ interp->errorFlag = 0;
1785618059
}
1785718060
interp->signal_level -= sig;
1785818061
1785918062
17860
- if (exitCode >= 0 && exitCode < max_ignore_code && ((1 << exitCode) & ignore_mask)) {
18063
+ if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) {
1786118064
1786218065
return exitCode;
1786318066
}
1786418067
1786518068
if (sig && exitCode == JIM_SIGNAL) {
@@ -18009,11 +18212,11 @@
1800918212
listObjPtr = Jim_NewListObj(interp, NULL, 0);
1801018213
1801118214
JimInitHashTableIterator(&interp->references, &htiter);
1801218215
while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
1801318216
char buf[JIM_REFERENCE_SPACE + 1];
18014
- Jim_Reference *refPtr = he->u.val;
18217
+ Jim_Reference *refPtr = Jim_GetHashEntryVal(he);
1801518218
const unsigned long *refId = he->key;
1801618219
1801718220
JimFormatReference(buf, refPtr, *refId);
1801818221
Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1));
1801918222
}
@@ -18043,11 +18246,11 @@
1804318246
1804418247
static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type)
1804518248
{
1804618249
Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
1804718250
if (type & JIM_DICTMATCH_VALUES) {
18048
- Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->u.val);
18251
+ Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he));
1804918252
}
1805018253
}
1805118254
1805218255
static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
1805318256
JimDictMatchCallbackType *callback, int type)
@@ -18092,21 +18295,65 @@
1809218295
return -1;
1809318296
}
1809418297
return ((Jim_HashTable *)objPtr->internalRep.ptr)->used;
1809518298
}
1809618299
18300
+int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr)
18301
+{
18302
+ Jim_HashTable *ht;
18303
+ unsigned int i;
18304
+
18305
+ if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18306
+ return JIM_ERR;
18307
+ }
18308
+
18309
+ ht = (Jim_HashTable *)objPtr->internalRep.ptr;
18310
+
18311
+
18312
+ printf("%d entries in table, %d buckets\n", ht->used, ht->size);
18313
+
18314
+ for (i = 0; i < ht->size; i++) {
18315
+ Jim_HashEntry *he = ht->table[i];
18316
+
18317
+ if (he) {
18318
+ printf("%d: ", i);
18319
+
18320
+ while (he) {
18321
+ printf(" %s", Jim_String(he->key));
18322
+ he = he->next;
18323
+ }
18324
+ printf("\n");
18325
+ }
18326
+ }
18327
+ return JIM_OK;
18328
+}
18329
+
18330
+static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv)
18331
+{
18332
+ Jim_Obj *prefixObj = Jim_NewStringObj(interp, basecmd, -1);
18333
+
18334
+ Jim_AppendString(interp, prefixObj, " ", 1);
18335
+ Jim_AppendString(interp, prefixObj, subcmd, -1);
18336
+
18337
+ return Jim_EvalObjPrefix(interp, prefixObj, argc, argv);
18338
+}
18339
+
1809718340
1809818341
static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1809918342
{
1810018343
Jim_Obj *objPtr;
1810118344
int option;
1810218345
static const char * const options[] = {
18103
- "create", "get", "set", "unset", "exists", "keys", "merge", "size", "with", NULL
18346
+ "create", "get", "set", "unset", "exists", "keys", "size", "info",
18347
+ "merge", "with", "append", "lappend", "incr", "remove", "values", "for",
18348
+ "replace", "update", NULL
1810418349
};
1810518350
enum
1810618351
{
18107
- OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXIST, OPT_KEYS, OPT_MERGE, OPT_SIZE, OPT_WITH,
18352
+ OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXISTS, OPT_KEYS, OPT_SIZE, OPT_INFO,
18353
+ OPT_MERGE, OPT_WITH, OPT_APPEND, OPT_LAPPEND, OPT_INCR, OPT_REMOVE, OPT_VALUES, OPT_FOR,
18354
+ OPT_REPLACE, OPT_UPDATE,
1810818355
};
1810918356
1811018357
if (argc < 2) {
1811118358
Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?");
1811218359
return JIM_ERR;
@@ -18117,11 +18364,11 @@
1811718364
}
1811818365
1811918366
switch (option) {
1812018367
case OPT_GET:
1812118368
if (argc < 3) {
18122
- Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?");
18369
+ Jim_WrongNumArgs(interp, 2, argv, "dictionary ?key ...?");
1812318370
return JIM_ERR;
1812418371
}
1812518372
if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr,
1812618373
JIM_ERRMSG) != JIM_OK) {
1812718374
return JIM_ERR;
@@ -18134,82 +18381,87 @@
1813418381
Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...? value");
1813518382
return JIM_ERR;
1813618383
}
1813718384
return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG);
1813818385
18139
- case OPT_EXIST:
18140
- if (argc < 3) {
18141
- Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?");
18386
+ case OPT_EXISTS:
18387
+ if (argc < 4) {
18388
+ Jim_WrongNumArgs(interp, 2, argv, "dictionary key ?key ...?");
1814218389
return JIM_ERR;
1814318390
}
18144
- Jim_SetResultBool(interp, Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3,
18145
- &objPtr, JIM_ERRMSG) == JIM_OK);
18146
- return JIM_OK;
18391
+ else {
18392
+ int rc = Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, JIM_ERRMSG);
18393
+ if (rc < 0) {
18394
+ return JIM_ERR;
18395
+ }
18396
+ Jim_SetResultBool(interp, rc == JIM_OK);
18397
+ return JIM_OK;
18398
+ }
1814718399
1814818400
case OPT_UNSET:
1814918401
if (argc < 4) {
1815018402
Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?");
1815118403
return JIM_ERR;
1815218404
}
18153
- return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_NONE);
18405
+ if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) {
18406
+ return JIM_ERR;
18407
+ }
18408
+ return JIM_OK;
1815418409
1815518410
case OPT_KEYS:
1815618411
if (argc != 3 && argc != 4) {
18157
- Jim_WrongNumArgs(interp, 2, argv, "dictVar ?pattern?");
18412
+ Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?");
1815818413
return JIM_ERR;
1815918414
}
1816018415
return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL);
1816118416
18162
- case OPT_SIZE: {
18163
- int size;
18164
-
18417
+ case OPT_SIZE:
1816518418
if (argc != 3) {
18166
- Jim_WrongNumArgs(interp, 2, argv, "dictVar");
18419
+ Jim_WrongNumArgs(interp, 2, argv, "dictionary");
1816718420
return JIM_ERR;
1816818421
}
18169
-
18170
- size = Jim_DictSize(interp, argv[2]);
18171
- if (size < 0) {
18422
+ else if (Jim_DictSize(interp, argv[2]) < 0) {
1817218423
return JIM_ERR;
1817318424
}
18174
- Jim_SetResultInt(interp, size);
18425
+ Jim_SetResultInt(interp, Jim_DictSize(interp, argv[2]));
1817518426
return JIM_OK;
18176
- }
1817718427
1817818428
case OPT_MERGE:
1817918429
if (argc == 2) {
1818018430
return JIM_OK;
1818118431
}
18182
- else if (SetDictFromAny(interp, argv[2]) != JIM_OK) {
18183
- return JIM_ERR;
18184
- }
18185
- else {
18186
- return Jim_EvalPrefix(interp, "dict merge", argc - 2, argv + 2);
18187
- }
18188
-
18189
- case OPT_WITH:
18190
- if (argc < 4) {
18191
- Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script");
18192
- return JIM_ERR;
18193
- }
18194
- else if (Jim_GetVariable(interp, argv[2], JIM_ERRMSG) == NULL) {
18195
- return JIM_ERR;
18196
- }
18197
- else {
18198
- return Jim_EvalPrefix(interp, "dict with", argc - 2, argv + 2);
18199
- }
18432
+ if (Jim_DictSize(interp, argv[2]) < 0) {
18433
+ return JIM_ERR;
18434
+ }
18435
+
18436
+ break;
18437
+
18438
+ case OPT_UPDATE:
18439
+ if (argc < 6 || argc % 2) {
18440
+
18441
+ argc = 2;
18442
+ }
18443
+ break;
1820018444
1820118445
case OPT_CREATE:
1820218446
if (argc % 2) {
1820318447
Jim_WrongNumArgs(interp, 2, argv, "?key value ...?");
1820418448
return JIM_ERR;
1820518449
}
1820618450
objPtr = Jim_NewDictObj(interp, argv + 2, argc - 2);
1820718451
Jim_SetResult(interp, objPtr);
1820818452
return JIM_OK;
18453
+
18454
+ case OPT_INFO:
18455
+ if (argc != 3) {
18456
+ Jim_WrongNumArgs(interp, 2, argv, "dictionary");
18457
+ return JIM_ERR;
18458
+ }
18459
+ return Jim_DictInfo(interp, argv[2]);
1820918460
}
18210
- return JIM_ERR;
18461
+
18462
+ return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2);
1821118463
}
1821218464
1821318465
1821418466
static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1821518467
{
@@ -18267,11 +18519,11 @@
1826718519
};
1826818520
enum
1826918521
{ INFO_BODY, INFO_STATICS, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL,
1827018522
INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS,
1827118523
INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE,
18272
- INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS
18524
+ INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS,
1827318525
};
1827418526
1827518527
#ifdef jim_ext_namespace
1827618528
int nons = 0;
1827718529
@@ -19047,11 +19299,11 @@
1904719299
}
1904819300
}
1904919301
1905019302
static const struct {
1905119303
const char *name;
19052
- Jim_CmdProc cmdProc;
19304
+ Jim_CmdProc *cmdProc;
1905319305
} Jim_CoreCommandsTable[] = {
1905419306
{"alias", Jim_AliasCoreCommand},
1905519307
{"set", Jim_SetCoreCommand},
1905619308
{"unset", Jim_UnsetCoreCommand},
1905719309
{"puts", Jim_PutsCoreCommand},
@@ -19279,10 +19531,12 @@
1927919531
}
1928019532
1928119533
len += extra;
1928219534
buf = Jim_Alloc(len + 1);
1928319535
len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]);
19536
+
19537
+ va_end(args);
1928419538
1928519539
Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len));
1928619540
}
1928719541
1928819542
@@ -19530,23 +19784,22 @@
1953019784
1953119785
#include <ctype.h>
1953219786
#include <string.h>
1953319787
1953419788
19535
-#define JIM_UTF_MAX 3
1953619789
#define JIM_INTEGER_SPACE 24
1953719790
#define MAX_FLOAT_WIDTH 320
1953819791
1953919792
Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv)
1954019793
{
1954119794
const char *span, *format, *formatEnd, *msg;
1954219795
int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0;
1954319796
static const char * const mixedXPG =
19544
- "cannot mix \"%\" and \"%n$\" conversion specifiers";
19797
+ "cannot mix \"%\" and \"%n$\" conversion specifiers";
1954519798
static const char * const badIndex[2] = {
19546
- "not enough arguments for all format specifiers",
19547
- "\"%n$\" argument index out of range"
19799
+ "not enough arguments for all format specifiers",
19800
+ "\"%n$\" argument index out of range"
1954819801
};
1954919802
int formatLen;
1955019803
Jim_Obj *resultPtr;
1955119804
1955219805
char *num_buffer = NULL;
@@ -19555,319 +19808,349 @@
1955519808
span = format = Jim_GetString(fmtObjPtr, &formatLen);
1955619809
formatEnd = format + formatLen;
1955719810
resultPtr = Jim_NewEmptyStringObj(interp);
1955819811
1955919812
while (format != formatEnd) {
19560
- char *end;
19561
- int gotMinus, sawFlag;
19562
- int gotPrecision, useShort;
19563
- long width, precision;
19564
- int newXpg;
19565
- int ch;
19566
- int step;
19567
- int doubleType;
19568
- char pad = ' ';
19569
- char spec[2*JIM_INTEGER_SPACE + 12];
19570
- char *p;
19571
-
19572
- int formatted_chars;
19573
- int formatted_bytes;
19574
- const char *formatted_buf;
19575
-
19576
- step = utf8_tounicode(format, &ch);
19577
- format += step;
19578
- if (ch != '%') {
19579
- numBytes += step;
19580
- continue;
19581
- }
19582
- if (numBytes) {
19583
- Jim_AppendString(interp, resultPtr, span, numBytes);
19584
- numBytes = 0;
19585
- }
19586
-
19587
-
19588
- step = utf8_tounicode(format, &ch);
19589
- if (ch == '%') {
19590
- span = format;
19591
- numBytes = step;
19592
- format += step;
19593
- continue;
19594
- }
19595
-
19596
-
19597
- newXpg = 0;
19598
- if (isdigit(ch)) {
19599
- int position = strtoul(format, &end, 10);
19600
- if (*end == '$') {
19601
- newXpg = 1;
19602
- objIndex = position - 1;
19603
- format = end + 1;
19604
- step = utf8_tounicode(format, &ch);
19605
- }
19606
- }
19607
- if (newXpg) {
19608
- if (gotSequential) {
19609
- msg = mixedXPG;
19610
- goto errorMsg;
19611
- }
19612
- gotXpg = 1;
19613
- } else {
19614
- if (gotXpg) {
19615
- msg = mixedXPG;
19616
- goto errorMsg;
19617
- }
19618
- gotSequential = 1;
19619
- }
19620
- if ((objIndex < 0) || (objIndex >= objc)) {
19621
- msg = badIndex[gotXpg];
19622
- goto errorMsg;
19623
- }
19624
-
19625
- p = spec;
19626
- *p++ = '%';
19627
-
19628
- gotMinus = 0;
19629
- sawFlag = 1;
19630
- do {
19631
- switch (ch) {
19632
- case '-':
19633
- gotMinus = 1;
19634
- break;
19635
- case '0':
19636
- pad = ch;
19637
- break;
19638
- case ' ':
19639
- case '+':
19640
- case '#':
19641
- break;
19642
- default:
19643
- sawFlag = 0;
19644
- continue;
19645
- }
19646
- *p++ = ch;
19647
- format += step;
19648
- step = utf8_tounicode(format, &ch);
19649
- } while (sawFlag);
19650
-
19651
-
19652
- width = 0;
19653
- if (isdigit(ch)) {
19654
- width = strtoul(format, &end, 10);
19655
- format = end;
19656
- step = utf8_tounicode(format, &ch);
19657
- } else if (ch == '*') {
19658
- if (objIndex >= objc - 1) {
19659
- msg = badIndex[gotXpg];
19660
- goto errorMsg;
19661
- }
19662
- if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) {
19663
- goto error;
19664
- }
19665
- if (width < 0) {
19666
- width = -width;
19667
- if (!gotMinus) {
19668
- *p++ = '-';
19669
- gotMinus = 1;
19670
- }
19671
- }
19672
- objIndex++;
19673
- format += step;
19674
- step = utf8_tounicode(format, &ch);
19675
- }
19676
-
19677
-
19678
- gotPrecision = precision = 0;
19679
- if (ch == '.') {
19680
- gotPrecision = 1;
19681
- format += step;
19682
- step = utf8_tounicode(format, &ch);
19683
- }
19684
- if (isdigit(ch)) {
19685
- precision = strtoul(format, &end, 10);
19686
- format = end;
19687
- step = utf8_tounicode(format, &ch);
19688
- } else if (ch == '*') {
19689
- if (objIndex >= objc - 1) {
19690
- msg = badIndex[gotXpg];
19691
- goto errorMsg;
19692
- }
19693
- if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) {
19694
- goto error;
19695
- }
19696
-
19697
-
19698
- if (precision < 0) {
19699
- precision = 0;
19700
- }
19701
- objIndex++;
19702
- format += step;
19703
- step = utf8_tounicode(format, &ch);
19704
- }
19705
-
19706
-
19707
- useShort = 0;
19708
- if (ch == 'h') {
19709
- useShort = 1;
19710
- format += step;
19711
- step = utf8_tounicode(format, &ch);
19712
- } else if (ch == 'l') {
19713
-
19714
- format += step;
19715
- step = utf8_tounicode(format, &ch);
19716
- if (ch == 'l') {
19717
- format += step;
19718
- step = utf8_tounicode(format, &ch);
19719
- }
19720
- }
19721
-
19722
- format += step;
19723
- span = format;
19724
-
19725
-
19726
- if (ch == 'i') {
19727
- ch = 'd';
19728
- }
19729
-
19730
- doubleType = 0;
19731
-
19732
- switch (ch) {
19733
- case '\0':
19734
- msg = "format string ended in middle of field specifier";
19735
- goto errorMsg;
19736
- case 's': {
19737
- formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
19738
- formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
19739
- if (gotPrecision && (precision < formatted_chars)) {
19740
-
19741
- formatted_chars = precision;
19742
- formatted_bytes = utf8_index(formatted_buf, precision);
19743
- }
19744
- break;
19745
- }
19746
- case 'c': {
19747
- jim_wide code;
19748
-
19749
- if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
19750
- goto error;
19751
- }
19752
-
19753
- formatted_bytes = utf8_fromunicode(spec, code);
19754
- formatted_buf = spec;
19755
- formatted_chars = 1;
19756
- break;
19757
- }
19758
-
19759
- case 'e':
19760
- case 'E':
19761
- case 'f':
19762
- case 'g':
19763
- case 'G':
19764
- doubleType = 1;
19765
-
19766
- case 'd':
19767
- case 'u':
19768
- case 'o':
19769
- case 'x':
19770
- case 'X': {
19771
- jim_wide w;
19772
- double d;
19773
- int length;
19774
-
19775
-
19776
- if (width) {
19777
- p += sprintf(p, "%ld", width);
19778
- }
19779
- if (gotPrecision) {
19780
- p += sprintf(p, ".%ld", precision);
19781
- }
19782
-
19783
-
19784
- if (doubleType) {
19785
- if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
19786
- goto error;
19787
- }
19788
- length = MAX_FLOAT_WIDTH;
19789
- }
19790
- else {
19791
- if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) {
19792
- goto error;
19793
- }
19794
- length = JIM_INTEGER_SPACE;
19795
- if (useShort) {
19796
- *p++ = 'h';
19797
- if (ch == 'd') {
19798
- w = (short)w;
19799
- }
19800
- else {
19801
- w = (unsigned short)w;
19802
- }
19803
- }
19804
- else {
19805
- *p++ = 'l';
19806
-#ifdef HAVE_LONG_LONG
19807
- if (sizeof(long long) == sizeof(jim_wide)) {
19808
- *p++ = 'l';
19809
- }
19810
-#endif
19811
- }
19812
- }
19813
-
19814
- *p++ = (char) ch;
19815
- *p = '\0';
19816
-
19817
-
19818
- if (width > length) {
19819
- length = width;
19820
- }
19821
- if (gotPrecision) {
19822
- length += precision;
19823
- }
19824
-
19825
-
19826
- if (num_buffer_size < length + 1) {
19827
- num_buffer_size = length + 1;
19828
- num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
19829
- }
19830
-
19831
- if (doubleType) {
19832
- snprintf(num_buffer, length + 1, spec, d);
19833
- }
19834
- else {
19835
- formatted_bytes = snprintf(num_buffer, length + 1, spec, w);
19836
- }
19837
- formatted_chars = formatted_bytes = strlen(num_buffer);
19838
- formatted_buf = num_buffer;
19839
- break;
19840
- }
19841
-
19842
- default: {
19843
-
19844
- spec[0] = ch;
19845
- spec[1] = '\0';
19846
- Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
19847
- goto error;
19848
- }
19849
- }
19850
-
19851
- if (!gotMinus) {
19852
- while (formatted_chars < width) {
19853
- Jim_AppendString(interp, resultPtr, &pad, 1);
19854
- formatted_chars++;
19855
- }
19856
- }
19857
-
19858
- Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes);
19859
-
19860
- while (formatted_chars < width) {
19861
- Jim_AppendString(interp, resultPtr, &pad, 1);
19862
- formatted_chars++;
19863
- }
19864
-
19865
- objIndex += gotSequential;
19866
- }
19867
- if (numBytes) {
19868
- Jim_AppendString(interp, resultPtr, span, numBytes);
19813
+ char *end;
19814
+ int gotMinus, sawFlag;
19815
+ int gotPrecision, useShort;
19816
+ long width, precision;
19817
+ int newXpg;
19818
+ int ch;
19819
+ int step;
19820
+ int doubleType;
19821
+ char pad = ' ';
19822
+ char spec[2*JIM_INTEGER_SPACE + 12];
19823
+ char *p;
19824
+
19825
+ int formatted_chars;
19826
+ int formatted_bytes;
19827
+ const char *formatted_buf;
19828
+
19829
+ step = utf8_tounicode(format, &ch);
19830
+ format += step;
19831
+ if (ch != '%') {
19832
+ numBytes += step;
19833
+ continue;
19834
+ }
19835
+ if (numBytes) {
19836
+ Jim_AppendString(interp, resultPtr, span, numBytes);
19837
+ numBytes = 0;
19838
+ }
19839
+
19840
+
19841
+ step = utf8_tounicode(format, &ch);
19842
+ if (ch == '%') {
19843
+ span = format;
19844
+ numBytes = step;
19845
+ format += step;
19846
+ continue;
19847
+ }
19848
+
19849
+
19850
+ newXpg = 0;
19851
+ if (isdigit(ch)) {
19852
+ int position = strtoul(format, &end, 10);
19853
+ if (*end == '$') {
19854
+ newXpg = 1;
19855
+ objIndex = position - 1;
19856
+ format = end + 1;
19857
+ step = utf8_tounicode(format, &ch);
19858
+ }
19859
+ }
19860
+ if (newXpg) {
19861
+ if (gotSequential) {
19862
+ msg = mixedXPG;
19863
+ goto errorMsg;
19864
+ }
19865
+ gotXpg = 1;
19866
+ } else {
19867
+ if (gotXpg) {
19868
+ msg = mixedXPG;
19869
+ goto errorMsg;
19870
+ }
19871
+ gotSequential = 1;
19872
+ }
19873
+ if ((objIndex < 0) || (objIndex >= objc)) {
19874
+ msg = badIndex[gotXpg];
19875
+ goto errorMsg;
19876
+ }
19877
+
19878
+ p = spec;
19879
+ *p++ = '%';
19880
+
19881
+ gotMinus = 0;
19882
+ sawFlag = 1;
19883
+ do {
19884
+ switch (ch) {
19885
+ case '-':
19886
+ gotMinus = 1;
19887
+ break;
19888
+ case '0':
19889
+ pad = ch;
19890
+ break;
19891
+ case ' ':
19892
+ case '+':
19893
+ case '#':
19894
+ break;
19895
+ default:
19896
+ sawFlag = 0;
19897
+ continue;
19898
+ }
19899
+ *p++ = ch;
19900
+ format += step;
19901
+ step = utf8_tounicode(format, &ch);
19902
+ } while (sawFlag);
19903
+
19904
+
19905
+ width = 0;
19906
+ if (isdigit(ch)) {
19907
+ width = strtoul(format, &end, 10);
19908
+ format = end;
19909
+ step = utf8_tounicode(format, &ch);
19910
+ } else if (ch == '*') {
19911
+ if (objIndex >= objc - 1) {
19912
+ msg = badIndex[gotXpg];
19913
+ goto errorMsg;
19914
+ }
19915
+ if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) {
19916
+ goto error;
19917
+ }
19918
+ if (width < 0) {
19919
+ width = -width;
19920
+ if (!gotMinus) {
19921
+ *p++ = '-';
19922
+ gotMinus = 1;
19923
+ }
19924
+ }
19925
+ objIndex++;
19926
+ format += step;
19927
+ step = utf8_tounicode(format, &ch);
19928
+ }
19929
+
19930
+
19931
+ gotPrecision = precision = 0;
19932
+ if (ch == '.') {
19933
+ gotPrecision = 1;
19934
+ format += step;
19935
+ step = utf8_tounicode(format, &ch);
19936
+ }
19937
+ if (isdigit(ch)) {
19938
+ precision = strtoul(format, &end, 10);
19939
+ format = end;
19940
+ step = utf8_tounicode(format, &ch);
19941
+ } else if (ch == '*') {
19942
+ if (objIndex >= objc - 1) {
19943
+ msg = badIndex[gotXpg];
19944
+ goto errorMsg;
19945
+ }
19946
+ if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) {
19947
+ goto error;
19948
+ }
19949
+
19950
+
19951
+ if (precision < 0) {
19952
+ precision = 0;
19953
+ }
19954
+ objIndex++;
19955
+ format += step;
19956
+ step = utf8_tounicode(format, &ch);
19957
+ }
19958
+
19959
+
19960
+ useShort = 0;
19961
+ if (ch == 'h') {
19962
+ useShort = 1;
19963
+ format += step;
19964
+ step = utf8_tounicode(format, &ch);
19965
+ } else if (ch == 'l') {
19966
+
19967
+ format += step;
19968
+ step = utf8_tounicode(format, &ch);
19969
+ if (ch == 'l') {
19970
+ format += step;
19971
+ step = utf8_tounicode(format, &ch);
19972
+ }
19973
+ }
19974
+
19975
+ format += step;
19976
+ span = format;
19977
+
19978
+
19979
+ if (ch == 'i') {
19980
+ ch = 'd';
19981
+ }
19982
+
19983
+ doubleType = 0;
19984
+
19985
+ switch (ch) {
19986
+ case '\0':
19987
+ msg = "format string ended in middle of field specifier";
19988
+ goto errorMsg;
19989
+ case 's': {
19990
+ formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
19991
+ formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
19992
+ if (gotPrecision && (precision < formatted_chars)) {
19993
+
19994
+ formatted_chars = precision;
19995
+ formatted_bytes = utf8_index(formatted_buf, precision);
19996
+ }
19997
+ break;
19998
+ }
19999
+ case 'c': {
20000
+ jim_wide code;
20001
+
20002
+ if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
20003
+ goto error;
20004
+ }
20005
+
20006
+ formatted_bytes = utf8_getchars(spec, code);
20007
+ formatted_buf = spec;
20008
+ formatted_chars = 1;
20009
+ break;
20010
+ }
20011
+ case 'b': {
20012
+ unsigned jim_wide w;
20013
+ int length;
20014
+ int i;
20015
+ int j;
20016
+
20017
+ if (Jim_GetWide(interp, objv[objIndex], (jim_wide *)&w) != JIM_OK) {
20018
+ goto error;
20019
+ }
20020
+ length = sizeof(w) * 8;
20021
+
20022
+
20023
+
20024
+ if (num_buffer_size < length + 1) {
20025
+ num_buffer_size = length + 1;
20026
+ num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
20027
+ }
20028
+
20029
+ j = 0;
20030
+ for (i = length; i > 0; ) {
20031
+ i--;
20032
+ if (w & ((unsigned jim_wide)1 << i)) {
20033
+ num_buffer[j++] = '1';
20034
+ }
20035
+ else if (j || i == 0) {
20036
+ num_buffer[j++] = '0';
20037
+ }
20038
+ }
20039
+ num_buffer[j] = 0;
20040
+ formatted_chars = formatted_bytes = j;
20041
+ formatted_buf = num_buffer;
20042
+ break;
20043
+ }
20044
+
20045
+ case 'e':
20046
+ case 'E':
20047
+ case 'f':
20048
+ case 'g':
20049
+ case 'G':
20050
+ doubleType = 1;
20051
+
20052
+ case 'd':
20053
+ case 'u':
20054
+ case 'o':
20055
+ case 'x':
20056
+ case 'X': {
20057
+ jim_wide w;
20058
+ double d;
20059
+ int length;
20060
+
20061
+
20062
+ if (width) {
20063
+ p += sprintf(p, "%ld", width);
20064
+ }
20065
+ if (gotPrecision) {
20066
+ p += sprintf(p, ".%ld", precision);
20067
+ }
20068
+
20069
+
20070
+ if (doubleType) {
20071
+ if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
20072
+ goto error;
20073
+ }
20074
+ length = MAX_FLOAT_WIDTH;
20075
+ }
20076
+ else {
20077
+ if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) {
20078
+ goto error;
20079
+ }
20080
+ length = JIM_INTEGER_SPACE;
20081
+ if (useShort) {
20082
+ if (ch == 'd') {
20083
+ w = (short)w;
20084
+ }
20085
+ else {
20086
+ w = (unsigned short)w;
20087
+ }
20088
+ }
20089
+ *p++ = 'l';
20090
+#ifdef HAVE_LONG_LONG
20091
+ if (sizeof(long long) == sizeof(jim_wide)) {
20092
+ *p++ = 'l';
20093
+ }
20094
+#endif
20095
+ }
20096
+
20097
+ *p++ = (char) ch;
20098
+ *p = '\0';
20099
+
20100
+
20101
+ if (width > length) {
20102
+ length = width;
20103
+ }
20104
+ if (gotPrecision) {
20105
+ length += precision;
20106
+ }
20107
+
20108
+
20109
+ if (num_buffer_size < length + 1) {
20110
+ num_buffer_size = length + 1;
20111
+ num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
20112
+ }
20113
+
20114
+ if (doubleType) {
20115
+ snprintf(num_buffer, length + 1, spec, d);
20116
+ }
20117
+ else {
20118
+ formatted_bytes = snprintf(num_buffer, length + 1, spec, w);
20119
+ }
20120
+ formatted_chars = formatted_bytes = strlen(num_buffer);
20121
+ formatted_buf = num_buffer;
20122
+ break;
20123
+ }
20124
+
20125
+ default: {
20126
+
20127
+ spec[0] = ch;
20128
+ spec[1] = '\0';
20129
+ Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
20130
+ goto error;
20131
+ }
20132
+ }
20133
+
20134
+ if (!gotMinus) {
20135
+ while (formatted_chars < width) {
20136
+ Jim_AppendString(interp, resultPtr, &pad, 1);
20137
+ formatted_chars++;
20138
+ }
20139
+ }
20140
+
20141
+ Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes);
20142
+
20143
+ while (formatted_chars < width) {
20144
+ Jim_AppendString(interp, resultPtr, &pad, 1);
20145
+ formatted_chars++;
20146
+ }
20147
+
20148
+ objIndex += gotSequential;
20149
+ }
20150
+ if (numBytes) {
20151
+ Jim_AppendString(interp, resultPtr, span, numBytes);
1986920152
}
1987020153
1987120154
Jim_Free(num_buffer);
1987220155
return resultPtr;
1987320156
@@ -19876,21 +20159,22 @@
1987620159
error:
1987720160
Jim_FreeNewObj(interp, resultPtr);
1987820161
Jim_Free(num_buffer);
1987920162
return NULL;
1988020163
}
20164
+
20165
+
20166
+#if defined(JIM_REGEXP)
1988120167
#include <stdio.h>
1988220168
#include <ctype.h>
1988320169
#include <stdlib.h>
1988420170
#include <string.h>
1988520171
19886
-
19887
-#if !defined(HAVE_REGCOMP) || defined(JIM_REGEXP)
19888
-
1988920172
1989020173
1989120174
#define REG_MAX_PAREN 100
20175
+
1989220176
1989320177
1989420178
#define END 0
1989520179
#define BOL 1
1989620180
#define EOL 2
@@ -19899,23 +20183,27 @@
1989920183
#define ANYBUT 5
1990020184
#define BRANCH 6
1990120185
#define BACK 7
1990220186
#define EXACTLY 8
1990320187
#define NOTHING 9
19904
-#define REP 10
20188
+#define REP 10
1990520189
#define REPMIN 11
1990620190
#define REPX 12
1990720191
#define REPXMIN 13
1990820192
1990920193
#define WORDA 15
1991020194
#define WORDZ 16
19911
-#define OPENNC 19
19912
-#define OPEN 20
20195
+
20196
+#define OPENNC 1000
20197
+#define OPEN 1001
1991320198
19914
-#define CLOSE (OPEN+REG_MAX_PAREN+1)
20199
+
20200
+
20201
+
20202
+#define CLOSENC 2000
20203
+#define CLOSE 2001
1991520204
#define CLOSE_END (CLOSE+REG_MAX_PAREN)
19916
-#define CLOSENC (CLOSE-1)
1991720205
1991820206
#define REG_MAGIC 0xFADED00D
1991920207
1992020208
1992120209
#define OP(preg, p) (preg->program[p])
@@ -19925,15 +20213,15 @@
1992520213
1992620214
1992720215
1992820216
#define FAIL(R,M) { (R)->err = (M); return (M); }
1992920217
#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{')
19930
-#define META "^$.[()|?{+*"
20218
+#define META "^$.[()|?{+*"
1993120219
19932
-#define HASWIDTH 01
19933
-#define SIMPLE 02
19934
-#define SPSTART 04
20220
+#define HASWIDTH 1
20221
+#define SIMPLE 2
20222
+#define SPSTART 4
1993520223
#define WORST 0
1993620224
1993720225
#define MAX_REP_COUNT 1000000
1993820226
1993920227
static int reg(regex_t *preg, int paren , int *flagp );
@@ -19942,13 +20230,13 @@
1994220230
static int regatom(regex_t *preg, int *flagp );
1994320231
static int regnode(regex_t *preg, int op );
1994420232
static int regnext(regex_t *preg, int p );
1994520233
static void regc(regex_t *preg, int b );
1994620234
static int reginsert(regex_t *preg, int op, int size, int opnd );
19947
-static void regtail_(regex_t *preg, int p, int val, int line );
20235
+static void regtail(regex_t *preg, int p, int val);
1994820236
static void regoptail(regex_t *preg, int p, int val );
19949
-#define regtail(PREG, P, VAL) regtail_(PREG, P, VAL, __LINE__)
20237
+static int regopsize(regex_t *preg, int p );
1995020238
1995120239
static int reg_range_find(const int *string, int c);
1995220240
static const char *str_find(const char *string, int c, int nocase);
1995320241
static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase);
1995420242
@@ -19985,13 +20273,10 @@
1998520273
FAIL(preg, REG_ERR_NULL_ARGUMENT);
1998620274
1998720275
1998820276
preg->cflags = cflags;
1998920277
preg->regparse = exp;
19990
-
19991
- preg->program = NULL;
19992
- preg->proglen = 0;
1999320278
1999420279
1999520280
preg->proglen = (strlen(exp) + 1) * 5;
1999620281
preg->program = malloc(preg->proglen * sizeof(int));
1999720282
if (preg->program == NULL)
@@ -20152,11 +20437,10 @@
2015220437
{
2015320438
int ret;
2015420439
char op;
2015520440
int next;
2015620441
int flags;
20157
- int chain = 0;
2015820442
int min;
2015920443
int max;
2016020444
2016120445
ret = regatom(preg, &flags);
2016220446
if (ret == 0)
@@ -20235,11 +20519,11 @@
2023520519
if (ISMULT(*preg->regparse)) {
2023620520
preg->err = REG_ERR_NESTED_COUNT;
2023720521
return 0;
2023820522
}
2023920523
20240
- return chain ? chain : ret;
20524
+ return ret;
2024120525
}
2024220526
2024320527
static void reg_addrange(regex_t *preg, int lower, int upper)
2024420528
{
2024520529
if (lower > upper) {
@@ -20329,10 +20613,11 @@
2032920613
break;
2033020614
case 'U':
2033120615
if ((n = parse_hex(s, 8, ch)) > 0) {
2033220616
s += n;
2033320617
}
20618
+ break;
2033420619
case 'x':
2033520620
if ((n = parse_hex(s, 2, ch)) > 0) {
2033620621
s += n;
2033720622
}
2033820623
break;
@@ -20577,10 +20862,11 @@
2057720862
2057820863
static int regnode(regex_t *preg, int op)
2057920864
{
2058020865
reg_grow(preg, 2);
2058120866
20867
+
2058220868
preg->program[preg->p++] = op;
2058320869
preg->program[preg->p++] = 0;
2058420870
2058520871
2058620872
return preg->p - 2;
@@ -20606,11 +20892,11 @@
2060620892
preg->p += size;
2060720893
2060820894
return opnd + size;
2060920895
}
2061020896
20611
-static void regtail_(regex_t *preg, int p, int val, int line )
20897
+static void regtail(regex_t *preg, int p, int val)
2061220898
{
2061320899
int scan;
2061420900
int temp;
2061520901
int offset;
2061620902
@@ -20669,36 +20955,16 @@
2066920955
preg->pmatch = pmatch;
2067020956
preg->nmatch = nmatch;
2067120957
preg->start = string;
2067220958
2067320959
20674
- for (scan = OPERAND(1); scan != 0; ) {
20675
- switch (OP(preg, scan)) {
20676
- case REP:
20677
- case REPMIN:
20678
- case REPX:
20679
- case REPXMIN:
20680
- preg->program[scan + 4] = 0;
20681
- scan += 5;
20682
- break;
20683
-
20684
- case ANYOF:
20685
- case ANYBUT:
20686
- case EXACTLY:
20687
- scan += 2;
20688
- while (preg->program[scan++]) {
20689
- }
20690
- break;
20691
-
20692
- case END:
20693
- scan = 0;
20694
- break;
20695
-
20696
- default:
20697
- scan += 2;
20698
- break;
20699
- }
20960
+ for (scan = OPERAND(1); scan != 0; scan += regopsize(preg, scan)) {
20961
+ int op = OP(preg, scan);
20962
+ if (op == END)
20963
+ break;
20964
+ if (op == REPX || op == REPXMIN)
20965
+ preg->program[scan + 4] = 0;
2070020966
}
2070120967
2070220968
2070320969
if (preg->regmust != 0) {
2070420970
s = string;
@@ -20950,10 +21216,11 @@
2095021216
2095121217
static int regmatch(regex_t *preg, int prog)
2095221218
{
2095321219
int scan;
2095421220
int next;
21221
+ const char *save;
2095521222
2095621223
scan = prog;
2095721224
2095821225
#ifdef DEBUG
2095921226
if (scan != 0 && regnarrate)
@@ -21038,27 +21305,24 @@
2103821305
break;
2103921306
case NOTHING:
2104021307
break;
2104121308
case BACK:
2104221309
break;
21043
- case BRANCH: {
21044
- const char *save;
21045
-
21046
- if (OP(preg, next) != BRANCH)
21047
- next = OPERAND(scan);
21048
- else {
21049
- do {
21050
- save = preg->reginput;
21051
- if (regmatch(preg, OPERAND(scan))) {
21052
- return(1);
21053
- }
21054
- preg->reginput = save;
21055
- scan = regnext(preg, scan);
21056
- } while (scan != 0 && OP(preg, scan) == BRANCH);
21057
- return(0);
21058
-
21059
- }
21310
+ case BRANCH:
21311
+ if (OP(preg, next) != BRANCH)
21312
+ next = OPERAND(scan);
21313
+ else {
21314
+ do {
21315
+ save = preg->reginput;
21316
+ if (regmatch(preg, OPERAND(scan))) {
21317
+ return(1);
21318
+ }
21319
+ preg->reginput = save;
21320
+ scan = regnext(preg, scan);
21321
+ } while (scan != 0 && OP(preg, scan) == BRANCH);
21322
+ return(0);
21323
+
2106021324
}
2106121325
break;
2106221326
case REP:
2106321327
case REPMIN:
2106421328
return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN);
@@ -21066,43 +21330,35 @@
2106621330
case REPX:
2106721331
case REPXMIN:
2106821332
return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN);
2106921333
2107021334
case END:
21071
- return(1);
21072
- break;
21335
+ return 1;
2107321336
2107421337
case OPENNC:
2107521338
case CLOSENC:
21076
- if (regmatch(preg, next)) {
21077
- return 1;
21078
- }
21079
- return 0;
21339
+ return regmatch(preg, next);
2108021340
2108121341
default:
2108221342
if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) {
21083
- const char *save;
21084
-
2108521343
save = preg->reginput;
21086
-
2108721344
if (regmatch(preg, next)) {
21088
- int no;
2108921345
if (OP(preg, scan) < CLOSE) {
21090
- no = OP(preg, scan) - OPEN;
21346
+ int no = OP(preg, scan) - OPEN;
2109121347
if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) {
2109221348
preg->pmatch[no].rm_so = save - preg->start;
2109321349
}
2109421350
}
2109521351
else {
21096
- no = OP(preg, scan) - CLOSE;
21352
+ int no = OP(preg, scan) - CLOSE;
2109721353
if (no < preg->nmatch && preg->pmatch[no].rm_eo == -1) {
2109821354
preg->pmatch[no].rm_eo = save - preg->start;
2109921355
}
2110021356
}
2110121357
return(1);
21102
- } else
21103
- return(0);
21358
+ }
21359
+ return(0);
2110421360
}
2110521361
return REG_ERR_INTERNAL;
2110621362
}
2110721363
2110821364
scan = next;
@@ -21181,10 +21437,32 @@
2118121437
if (OP(preg, p) == BACK)
2118221438
return(p-offset);
2118321439
else
2118421440
return(p+offset);
2118521441
}
21442
+
21443
+static int regopsize(regex_t *preg, int p )
21444
+{
21445
+
21446
+ switch (OP(preg, p)) {
21447
+ case REP:
21448
+ case REPMIN:
21449
+ case REPX:
21450
+ case REPXMIN:
21451
+ return 5;
21452
+
21453
+ case ANYOF:
21454
+ case ANYBUT:
21455
+ case EXACTLY: {
21456
+ int s = p + 2;
21457
+ while (preg->program[s++]) {
21458
+ }
21459
+ return s - p;
21460
+ }
21461
+ }
21462
+ return 2;
21463
+}
2118621464
2118721465
2118821466
size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
2118921467
{
2119021468
static const char *error_strings[] = {
@@ -21359,19 +21637,24 @@
2135921637
char *Jim_HistoryGetline(const char *prompt)
2136021638
{
2136121639
#ifdef USE_LINENOISE
2136221640
return linenoise(prompt);
2136321641
#else
21642
+ int len;
2136421643
char *line = malloc(MAX_LINE_LEN);
2136521644
2136621645
fputs(prompt, stdout);
2136721646
fflush(stdout);
2136821647
2136921648
if (fgets(line, MAX_LINE_LEN, stdin) == NULL) {
2137021649
free(line);
2137121650
return NULL;
2137221651
}
21652
+ len = strlen(line);
21653
+ if (len && line[len - 1] == '\n') {
21654
+ line[len - 1] = '\0';
21655
+ }
2137321656
return line;
2137421657
#endif
2137521658
}
2137621659
2137721660
void Jim_HistoryLoad(const char *filename)
@@ -21422,11 +21705,11 @@
2142221705
snprintf(history_file, history_len, "%s/.jim_history", home);
2142321706
Jim_HistoryLoad(history_file);
2142421707
}
2142521708
#endif
2142621709
21427
- printf("Welcome to Jim version %d.%d" JIM_NL,
21710
+ printf("Welcome to Jim version %d.%d\n",
2142821711
JIM_VERSION / 100, JIM_VERSION % 100);
2142921712
Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1");
2143021713
2143121714
while (1) {
2143221715
Jim_Obj *scriptObjPtr;
@@ -21534,10 +21817,16 @@
2153421817
}
2153521818
2153621819
Jim_SetVariableStr(interp, "argv", listObj);
2153721820
Jim_SetVariableStr(interp, "argc", Jim_NewIntObj(interp, argc));
2153821821
}
21822
+
21823
+static void JimPrintErrorMessage(Jim_Interp *interp)
21824
+{
21825
+ Jim_MakeErrorMessage(interp);
21826
+ fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21827
+}
2153921828
2154021829
int main(int argc, char *const argv[])
2154121830
{
2154221831
int retcode;
2154321832
Jim_Interp *interp;
@@ -21551,22 +21840,20 @@
2155121840
interp = Jim_CreateInterp();
2155221841
Jim_RegisterCoreCommands(interp);
2155321842
2155421843
2155521844
if (Jim_InitStaticExtensions(interp) != JIM_OK) {
21556
- Jim_MakeErrorMessage(interp);
21557
- fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21845
+ JimPrintErrorMessage(interp);
2155821846
}
2155921847
2156021848
Jim_SetVariableStrWithStr(interp, "jim_argv0", argv[0]);
2156121849
Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0");
2156221850
retcode = Jim_initjimshInit(interp);
2156321851
2156421852
if (argc == 1) {
2156521853
if (retcode == JIM_ERR) {
21566
- Jim_MakeErrorMessage(interp);
21567
- fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21854
+ JimPrintErrorMessage(interp);
2156821855
}
2156921856
if (retcode != JIM_EXIT) {
2157021857
JimSetArgv(interp, 0, NULL);
2157121858
retcode = Jim_InteractivePrompt(interp);
2157221859
}
@@ -21583,12 +21870,11 @@
2158321870
Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1));
2158421871
JimSetArgv(interp, argc - 2, argv + 2);
2158521872
retcode = Jim_EvalFile(interp, argv[1]);
2158621873
}
2158721874
if (retcode == JIM_ERR) {
21588
- Jim_MakeErrorMessage(interp);
21589
- fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21875
+ JimPrintErrorMessage(interp);
2159021876
}
2159121877
}
2159221878
if (retcode == JIM_EXIT) {
2159321879
retcode = Jim_GetExitCode(interp);
2159421880
}
2159521881
--- autosetup/jimsh0.c
+++ autosetup/jimsh0.c
@@ -1,6 +1,6 @@
1 /* This is single source file, bootstrap version of Jim Tcl. See http://jim.berlios.de/ */
2 #define _GNU_SOURCE
3 #define JIM_TCL_COMPAT
4 #define JIM_REFERENCES
5 #define JIM_ANSIC
6 #define JIM_REGEXP
@@ -47,10 +47,14 @@
47 #define JIM_VERSION 75
48 #ifndef JIM_WIN32COMPAT_H
49 #define JIM_WIN32COMPAT_H
50
51
 
 
 
 
52
53
54 #if defined(_WIN32) || defined(WIN32)
55
56 #define HAVE_DLOPEN
@@ -106,17 +110,31 @@
106 } DIR;
107
108 DIR *opendir(const char *name);
109 int closedir(DIR *dir);
110 struct dirent *readdir(DIR *dir);
111 #endif
 
 
 
 
 
112
113 #endif
 
 
 
 
114
115 #endif
116 #ifndef UTF8_UTIL_H
117 #define UTF8_UTIL_H
 
 
 
 
 
118
119
120 #define MAX_UTF8_LEN 4
121
122 int utf8_fromunicode(char *p, unsigned uc);
@@ -125,10 +143,11 @@
125 #include <ctype.h>
126
127
128 #define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B))
129 #define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
 
130 #define utf8_upper(C) toupper(C)
131 #define utf8_title(C) toupper(C)
132 #define utf8_lower(C) tolower(C)
133 #define utf8_index(C, I) (I)
134 #define utf8_charlen(C) 1
@@ -135,10 +154,14 @@
135 #define utf8_prev_len(S, L) 1
136
137 #else
138
139 #endif
 
 
 
 
140
141 #endif
142
143 #ifndef __JIM__H
144 #define __JIM__H
@@ -199,44 +222,34 @@
199 #define JIM_EVAL 7
200
201 #define JIM_MAX_CALLFRAME_DEPTH 1000
202 #define JIM_MAX_EVAL_DEPTH 2000
203
204 #define JIM_NONE 0
205 #define JIM_ERRMSG 1
206
207 #define JIM_UNSHARED 4
208 #define JIM_MUSTEXIST 8
209
210
211 #define JIM_GLOBAL_ONLY 0x100
212
213
214 #define JIM_SUBST_NOVAR 1
215 #define JIM_SUBST_NOCMD 2
216 #define JIM_SUBST_NOESC 4
217 #define JIM_SUBST_FLAG 128
218
219
220 #define JIM_NOTUSED(V) ((void) V)
221
222
223 #define JIM_ENUM_ABBREV 2
224
225
226 #define JIM_CASESENS 0
227 #define JIM_NOCASE 1
228
229
230 #define JIM_PATH_LEN 1024
231
232
233 #ifdef JIM_CRLF
234 #define JIM_NL "\r\n"
235 #else
236 #define JIM_NL "\n"
237 #endif
238
239 #define JIM_LIBPATH "auto_path"
240 #define JIM_INTERACTIVE "tcl_interactive"
241
242
@@ -266,21 +279,22 @@
266 } Jim_HashTableType;
267
268 typedef struct Jim_HashTable {
269 Jim_HashEntry **table;
270 const Jim_HashTableType *type;
 
271 unsigned int size;
272 unsigned int sizemask;
273 unsigned int used;
274 unsigned int collisions;
275 void *privdata;
276 } Jim_HashTable;
277
278 typedef struct Jim_HashTableIterator {
279 Jim_HashTable *ht;
280 int index;
281 Jim_HashEntry *entry, *nextEntry;
 
282 } Jim_HashTableIterator;
283
284
285 #define JIM_HT_INITIAL_SIZE 16
286
@@ -289,35 +303,35 @@
289 if ((ht)->type->valDestructor) \
290 (ht)->type->valDestructor((ht)->privdata, (entry)->u.val)
291
292 #define Jim_SetHashVal(ht, entry, _val_) do { \
293 if ((ht)->type->valDup) \
294 entry->u.val = (ht)->type->valDup((ht)->privdata, _val_); \
295 else \
296 entry->u.val = (_val_); \
297 } while(0)
298
299 #define Jim_FreeEntryKey(ht, entry) \
300 if ((ht)->type->keyDestructor) \
301 (ht)->type->keyDestructor((ht)->privdata, (entry)->key)
302
303 #define Jim_SetHashKey(ht, entry, _key_) do { \
304 if ((ht)->type->keyDup) \
305 entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \
306 else \
307 entry->key = (void *)(_key_); \
308 } while(0)
309
310 #define Jim_CompareHashKeys(ht, key1, key2) \
311 (((ht)->type->keyCompare) ? \
312 (ht)->type->keyCompare((ht)->privdata, key1, key2) : \
313 (key1) == (key2))
314
315 #define Jim_HashKey(ht, key) (ht)->type->hashFunction(key)
316
317 #define Jim_GetHashEntryKey(he) ((he)->key)
318 #define Jim_GetHashEntryVal(he) ((he)->val)
319 #define Jim_GetHashTableCollisions(ht) ((ht)->collisions)
320 #define Jim_GetHashTableSize(ht) ((ht)->size)
321 #define Jim_GetHashTableUsed(ht) ((ht)->used)
322
323
@@ -341,19 +355,19 @@
341 void *ptr1;
342 void *ptr2;
343 } twoPtrValue;
344
345 struct {
346 unsigned long callFrameId;
347 struct Jim_Var *varPtr;
 
348 int global;
349 } varValue;
350
351 struct {
352 unsigned long procEpoch;
353 struct Jim_Obj *nsObj;
354 struct Jim_Cmd *cmdPtr;
 
355 } cmdValue;
356
357 struct {
358 struct Jim_Obj **ele;
359 int len;
@@ -379,12 +393,12 @@
379 struct Jim_Obj *varNameObjPtr;
380 struct Jim_Obj *indexObjPtr;
381 } dictSubstValue;
382
383 struct {
384 unsigned flags;
385 void *compre;
 
386 } regexpValue;
387 struct {
388 int line;
389 int argc;
390 } scriptLineValue;
@@ -453,21 +467,24 @@
453 struct Jim_CallFrame *next;
454 Jim_Obj *nsObj;
455 Jim_Obj *fileNameObj;
456 int line;
457 Jim_Stack *localCommands;
 
 
 
458 } Jim_CallFrame;
459
460 typedef struct Jim_Var {
461 Jim_Obj *objPtr;
462 struct Jim_CallFrame *linkFramePtr;
463 } Jim_Var;
464
465
466 typedef int (*Jim_CmdProc)(struct Jim_Interp *interp, int argc,
467 Jim_Obj *const *argv);
468 typedef void (*Jim_DelCmdProc)(struct Jim_Interp *interp, void *privData);
469
470
471
472 typedef struct Jim_Cmd {
473 int inUse;
@@ -474,12 +491,12 @@
474 int isproc;
475 struct Jim_Cmd *prevCmd;
476 union {
477 struct {
478
479 Jim_CmdProc cmdProc;
480 Jim_DelCmdProc delProc;
481 void *privData;
482 } native;
483 struct {
484
485 Jim_Obj *argListObjPtr;
@@ -589,15 +606,11 @@
589 Jim_Obj *finalizerCmdNamePtr;
590 char tag[JIM_REFERENCE_TAGLEN+1];
591 } Jim_Reference;
592
593
594
595 #define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0)
596
597
598
599 #define Jim_FreeHashTableIterator(iter) Jim_Free(iter)
600
601 #define JIM_EXPORT
602
603
@@ -608,10 +621,11 @@
608 JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);
609
610
611 JIM_EXPORT char **Jim_GetEnviron(void);
612 JIM_EXPORT void Jim_SetEnviron(char **env);
 
613
614
615 JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);
616
617
@@ -739,13 +753,12 @@
739 JIM_EXPORT int Jim_SetVariableStrWithStr (Jim_Interp *interp,
740 const char *name, const char *val);
741 JIM_EXPORT int Jim_SetVariableLink (Jim_Interp *interp,
742 Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr,
743 Jim_CallFrame *targetCallFrame);
744 JIM_EXPORT int Jim_CreateNamespaceVariable(Jim_Interp *interp,
745 Jim_Obj *varNameObj, Jim_Obj *targetNameObj);
746 JIM_EXPORT int Jim_DiscardNamespaceVars(Jim_Interp *interp);
747 JIM_EXPORT Jim_Obj * Jim_GetVariable (Jim_Interp *interp,
748 Jim_Obj *nameObjPtr, int flags);
749 JIM_EXPORT Jim_Obj * Jim_GetGlobalVariable (Jim_Interp *interp,
750 Jim_Obj *nameObjPtr, int flags);
751 JIM_EXPORT Jim_Obj * Jim_GetVariableStr (Jim_Interp *interp,
@@ -804,10 +817,11 @@
804 JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
805 Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr);
806 JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj);
807 JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr);
808 JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr);
 
809
810
811 JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr,
812 int *intPtr);
813
@@ -869,19 +883,19 @@
869
870
871 JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp);
872 JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base);
873 JIM_EXPORT int Jim_IsBigEndian(void);
 
874 #define Jim_CheckSignal(i) ((i)->signal_level && (i)->sigmask)
875
876
877 JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName);
878 JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp);
879
880
881 JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command);
882
883
884
885 JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr);
886 JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr);
887
@@ -903,16 +917,16 @@
903 #define JIM_MODFLAG_HIDDEN 0x0001
904 #define JIM_MODFLAG_FULLARGV 0x0002
905
906
907
908 typedef int tclmod_cmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
909
910 typedef struct {
911 const char *cmd;
912 const char *args;
913 tclmod_cmd_function *function;
914 short minargs;
915 short maxargs;
916 unsigned short flags;
917 } jim_subcmd_type;
918
@@ -929,22 +943,16 @@
929
930 #endif
931 #ifndef JIMREGEXP_H
932 #define JIMREGEXP_H
933
934 #ifndef _JIMAUTOCONF_H
935 #error Need jimautoconf.h
 
936 #endif
937
938 #if defined(HAVE_REGCOMP) && !defined(JIM_REGEXP)
939
940 #include <regex.h>
941
942 #else
943
944 #include <stdlib.h>
945
946
947 typedef struct {
948 int rm_so;
949 int rm_eo;
950 } regmatch_t;
@@ -1013,10 +1021,12 @@
1013 int regcomp(regex_t *preg, const char *regex, int cflags);
1014 int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
1015 size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);
1016 void regfree(regex_t *preg);
1017
 
 
1018 #endif
1019
1020 #endif
1021 int Jim_bootstrapInit(Jim_Interp *interp)
1022 {
@@ -1079,10 +1089,15 @@
1079 "\n"
1080 "package require readdir\n"
1081 "\n"
1082 "\n"
1083 "proc glob.globdir {dir pattern} {\n"
 
 
 
 
 
1084 " set result {}\n"
1085 " set files [readdir $dir]\n"
1086 " lappend files . ..\n"
1087 "\n"
1088 " foreach name $files {\n"
@@ -1261,10 +1276,12 @@
1261 {
1262 if (Jim_PackageProvide(interp, "stdlib", "1.0", JIM_ERRMSG))
1263 return JIM_ERR;
1264
1265 return Jim_EvalSource(interp, "stdlib.tcl", 1,
 
 
1266 "\n"
1267 "proc lambda {arglist args} {\n"
1268 " tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n"
1269 "}\n"
1270 "\n"
@@ -1290,46 +1307,48 @@
1290 "}\n"
1291 "\n"
1292 "\n"
1293 "\n"
1294 "\n"
1295 "proc stacktrace {} {\n"
1296 " set trace {}\n"
1297 " foreach level [range 1 [info level]] {\n"
1298 " lassign [info frame -$level] p f l\n"
1299 " lappend trace $p $f $l\n"
1300 " }\n"
1301 " return $trace\n"
1302 "}\n"
1303 "\n"
1304 "\n"
1305 "proc stackdump {stacktrace} {\n"
1306 " set result {}\n"
1307 " set count 0\n"
1308 " foreach {l f p} [lreverse $stacktrace] {\n"
1309 " if {$count} {\n"
1310 " append result \\n\n"
1311 " }\n"
1312 " incr count\n"
1313 " if {$p ne \"\"} {\n"
1314 " append result \"in procedure '$p' \"\n"
1315 " if {$f ne \"\"} {\n"
1316 " append result \"called \"\n"
1317 " }\n"
1318 " }\n"
1319 " if {$f ne \"\"} {\n"
1320 " append result \"at file \\\"$f\\\", line $l\"\n"
 
 
 
1321 " }\n"
1322 " }\n"
1323 " return $result\n"
1324 "}\n"
1325 "\n"
1326 "\n"
1327 "\n"
1328 "proc errorInfo {msg {stacktrace \"\"}} {\n"
1329 " if {$stacktrace eq \"\"} {\n"
 
1330 " set stacktrace [info stacktrace]\n"
 
 
1331 " }\n"
1332 " lassign $stacktrace p f l\n"
1333 " if {$f ne \"\"} {\n"
1334 " set result \"Runtime Error: $f:$l: \"\n"
1335 " }\n"
@@ -1356,25 +1375,46 @@
1356 " }\n"
1357 " return \"\"\n"
1358 "}\n"
1359 "\n"
1360 "\n"
1361 "proc {dict with} {dictVar args script} {\n"
1362 " upvar $dictVar dict\n"
1363 " set keys {}\n"
1364 " foreach {n v} [dict get $dict {*}$args] {\n"
1365 " upvar $n var_$n\n"
1366 " set var_$n $v\n"
1367 " lappend keys $n\n"
1368 " }\n"
1369 " catch {uplevel 1 $script} msg opts\n"
1370 " if {[info exists dict] && [dict exists $dict {*}$args]} {\n"
1371 " foreach n $keys {\n"
1372 " if {[info exists var_$n]} {\n"
1373 " dict set dict {*}$args $n [set var_$n]\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1374 " } else {\n"
1375 " dict unset dict {*}$args $n\n"
1376 " }\n"
1377 " }\n"
1378 " }\n"
1379 " return {*}$opts $msg\n"
1380 "}\n"
@@ -1389,10 +1429,69 @@
1389 " dict set dict $k $v\n"
1390 " }\n"
1391 " }\n"
1392 " return $dict\n"
1393 "}\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1394 );
1395 }
1396 int Jim_tclcompatInit(Jim_Interp *interp)
1397 {
1398 if (Jim_PackageProvide(interp, "tclcompat", "1.0", JIM_ERRMSG))
@@ -1403,12 +1502,14 @@
1403 "\n"
1404 "\n"
1405 "\n"
1406 "\n"
1407 "\n"
 
1408 "\n"
1409 "set env [env]\n"
 
1410 "\n"
1411 "if {[info commands stdout] ne \"\"} {\n"
1412 "\n"
1413 " foreach p {gets flush close eof seek tell} {\n"
1414 " proc $p {chan args} {p} {\n"
@@ -1455,51 +1556,10 @@
1455 " }\n"
1456 " }\n"
1457 " }\n"
1458 "}\n"
1459 "\n"
1460 "\n"
1461 "proc case {var args} {\n"
1462 "\n"
1463 " if {[lindex $args 0] eq \"in\"} {\n"
1464 " set args [lrange $args 1 end]\n"
1465 " }\n"
1466 "\n"
1467 "\n"
1468 " if {[llength $args] == 1} {\n"
1469 " set args [lindex $args 0]\n"
1470 " }\n"
1471 "\n"
1472 "\n"
1473 " if {[llength $args] % 2 != 0} {\n"
1474 " return -code error \"extra case pattern with no body\"\n"
1475 " }\n"
1476 "\n"
1477 "\n"
1478 " local proc case.checker {value pattern} {\n"
1479 " string match $pattern $value\n"
1480 " }\n"
1481 "\n"
1482 " foreach {value action} $args {\n"
1483 " if {$value eq \"default\"} {\n"
1484 " set do_action $action\n"
1485 " continue\n"
1486 " } elseif {[lsearch -bool -command case.checker $value $var]} {\n"
1487 " set do_action $action\n"
1488 " break\n"
1489 " }\n"
1490 " }\n"
1491 "\n"
1492 " if {[info exists do_action]} {\n"
1493 " set rc [catch [list uplevel 1 $do_action] result opts]\n"
1494 " if {$rc} {\n"
1495 " incr opts(-level)\n"
1496 " }\n"
1497 " return {*}$opts $result\n"
1498 " }\n"
1499 "}\n"
1500 "\n"
1501 "\n"
1502 "proc fileevent {args} {\n"
1503 " tailcall {*}$args\n"
1504 "}\n"
1505 "\n"
@@ -1529,13 +1589,25 @@
1529 " error \"bad option \\\"$force\\\": should be -force\"\n"
1530 " }\n"
1531 "\n"
1532 " set in [open $source]\n"
1533 "\n"
1534 " if {$force eq \"\" && [file exists $target]} {\n"
1535 " $in close\n"
1536 " error \"error copying \\\"$source\\\" to \\\"$target\\\": file already exists\"\n"
 
 
 
 
 
 
 
 
 
 
 
 
1537 " }\n"
1538 " set out [open $target w]\n"
1539 " $in copyto $out\n"
1540 " $out close\n"
1541 " } on error {msg opts} {\n"
@@ -1580,18 +1652,18 @@
1580 " error $error\n"
1581 " }\n"
1582 "}\n"
1583 "\n"
1584 "\n"
1585 "local proc pid {{chan {}}} {\n"
1586 " if {$chan eq \"\"} {\n"
1587 " tailcall upcall pid\n"
1588 " }\n"
1589 " if {[catch {$chan tell}]} {\n"
1590 " return -code error \"can not find channel named \\\"$chan\\\"\"\n"
1591 " }\n"
1592 " if {[catch {$chan pid} pids]} {\n"
1593 " return \"\"\n"
1594 " }\n"
1595 " return $pids\n"
1596 "}\n"
1597 "\n"
@@ -1680,23 +1752,25 @@
1680 "}\n"
1681 );
1682 }
1683
1684
1685
1686 #include <stdio.h>
1687 #include <string.h>
1688 #include <errno.h>
1689 #include <fcntl.h>
 
 
 
 
1690
1691
1692 #if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H)
1693 #include <sys/socket.h>
1694 #include <netinet/in.h>
1695 #include <arpa/inet.h>
1696 #include <netdb.h>
1697 #include <unistd.h>
1698 #ifdef HAVE_SYS_UN_H
1699 #include <sys/un.h>
1700 #endif
1701 #else
1702 #define JIM_ANSIC
@@ -1728,15 +1802,12 @@
1728 typedef struct AioFile
1729 {
1730 FILE *fp;
1731 Jim_Obj *filename;
1732 int type;
1733 int OpenFlags;
1734 int fd;
1735 #ifdef O_NDELAY
1736 int flags;
1737 #endif
1738 Jim_Obj *rEvent;
1739 Jim_Obj *wEvent;
1740 Jim_Obj *eEvent;
1741 int addr_family;
1742 } AioFile;
@@ -1760,20 +1831,21 @@
1760 {
1761 AioFile *af = privData;
1762
1763 JIM_NOTUSED(interp);
1764
1765 if (!(af->OpenFlags & AIO_KEEPOPEN)) {
1766 fclose(af->fp);
1767 }
1768
1769 Jim_DecrRefCount(interp, af->filename);
1770
1771 #ifdef jim_ext_eventloop
1772
1773 Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION);
1774 #endif
 
 
 
 
 
1775 Jim_Free(af);
1776 }
1777
1778 static int JimCheckStreamError(Jim_Interp *interp, AioFile *af)
1779 {
@@ -2020,12 +2092,31 @@
2020 return JIM_OK;
2021 }
2022
2023 static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2024 {
2025 Jim_DeleteCommand(interp, Jim_String(argv[0]));
2026 return JIM_OK;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2027 }
2028
2029 static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2030 {
2031 AioFile *af = Jim_CmdPrivData(interp);
@@ -2072,11 +2163,11 @@
2072 #ifdef O_NDELAY
2073 static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2074 {
2075 AioFile *af = Jim_CmdPrivData(interp);
2076
2077 int fmode = af->flags;
2078
2079 if (argc) {
2080 long nb;
2081
2082 if (Jim_GetLong(interp, argv[0], &nb) != JIM_OK) {
@@ -2086,12 +2177,11 @@
2086 fmode |= O_NDELAY;
2087 }
2088 else {
2089 fmode &= ~O_NDELAY;
2090 }
2091 fcntl(af->fd, F_SETFL, fmode);
2092 af->flags = fmode;
2093 }
2094 Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0);
2095 return JIM_OK;
2096 }
2097 #endif
@@ -2195,11 +2285,11 @@
2195
2196 static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2197 {
2198 AioFile *af = Jim_CmdPrivData(interp);
2199
2200 return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->wEvent, argc, argv);
2201 }
2202 #endif
2203
2204 static const jim_subcmd_type aio_command_table[] = {
2205 { "read",
@@ -2250,14 +2340,14 @@
2250 0,
2251 0,
2252
2253 },
2254 { "close",
2255 NULL,
2256 aio_cmd_close,
2257 0,
2258 0,
2259 JIM_MODFLAG_FULLARGV,
2260
2261 },
2262 { "seek",
2263 "offset ?start|current|end",
@@ -2329,30 +2419,32 @@
2329
2330 static int JimAioOpenCommand(Jim_Interp *interp, int argc,
2331 Jim_Obj *const *argv)
2332 {
2333 const char *mode;
2334 const char *filename;
2335
2336 if (argc != 2 && argc != 3) {
2337 Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?");
2338 return JIM_ERR;
2339 }
2340
2341 mode = (argc == 3) ? Jim_String(argv[2]) : "r";
2342 filename = Jim_String(argv[1]);
2343
2344 #ifdef jim_ext_tclcompat
2345
2346 if (*filename == '|') {
2347 Jim_Obj *evalObj[3];
2348
2349 evalObj[0] = Jim_NewStringObj(interp, "popen", -1);
2350 evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1);
2351 evalObj[2] = Jim_NewStringObj(interp, mode, -1);
2352
2353 return Jim_EvalObjVector(interp, 3, evalObj);
 
 
 
 
2354 }
2355 #endif
2356 return JimMakeChannel(interp, NULL, -1, argv[1], "aio.handle%ld", 0, mode);
2357 }
2358
@@ -2359,70 +2451,129 @@
2359 static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename,
2360 const char *hdlfmt, int family, const char *mode)
2361 {
2362 AioFile *af;
2363 char buf[AIO_CMD_LEN];
2364 int OpenFlags = 0;
2365
2366 if (filename == NULL) {
2367 filename = Jim_NewStringObj(interp, hdlfmt, -1);
 
2368 }
2369
2370 Jim_IncrRefCount(filename);
2371
2372 if (fh == NULL) {
2373 if (fd < 0) {
2374 fh = fopen(Jim_String(filename), mode);
2375 }
2376 else {
2377 fh = fdopen(fd, mode);
2378 }
2379 }
2380 else {
2381 OpenFlags = AIO_KEEPOPEN;
2382 }
2383
2384 if (fh == NULL) {
2385 JimAioSetError(interp, filename);
2386 #if !defined(JIM_ANSIC)
2387 if (fd >= 0) {
2388 close(fd);
 
 
 
 
2389 }
2390 #endif
2391 Jim_DecrRefCount(interp, filename);
2392 return JIM_ERR;
2393 }
2394
2395
2396 af = Jim_Alloc(sizeof(*af));
2397 memset(af, 0, sizeof(*af));
2398 af->fp = fh;
2399 af->fd = fileno(fh);
2400 af->filename = filename;
2401 #ifdef FD_CLOEXEC
2402 if ((OpenFlags & AIO_KEEPOPEN) == 0) {
2403 fcntl(af->fd, F_SETFD, FD_CLOEXEC);
2404 }
2405 #endif
2406 af->OpenFlags = OpenFlags;
2407 #ifdef O_NDELAY
2408 af->flags = fcntl(af->fd, F_GETFL);
2409 #endif
2410 af->addr_family = family;
2411 snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp));
2412 Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);
2413
2414 Jim_SetResultString(interp, buf, -1);
2415
2416 return JIM_OK;
2417 }
2418
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2419
2420 FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command)
2421 {
2422 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
2423
 
2424 if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
2425 return ((AioFile *) cmdPtr->u.native.privData)->fp;
2426 }
2427 Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command);
2428 return NULL;
@@ -2443,11 +2594,10 @@
2443 JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w");
2444 JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w");
2445
2446 return JIM_OK;
2447 }
2448
2449
2450 #include <errno.h>
2451 #include <stdio.h>
2452 #include <string.h>
2453
@@ -2479,28 +2629,29 @@
2479 return JIM_OK;
2480 }
2481 Jim_SetResultString(interp, strerror(errno), -1);
2482 return JIM_ERR;
2483 }
2484 Jim_SetResultString(interp, strerror(errno), -1);
2485
2486 Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
2487
2488 while ((entryPtr = readdir(dirPtr)) != NULL) {
2489 if (entryPtr->d_name[0] == '.') {
2490 if (entryPtr->d_name[1] == '\0') {
2491 continue;
2492 }
2493 if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0'))
2494 continue;
2495 }
2496 Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp,
2497 entryPtr->d_name, -1));
2498 }
2499 closedir(dirPtr);
2500
2501 return JIM_OK;
 
2502 }
2503
2504 int Jim_readdirInit(Jim_Interp *interp)
2505 {
2506 if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG))
@@ -2511,10 +2662,14 @@
2511 }
2512
2513 #include <stdlib.h>
2514 #include <string.h>
2515
 
 
 
 
2516
2517 static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
2518 {
2519 regfree(objPtr->internalRep.regexpValue.compre);
2520 Jim_Free(objPtr->internalRep.regexpValue.compre);
@@ -3058,58 +3213,61 @@
3058 }
3059 #endif
3060 return "unknown";
3061 }
3062
3063
3064 static int set_array_int_value(Jim_Interp *interp, Jim_Obj *container, const char *key,
3065 jim_wide value)
3066 {
3067 Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1);
3068 Jim_Obj *valobj = Jim_NewWideObj(interp, value);
3069
3070 if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) {
3071 Jim_FreeObj(interp, nameobj);
3072 Jim_FreeObj(interp, valobj);
3073 return JIM_ERR;
3074 }
3075 return JIM_OK;
3076 }
3077
3078 static int set_array_string_value(Jim_Interp *interp, Jim_Obj *container, const char *key,
3079 const char *value)
3080 {
3081 Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1);
3082 Jim_Obj *valobj = Jim_NewStringObj(interp, value, -1);
3083
3084 if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) {
3085 Jim_FreeObj(interp, nameobj);
3086 Jim_FreeObj(interp, valobj);
3087 return JIM_ERR;
3088 }
3089 return JIM_OK;
3090 }
3091
3092 static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb)
3093 {
3094 if (set_array_int_value(interp, varName, "dev", sb->st_dev) != JIM_OK) {
3095 Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName);
3096 return JIM_ERR;
3097 }
3098 set_array_int_value(interp, varName, "ino", sb->st_ino);
3099 set_array_int_value(interp, varName, "mode", sb->st_mode);
3100 set_array_int_value(interp, varName, "nlink", sb->st_nlink);
3101 set_array_int_value(interp, varName, "uid", sb->st_uid);
3102 set_array_int_value(interp, varName, "gid", sb->st_gid);
3103 set_array_int_value(interp, varName, "size", sb->st_size);
3104 set_array_int_value(interp, varName, "atime", sb->st_atime);
3105 set_array_int_value(interp, varName, "mtime", sb->st_mtime);
3106 set_array_int_value(interp, varName, "ctime", sb->st_ctime);
3107 set_array_string_value(interp, varName, "type", JimGetFileType((int)sb->st_mode));
3108
3109
3110 Jim_SetResult(interp, Jim_GetVariable(interp, varName, 0));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3111
3112 return JIM_OK;
3113 }
3114
3115 static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -3264,14 +3422,11 @@
3264 return JIM_OK;
3265 }
3266
3267 static int file_access(Jim_Interp *interp, Jim_Obj *filename, int mode)
3268 {
3269 const char *path = Jim_String(filename);
3270 int rc = access(path, mode);
3271
3272 Jim_SetResultBool(interp, rc != -1);
3273
3274 return JIM_OK;
3275 }
3276
3277 static int file_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -3287,10 +3442,11 @@
3287 static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3288 {
3289 #ifdef X_OK
3290 return file_access(interp, argv[0], X_OK);
3291 #else
 
3292 Jim_SetResultBool(interp, 1);
3293 return JIM_OK;
3294 #endif
3295 }
3296
@@ -3391,33 +3547,21 @@
3391 argv++;
3392 }
3393 return JIM_OK;
3394 }
3395
3396 #ifdef HAVE_MKSTEMP
3397 static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3398 {
3399 int fd;
3400 char *filename;
3401 const char *template = "/tmp/tcl.tmp.XXXXXX";
3402
3403 if (argc >= 1) {
3404 template = Jim_String(argv[0]);
3405 }
3406 filename = Jim_StrDup(template);
3407
3408 fd = mkstemp(filename);
3409 if (fd < 0) {
3410 Jim_SetResultString(interp, "Failed to create tempfile", -1);
3411 return JIM_ERR;
3412 }
3413 close(fd);
3414
3415 Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, filename, -1));
3416 return JIM_OK;
3417 }
3418 #endif
3419
3420 static int file_cmd_rename(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3421 {
3422 const char *source;
3423 const char *dest;
@@ -3459,14 +3603,11 @@
3459 return JIM_ERR;
3460 }
3461 return JIM_OK;
3462 }
3463
3464 #ifndef HAVE_LSTAT
3465 #define lstat stat
3466 #endif
3467
3468 static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb)
3469 {
3470 const char *path = Jim_String(filename);
3471
3472 if (lstat(path, sb) == -1) {
@@ -3473,10 +3614,13 @@
3473 Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno));
3474 return JIM_ERR;
3475 }
3476 return JIM_OK;
3477 }
 
 
 
3478
3479 static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3480 {
3481 struct stat sb;
3482
@@ -3601,28 +3745,32 @@
3601 }
3602 Jim_SetResultString(interp, JimGetFileType((int)sb.st_mode), -1);
3603 return JIM_OK;
3604 }
3605
 
3606 static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3607 {
3608 struct stat sb;
3609
3610 if (file_lstat(interp, argv[0], &sb) != JIM_OK) {
3611 return JIM_ERR;
3612 }
3613 return StoreStatData(interp, argv[1], &sb);
3614 }
 
 
 
3615
3616 static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3617 {
3618 struct stat sb;
3619
3620 if (file_stat(interp, argv[0], &sb) != JIM_OK) {
3621 return JIM_ERR;
3622 }
3623 return StoreStatData(interp, argv[1], &sb);
3624 }
3625
3626 static const jim_subcmd_type file_command_table[] = {
3627 { "atime",
3628 "name",
@@ -3727,19 +3875,17 @@
3727 file_cmd_mkdir,
3728 1,
3729 -1,
3730
3731 },
3732 #ifdef HAVE_MKSTEMP
3733 { "tempfile",
3734 "?template?",
3735 file_cmd_tempfile,
3736 0,
3737 1,
3738
3739 },
3740 #endif
3741 { "rename",
3742 "?-force? source dest",
3743 file_cmd_rename,
3744 2,
3745 3,
@@ -3760,20 +3906,20 @@
3760 1,
3761 1,
3762
3763 },
3764 { "stat",
3765 "name var",
3766 file_cmd_stat,
3767 2,
3768 2,
3769
3770 },
3771 { "lstat",
3772 "name var",
3773 file_cmd_lstat,
3774 2,
3775 2,
3776
3777 },
3778 { "type",
3779 "name",
@@ -3829,15 +3975,15 @@
3829 return JIM_OK;
3830 }
3831
3832 static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3833 {
3834 const int cwd_len = 2048;
3835 char *cwd = malloc(cwd_len);
3836
3837 if (getcwd(cwd, cwd_len) == NULL) {
3838 Jim_SetResultString(interp, "Failed to get pwd", -1);
 
3839 return JIM_ERR;
3840 }
3841 #if defined(__MINGW32__) || defined(_MSC_VER)
3842 {
3843
@@ -3848,11 +3994,11 @@
3848 }
3849 #endif
3850
3851 Jim_SetResultString(interp, cwd, -1);
3852
3853 free(cwd);
3854 return JIM_OK;
3855 }
3856
3857 int Jim_fileInit(Jim_Interp *interp)
3858 {
@@ -3917,10 +4063,11 @@
3917
3918 int Jim_execInit(Jim_Interp *interp)
3919 {
3920 if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
3921 return JIM_ERR;
 
3922 Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL);
3923 return JIM_OK;
3924 }
3925 #else
3926
@@ -3960,10 +4107,11 @@
3960 static int JimErrno(void);
3961 #else
3962 #include <unistd.h>
3963 #include <fcntl.h>
3964 #include <sys/wait.h>
 
3965
3966 typedef int fdtype;
3967 typedef int pidtype;
3968 #define JimPipe pipe
3969 #define JimErrno() errno
@@ -4034,23 +4182,12 @@
4034 Jim_RemoveTrailingNewline(strObj);
4035 fclose(fh);
4036 return JIM_OK;
4037 }
4038
4039 static void JimTrimTrailingNewline(Jim_Interp *interp)
4040 {
4041 int len;
4042 const char *p = Jim_GetString(Jim_GetResult(interp), &len);
4043
4044 if (len > 0 && p[len - 1] == '\n') {
4045 Jim_SetResultString(interp, p, len - 1);
4046 }
4047 }
4048
4049 static char **JimBuildEnv(Jim_Interp *interp)
4050 {
4051 #if defined(jim_ext_tclcompat)
4052 int i;
4053 int size;
4054 int num;
4055 int n;
4056 char **envptr;
@@ -4064,10 +4201,11 @@
4064
4065
4066
4067 num = Jim_ListLength(interp, objPtr);
4068 if (num % 2) {
 
4069 num--;
4070 }
4071 size = Jim_Length(objPtr) + 2;
4072
4073 envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size);
@@ -4090,22 +4228,17 @@
4090 }
4091 envptr[n] = NULL;
4092 *envdata = 0;
4093
4094 return envptr;
4095 #else
4096 return Jim_GetEnviron();
4097 #endif
4098 }
4099
4100 static void JimFreeEnv(char **env, char **original_environ)
4101 {
4102 #ifdef jim_ext_tclcompat
4103 if (env != original_environ) {
4104 Jim_Free(env);
4105 }
4106 #endif
4107 }
4108
4109 static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus)
4110 {
4111 Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0);
@@ -4154,19 +4287,19 @@
4154 }
4155
4156
4157 struct WaitInfo
4158 {
4159 pidtype pid;
4160 int status;
4161 int flags;
4162 };
4163
4164 struct WaitInfoTable {
4165 struct WaitInfo *info;
4166 int size;
4167 int used;
4168 };
4169
4170
4171 #define WI_DETACHED 2
4172
@@ -4189,14 +4322,12 @@
4189 return table;
4190 }
4191
4192 static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
4193 {
4194 fdtype outputId; /* File id for output pipe. -1
4195 * means command overrode. */
4196 fdtype errorId; /* File id for temporary file
4197 * containing error output. */
4198 pidtype *pidPtr;
4199 int numPids, result;
4200
4201 if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) {
4202 Jim_Obj *listObj;
@@ -4243,26 +4374,32 @@
4243
4244 static void JimReapDetachedPids(struct WaitInfoTable *table)
4245 {
4246 struct WaitInfo *waitPtr;
4247 int count;
 
4248
4249 if (!table) {
4250 return;
4251 }
4252
4253 for (waitPtr = table->info, count = table->used; count > 0; waitPtr++, count--) {
 
 
4254 if (waitPtr->flags & WI_DETACHED) {
4255 int status;
4256 pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG);
4257 if (pid != JIM_BAD_PID) {
4258 if (waitPtr != &table->info[table->used - 1]) {
4259 *waitPtr = table->info[table->used - 1];
4260 }
4261 table->used--;
 
4262 }
4263 }
 
 
 
 
4264 }
4265 }
4266
4267 static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr)
4268 {
@@ -4284,11 +4421,10 @@
4284 }
4285
4286
4287 return JIM_BAD_PID;
4288 }
4289
4290
4291 static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr)
4292 {
4293 int j;
4294 struct WaitInfoTable *table = Jim_CmdPrivData(interp);
@@ -4609,27 +4745,23 @@
4609 }
4610 outputId = pipeIds[1];
4611 }
4612
4613
 
 
 
 
 
4614
4615 #ifdef __MINGW32__
4616 pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId);
4617 if (pid == JIM_BAD_PID) {
4618 Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]);
4619 goto error;
4620 }
4621 #else
4622 if (table->info == NULL) {
4623 (void)signal(SIGPIPE, SIG_IGN);
4624 }
4625
4626
4627 if (pipe_dup_err) {
4628 errorId = outputId;
4629 }
4630
4631 pid = vfork();
4632 if (pid < 0) {
4633 Jim_SetResultErrno(interp, "couldn't fork child process");
4634 goto error;
4635 }
@@ -4642,14 +4774,17 @@
4642
4643 for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) {
4644 close(i);
4645 }
4646
 
 
 
4647 execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron());
4648
4649
4650 fprintf(stderr, "couldn't exec \"%s\"", arg_array[firstArg]);
4651 _exit(127);
4652 }
4653 #endif
4654
4655
@@ -4751,19 +4886,24 @@
4751 if (JimAppendStreamToString(interp, errorId, Jim_GetResult(interp)) != JIM_OK) {
4752 result = JIM_ERR;
4753 }
4754 }
4755
4756 JimTrimTrailingNewline(interp);
4757
4758 return result;
4759 }
4760
4761 int Jim_execInit(Jim_Interp *interp)
4762 {
4763 if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
4764 return JIM_ERR;
 
 
 
 
 
4765 Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable);
4766 return JIM_OK;
4767 }
4768
4769 #if defined(__MINGW32__)
@@ -5088,28 +5228,26 @@
5088 {
5089 STARTUPINFO startInfo;
5090 PROCESS_INFORMATION procInfo;
5091 HANDLE hProcess, h;
5092 char execPath[MAX_PATH];
5093 char *originalName;
5094 pidtype pid = JIM_BAD_PID;
5095 Jim_Obj *cmdLineObj;
5096
5097 if (JimWinFindExecutable(argv[0], execPath) < 0) {
5098 return JIM_BAD_PID;
5099 }
5100 originalName = argv[0];
5101 argv[0] = execPath;
5102
5103 hProcess = GetCurrentProcess();
5104 cmdLineObj = JimWinBuildCommandLine(interp, argv);
5105
5106
5107 ZeroMemory(&startInfo, sizeof(startInfo));
5108 startInfo.cb = sizeof(startInfo);
5109 startInfo.dwFlags = STARTF_USESTDHANDLES;
5110 startInfo.hStdInput = INVALID_HANDLE_VALUE;
5111 startInfo.hStdOutput= INVALID_HANDLE_VALUE;
5112 startInfo.hStdError = INVALID_HANDLE_VALUE;
5113
5114 if (inputId == JIM_BAD_FD) {
5115 if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) {
@@ -5182,18 +5320,17 @@
5182 return lseek(fd, 0L, SEEK_SET);
5183 }
5184
5185 static int JimCreateTemp(Jim_Interp *interp, const char *contents, int len)
5186 {
5187 char inName[] = "/tmp/tcl.tmp.XXXXXX";
5188
5189 int fd = mkstemp(inName);
5190 if (fd == JIM_BAD_FD) {
5191 Jim_SetResultErrno(interp, "couldn't create temp file");
5192 return -1;
5193 }
5194 unlink(inName);
5195 if (contents) {
5196 if (write(fd, contents, len) != len) {
5197 Jim_SetResultErrno(interp, "couldn't write temp file");
5198 close(fd);
5199 return -1;
@@ -5217,11 +5354,10 @@
5217 }
5218 #endif
5219 #endif
5220
5221
5222
5223 #ifndef _XOPEN_SOURCE
5224 #define _XOPEN_SOURCE 500
5225 #endif
5226
5227 #include <stdlib.h>
@@ -5239,11 +5375,11 @@
5239
5240 char buf[100];
5241 time_t t;
5242 long seconds;
5243
5244 const char *format = "%a %b %d %H:%M:%S %Z %Y";
5245
5246 if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) {
5247 return -1;
5248 }
5249
@@ -5254,11 +5390,14 @@
5254 if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) {
5255 return JIM_ERR;
5256 }
5257 t = seconds;
5258
5259 strftime(buf, sizeof(buf), format, localtime(&t));
 
 
 
5260
5261 Jim_SetResultString(interp, buf, -1);
5262
5263 return JIM_OK;
5264 }
@@ -5374,11 +5513,10 @@
5374
5375 Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL);
5376 return JIM_OK;
5377 }
5378
5379
5380 #include <limits.h>
5381 #include <stdlib.h>
5382 #include <string.h>
5383 #include <stdio.h>
5384 #include <errno.h>
@@ -5392,33 +5530,29 @@
5392 }
5393
5394 static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5395 {
5396 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
 
5397
5398 if (!objPtr) {
5399 return JIM_OK;
5400 }
5401
5402 if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
5403
5404 if (Jim_IsList(objPtr)) {
5405 if (Jim_ListLength(interp, objPtr) % 2 != 0) {
5406
5407 return JIM_ERR;
5408 }
5409 }
5410 else if (Jim_DictSize(interp, objPtr) < 0) {
5411
5412 return JIM_ERR;
5413 }
5414 Jim_SetResult(interp, objPtr);
5415 return JIM_OK;
5416 }
5417
5418
5419 return Jim_DictValues(interp, objPtr, argv[1]);
5420 }
5421
5422 static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5423 {
5424 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
@@ -5443,10 +5577,15 @@
5443 Jim_UnsetVariable(interp, argv[0], JIM_NONE);
5444 return JIM_OK;
5445 }
5446
5447 objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
 
 
 
 
 
5448
5449 if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
5450 return JIM_ERR;
5451 }
5452
@@ -5480,10 +5619,20 @@
5480
5481 Jim_SetResultInt(interp, len);
5482
5483 return JIM_OK;
5484 }
 
 
 
 
 
 
 
 
 
 
5485
5486 static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5487 {
5488 int i;
5489 int len;
@@ -5498,10 +5647,13 @@
5498
5499 dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
5500 if (!dictObj) {
5501
5502 return Jim_SetVariable(interp, argv[0], listObj);
 
 
 
5503 }
5504
5505 if (Jim_IsShared(dictObj)) {
5506 dictObj = Jim_DuplicateObj(interp, dictObj);
5507 }
@@ -5551,10 +5703,17 @@
5551 "arrayName",
5552 array_cmd_size,
5553 1,
5554 1,
5555
 
 
 
 
 
 
 
5556 },
5557 { "unset",
5558 "arrayName ?pattern?",
5559 array_cmd_unset,
5560 1,
@@ -5597,11 +5756,10 @@
5597 Jim_arrayInit(interp);
5598 Jim_stdlibInit(interp);
5599 Jim_tclcompatInit(interp);
5600 return JIM_OK;
5601 }
5602
5603 #define JIM_OPTIMIZATION
5604
5605 #include <stdio.h>
5606 #include <stdlib.h>
5607
@@ -5661,21 +5819,20 @@
5661 #define JIM_INTEGER_SPACE 24
5662
5663 const char *jim_tt_name(int type);
5664
5665 #ifdef JIM_DEBUG_PANIC
5666 static void JimPanicDump(int panic_condition, const char *fmt, ...);
5667 #define JimPanic(X) JimPanicDump X
5668 #else
5669 #define JimPanic(X)
5670 #endif
5671
5672
5673 static char JimEmptyStringRep[] = "";
5674
5675 static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf);
5676 static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags);
5677 static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
5678 int flags);
5679 static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands);
5680 static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr);
5681 static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
@@ -5922,44 +6079,10 @@
5922 }
5923 return n;
5924 }
5925 #endif
5926
5927 static int JimWideToString(char *buf, jim_wide wideValue)
5928 {
5929 int pos = 0;
5930
5931 if (wideValue == 0) {
5932 buf[pos++] = '0';
5933 }
5934 else {
5935 char tmp[JIM_INTEGER_SPACE];
5936 int num = 0;
5937 int i;
5938
5939 if (wideValue < 0) {
5940 buf[pos++] = '-';
5941
5942 i = wideValue % 10;
5943 tmp[num++] = (i > 0) ? (10 - i) : -i;
5944 wideValue /= -10;
5945 }
5946
5947 while (wideValue) {
5948 tmp[num++] = wideValue % 10;
5949 wideValue /= 10;
5950 }
5951
5952 for (i = 0; i < num; i++) {
5953 buf[pos++] = '0' + tmp[num - i - 1];
5954 }
5955 }
5956 buf[pos] = 0;
5957
5958 return pos;
5959 }
5960
5961 static int JimCheckConversion(const char *str, const char *endptr)
5962 {
5963 if (str[0] == '\0' || str == endptr) {
5964 return JIM_ERR;
5965 }
@@ -6070,48 +6193,10 @@
6070 }
6071
6072 return JimCheckConversion(str, endptr);
6073 }
6074
6075 int Jim_DoubleToString(char *buf, double doubleValue)
6076 {
6077 int len;
6078 int i;
6079
6080 len = sprintf(buf, "%.12g", doubleValue);
6081
6082
6083 for (i = 0; i < len; i++) {
6084 if (buf[i] == '.' || buf[i] == 'e') {
6085 #if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
6086 char *e = strchr(buf, 'e');
6087 if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
6088
6089 e += 2;
6090 memmove(e, e + 1, len - (e - buf));
6091 return len - 1;
6092 }
6093 #endif
6094 return len;
6095 }
6096
6097 if (buf[i] == 'i' || buf[i] == 'I' || buf[i] == 'n' || buf[i] == 'N') {
6098 buf[i] = toupper(UCHAR(buf[i]));
6099 if (buf[i] == 'n' || buf[i] == 'N')
6100 buf[i+2] = toupper(UCHAR(buf[i+2]));
6101 buf[i + 3] = 0;
6102 return i + 3;
6103 }
6104 }
6105
6106 buf[i++] = '.';
6107 buf[i++] = '0';
6108 buf[i] = '\0';
6109
6110 return i;
6111 }
6112
6113 int Jim_StringToDouble(const char *str, double *doublePtr)
6114 {
6115 char *endptr;
6116
6117
@@ -6133,23 +6218,23 @@
6133 }
6134 return res;
6135 }
6136
6137 #ifdef JIM_DEBUG_PANIC
6138 void JimPanicDump(int condition, const char *fmt, ...)
6139 {
6140 va_list ap;
6141
6142 if (!condition) {
6143 return;
6144 }
6145
6146 va_start(ap, fmt);
6147
6148 fprintf(stderr, JIM_NL "JIM INTERPRETER PANIC: ");
6149 vfprintf(stderr, fmt, ap);
6150 fprintf(stderr, JIM_NL JIM_NL);
6151 va_end(ap);
6152
6153 #ifdef HAVE_BACKTRACE
6154 {
6155 void *array[40];
@@ -6157,13 +6242,13 @@
6157 char **strings;
6158
6159 size = backtrace(array, 40);
6160 strings = backtrace_symbols(array, size);
6161 for (i = 0; i < size; i++)
6162 fprintf(stderr, "[backtrace] %s" JIM_NL, strings[i]);
6163 fprintf(stderr, "[backtrace] Include the above lines and the output" JIM_NL);
6164 fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report." JIM_NL);
6165 }
6166 #endif
6167
6168 exit(1);
6169 }
@@ -6237,18 +6322,24 @@
6237 h += (h << 3) + *buf++;
6238 return h;
6239 }
6240
6241
 
6242
6243 static void JimResetHashTable(Jim_HashTable *ht)
6244 {
6245 ht->table = NULL;
6246 ht->size = 0;
6247 ht->sizemask = 0;
6248 ht->used = 0;
6249 ht->collisions = 0;
 
 
 
 
 
6250 }
6251
6252 static void JimInitHashTableIterator(Jim_HashTable *ht, Jim_HashTableIterator *iter)
6253 {
6254 iter->ht = ht;
@@ -6286,10 +6377,12 @@
6286
6287 Jim_InitHashTable(&n, ht->type, ht->privdata);
6288 n.size = realsize;
6289 n.sizemask = realsize - 1;
6290 n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *));
 
 
6291
6292
6293 memset(n.table, 0, realsize * sizeof(Jim_HashEntry *));
6294
6295 n.used = ht->used;
@@ -6342,20 +6435,27 @@
6342 int existed;
6343 Jim_HashEntry *entry;
6344
6345 entry = JimInsertHashEntry(ht, key, 1);
6346 if (entry->key) {
6347
6348 Jim_FreeEntryVal(ht, entry);
 
 
 
 
 
 
 
6349 existed = 1;
6350 }
6351 else {
6352
6353 Jim_SetHashKey(ht, entry, key);
 
6354 existed = 0;
6355 }
6356 Jim_SetHashVal(ht, entry, val);
6357
6358 return existed;
6359 }
6360
6361
@@ -6520,11 +6620,11 @@
6520 return Jim_GenHashFunction(key, strlen(key));
6521 }
6522
6523 static void *JimStringCopyHTDup(void *privdata, const void *key)
6524 {
6525 return strdup(key);
6526 }
6527
6528 static int JimStringCopyHTKeyCompare(void *privdata, const void *key1, const void *key2)
6529 {
6530 return strcmp(key1, key2) == 0;
@@ -6620,11 +6720,11 @@
6620 freeFunc(stack->vector[i]);
6621 }
6622
6623
6624
6625 #define JIM_TT_NONE 0
6626 #define JIM_TT_STR 1
6627 #define JIM_TT_ESC 2
6628 #define JIM_TT_VAR 3
6629 #define JIM_TT_DICTSUGAR 4
6630 #define JIM_TT_CMD 5
@@ -6652,10 +6752,15 @@
6652
6653
6654 #define JIM_PS_DEF 0
6655 #define JIM_PS_QUOTE 1
6656 #define JIM_PS_DICTSUGAR 2
 
 
 
 
 
6657
6658 struct JimParserCtx
6659 {
6660 const char *p;
6661 int len;
@@ -6665,17 +6770,11 @@
6665 int tline;
6666 int tt;
6667 int eof;
6668 int state;
6669 int comment;
6670 char missing;
6671 int missingline;
6672 };
6673
6674 struct JimParseResult {
6675 char missing;
6676 int line;
6677 };
6678
6679 static int JimParseScript(struct JimParserCtx *pc);
6680 static int JimParseSep(struct JimParserCtx *pc);
6681 static int JimParseEol(struct JimParserCtx *pc);
@@ -6685,11 +6784,10 @@
6685 static int JimParseBrace(struct JimParserCtx *pc);
6686 static int JimParseStr(struct JimParserCtx *pc);
6687 static int JimParseComment(struct JimParserCtx *pc);
6688 static void JimParseSubCmd(struct JimParserCtx *pc);
6689 static int JimParseSubQuote(struct JimParserCtx *pc);
6690 static void JimParseSubCmd(struct JimParserCtx *pc);
6691 static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc);
6692
6693 static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int linenr)
6694 {
6695 pc->p = prg;
@@ -6700,12 +6798,12 @@
6700 pc->tt = JIM_TT_NONE;
6701 pc->eof = 0;
6702 pc->state = JIM_PS_DEF;
6703 pc->linenr = linenr;
6704 pc->comment = 1;
6705 pc->missing = ' ';
6706 pc->missingline = linenr;
6707 }
6708
6709 static int JimParseScript(struct JimParserCtx *pc)
6710 {
6711 while (1) {
@@ -6837,12 +6935,12 @@
6837 break;
6838 }
6839 pc->p++;
6840 pc->len--;
6841 }
6842 pc->missing = '{';
6843 pc->missingline = pc->tline;
6844 pc->tend = pc->p - 1;
6845 }
6846
6847 static int JimParseSubQuote(struct JimParserCtx *pc)
6848 {
@@ -6884,12 +6982,12 @@
6884 break;
6885 }
6886 pc->p++;
6887 pc->len--;
6888 }
6889 pc->missing = '"';
6890 pc->missingline = line;
6891 pc->tend = pc->p - 1;
6892 return tt;
6893 }
6894
6895 static void JimParseSubCmd(struct JimParserCtx *pc)
@@ -6943,12 +7041,12 @@
6943 }
6944 startofword = isspace(UCHAR(*pc->p));
6945 pc->p++;
6946 pc->len--;
6947 }
6948 pc->missing = '[';
6949 pc->missingline = line;
6950 pc->tend = pc->p - 1;
6951 }
6952
6953 static int JimParseBrace(struct JimParserCtx *pc)
6954 {
@@ -7088,19 +7186,19 @@
7088 if (*pc->p == '"') {
7089 pc->state = JIM_PS_QUOTE;
7090 pc->p++;
7091 pc->len--;
7092
7093 pc->missingline = pc->tline;
7094 }
7095 }
7096 pc->tstart = pc->p;
7097 pc->tline = pc->linenr;
7098 while (1) {
7099 if (pc->len == 0) {
7100 if (pc->state == JIM_PS_QUOTE) {
7101 pc->missing = '"';
7102 }
7103 pc->tend = pc->p - 1;
7104 pc->tt = JIM_TT_ESC;
7105 return JIM_OK;
7106 }
@@ -7116,10 +7214,14 @@
7116 pc->linenr++;
7117 }
7118 pc->p++;
7119 pc->len--;
7120 }
 
 
 
 
7121 break;
7122 case '(':
7123
7124 if (pc->len > 1 && pc->p[1] != '$') {
7125 break;
@@ -7176,17 +7278,26 @@
7176 }
7177
7178 static int JimParseComment(struct JimParserCtx *pc)
7179 {
7180 while (*pc->p) {
7181 if (*pc->p == '\n') {
 
 
 
 
 
 
 
 
 
 
 
 
 
7182 pc->linenr++;
7183 if (*(pc->p - 1) != '\\') {
7184 pc->p++;
7185 pc->len--;
7186 return JIM_OK;
7187 }
7188 }
7189 pc->p++;
7190 pc->len--;
7191 }
7192 return JIM_OK;
@@ -7404,13 +7515,13 @@
7404 JimParserInit(&parser, s, len, 1);
7405 while (!parser.eof) {
7406 JimParseScript(&parser);
7407 }
7408 if (stateCharPtr) {
7409 *stateCharPtr = parser.missing;
7410 }
7411 return parser.missing == ' ';
7412 }
7413
7414 static int JimParseListSep(struct JimParserCtx *pc);
7415 static int JimParseListStr(struct JimParserCtx *pc);
7416 static int JimParseListQuote(struct JimParserCtx *pc);
@@ -7662,10 +7773,16 @@
7662 JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
7663 objPtr->typePtr->updateStringProc(objPtr);
7664 }
7665 return objPtr->bytes;
7666 }
 
 
 
 
 
 
7667
7668 static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
7669 static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
7670
7671 static const Jim_ObjType dictSubstObjType = {
@@ -7703,11 +7820,10 @@
7703 static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
7704 {
7705 JIM_NOTUSED(interp);
7706
7707 dupPtr->internalRep.strValue.maxLength = srcPtr->length;
7708
7709 dupPtr->internalRep.strValue.charLength = srcPtr->internalRep.strValue.charLength;
7710 }
7711
7712 static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
7713 {
@@ -7752,18 +7868,17 @@
7752 if (len == -1)
7753 len = strlen(s);
7754
7755 if (len == 0) {
7756 objPtr->bytes = JimEmptyStringRep;
7757 objPtr->length = 0;
7758 }
7759 else {
7760 objPtr->bytes = Jim_Alloc(len + 1);
7761 objPtr->length = len;
7762 memcpy(objPtr->bytes, s, len);
7763 objPtr->bytes[len] = '\0';
7764 }
 
7765
7766
7767 objPtr->typePtr = NULL;
7768 return objPtr;
7769 }
@@ -7791,11 +7906,11 @@
7791 Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len)
7792 {
7793 Jim_Obj *objPtr = Jim_NewObj(interp);
7794
7795 objPtr->bytes = s;
7796 objPtr->length = len == -1 ? strlen(s) : len;
7797 objPtr->typePtr = NULL;
7798 return objPtr;
7799 }
7800
7801 static void StringAppendString(Jim_Obj *objPtr, const char *str, int len)
@@ -7820,17 +7935,17 @@
7820 }
7821 objPtr->internalRep.strValue.maxLength = needlen;
7822 }
7823 memcpy(objPtr->bytes + objPtr->length, str, len);
7824 objPtr->bytes[objPtr->length + len] = '\0';
 
7825 if (objPtr->internalRep.strValue.charLength >= 0) {
7826
7827 objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len);
7828 }
7829 objPtr->length += len;
7830 }
7831
7832
7833 void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len)
7834 {
7835 JimPanic((Jim_IsShared(objPtr), "Jim_AppendString called with shared object"));
7836 SetStringFromAny(interp, objPtr);
@@ -7838,13 +7953,11 @@
7838 }
7839
7840 void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr)
7841 {
7842 int len;
7843 const char *str;
7844
7845 str = Jim_GetString(appendObjPtr, &len);
7846 Jim_AppendString(interp, objPtr, str, len);
7847 }
7848
7849 void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...)
7850 {
@@ -7851,11 +7964,11 @@
7851 va_list ap;
7852
7853 SetStringFromAny(interp, objPtr);
7854 va_start(ap, objPtr);
7855 while (1) {
7856 char *s = va_arg(ap, char *);
7857
7858 if (s == NULL)
7859 break;
7860 Jim_AppendString(interp, objPtr, s, -1);
7861 }
@@ -7862,20 +7975,20 @@
7862 va_end(ap);
7863 }
7864
7865 int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr)
7866 {
7867 const char *aStr, *bStr;
7868 int aLen, bLen;
7869
7870 if (aObjPtr == bObjPtr)
7871 return 1;
7872 aStr = Jim_GetString(aObjPtr, &aLen);
7873 bStr = Jim_GetString(bObjPtr, &bLen);
7874 if (aLen != bLen)
7875 return 0;
7876 return JimStringCompare(aStr, aLen, bStr, bLen) == 0;
 
 
 
7877 }
7878
7879 int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase)
7880 {
7881 return JimGlobMatch(Jim_String(patternObjPtr), Jim_String(objPtr), nocase);
@@ -8036,11 +8149,11 @@
8036 static void JimStrCopyUpperLower(char *dest, const char *str, int uc)
8037 {
8038 while (*str) {
8039 int c;
8040 str += utf8_tounicode(str, &c);
8041 dest += utf8_fromunicode(dest, uc ? utf8_upper(c) : utf8_lower(c));
8042 }
8043 *dest = 0;
8044 }
8045
8046 static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr)
@@ -8096,11 +8209,11 @@
8096 len *= 2;
8097 #endif
8098 buf = p = Jim_Alloc(len + 1);
8099
8100 str += utf8_tounicode(str, &c);
8101 p += utf8_fromunicode(p, utf8_title(c));
8102
8103 JimStrCopyUpperLower(p, str, 0);
8104
8105 return Jim_NewStringObjNoAlloc(interp, buf, -1);
8106 }
@@ -8203,10 +8316,11 @@
8203 if (nontrim == NULL) {
8204
8205 return Jim_NewEmptyStringObj(interp);
8206 }
8207 if (nontrim == strObjPtr->bytes + len) {
 
8208 return strObjPtr;
8209 }
8210
8211 if (Jim_IsShared(strObjPtr)) {
8212 strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes));
@@ -8226,14 +8340,14 @@
8226 Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr);
8227
8228
8229 strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr);
8230
8231 if (objPtr != strObjPtr) {
 
8232
8233 Jim_IncrRefCount(objPtr);
8234 Jim_DecrRefCount(interp, objPtr);
8235 }
8236
8237 return strObjPtr;
8238 }
8239
@@ -8270,26 +8384,26 @@
8270 return JIM_ERR;
8271 }
8272
8273 str = Jim_GetString(strObjPtr, &len);
8274 if (len == 0) {
8275 Jim_SetResultInt(interp, !strict);
8276 return JIM_OK;
8277 }
8278
8279 switch (strclass) {
8280 case STR_IS_INTEGER:
8281 {
8282 jim_wide w;
8283 Jim_SetResultInt(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK);
8284 return JIM_OK;
8285 }
8286
8287 case STR_IS_DOUBLE:
8288 {
8289 double d;
8290 Jim_SetResultInt(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE);
8291 return JIM_OK;
8292 }
8293
8294 case STR_IS_ALPHA: isclassfunc = isalpha; break;
8295 case STR_IS_ALNUM: isclassfunc = isalnum; break;
@@ -8307,15 +8421,15 @@
8307 return JIM_ERR;
8308 }
8309
8310 for (i = 0; i < len; i++) {
8311 if (!isclassfunc(str[i])) {
8312 Jim_SetResultInt(interp, 0);
8313 return JIM_OK;
8314 }
8315 }
8316 Jim_SetResultInt(interp, 1);
8317 return JIM_OK;
8318 }
8319
8320
8321
@@ -8327,17 +8441,19 @@
8327 JIM_TYPE_REFERENCES,
8328 };
8329
8330 int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str)
8331 {
8332 if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str)
8333 return 1;
 
8334 else {
8335 const char *objStr = Jim_String(objPtr);
8336
8337 if (strcmp(str, objStr) != 0)
8338 return 0;
 
8339 if (objPtr->typePtr != &comparedStringObjType) {
8340 Jim_FreeIntRep(interp, objPtr);
8341 objPtr->typePtr = &comparedStringObjType;
8342 }
8343 objPtr->internalRep.ptr = (char *)str;
@@ -8379,24 +8495,23 @@
8379
8380 static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr,
8381 Jim_Obj *fileNameObj, int lineNumber)
8382 {
8383 JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object"));
8384 JimPanic((objPtr->typePtr == &sourceObjType, "JimSetSourceInfo called with non-source object"));
8385 Jim_IncrRefCount(fileNameObj);
8386 objPtr->internalRep.sourceValue.fileNameObj = fileNameObj;
8387 objPtr->internalRep.sourceValue.lineNumber = lineNumber;
8388 objPtr->typePtr = &sourceObjType;
8389 }
8390
8391
8392 static const Jim_ObjType scriptLineObjType = {
8393 "scriptline",
8394 NULL,
8395 NULL,
8396 NULL,
8397 0,
8398 };
8399
8400 static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line)
8401 {
8402 Jim_Obj *objPtr;
@@ -8413,15 +8528,14 @@
8413 objPtr->internalRep.scriptLineValue.line = line;
8414
8415 return objPtr;
8416 }
8417
8418 #define JIM_CMDSTRUCT_EXPAND -1
8419
8420 static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
8421 static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
8422 static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result);
 
8423
8424 static const Jim_ObjType scriptObjType = {
8425 "script",
8426 FreeScriptInternalRep,
8427 DupScriptInternalRep,
@@ -8429,34 +8543,33 @@
8429 JIM_TYPE_REFERENCES,
8430 };
8431
8432 typedef struct ScriptToken
8433 {
8434 int type;
8435 Jim_Obj *objPtr;
 
8436 } ScriptToken;
8437
8438 typedef struct ScriptObj
8439 {
8440 int len;
8441 ScriptToken *token;
 
 
8442 int substFlags;
8443 int inUse; /* Used to share a ScriptObj. Currently
8444 only used by Jim_EvalObj() as protection against
8445 shimmering of the currently evaluated object. */
8446 Jim_Obj *fileNameObj;
8447 int firstline;
8448 int linenr;
8449 } ScriptObj;
8450
8451 void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
8452 {
8453 int i;
8454 struct ScriptObj *script = (void *)objPtr->internalRep.ptr;
8455
8456 script->inUse--;
8457 if (script->inUse != 0)
8458 return;
8459 for (i = 0; i < script->len; i++) {
8460 Jim_DecrRefCount(interp, script->token[i].objPtr);
8461 }
8462 Jim_Free(script->token);
@@ -8467,11 +8580,10 @@
8467 void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
8468 {
8469 JIM_NOTUSED(interp);
8470 JIM_NOTUSED(srcPtr);
8471
8472
8473 dupPtr->typePtr = NULL;
8474 }
8475
8476 typedef struct
8477 {
@@ -8666,11 +8778,11 @@
8666 token--;
8667 }
8668
8669 script->len = token - script->token;
8670
8671 assert(script->len < count);
8672
8673 #ifdef DEBUG_SHOW_SCRIPT
8674 printf("==== Script (%s) ====\n", Jim_String(script->fileNameObj));
8675 for (i = 0; i < script->len; i++) {
8676 const ScriptToken *t = &script->token[i];
@@ -8677,10 +8789,35 @@
8677 printf("[%2d] %s %s\n", i, jim_tt_name(t->type), Jim_String(t->objPtr));
8678 }
8679 #endif
8680
8681 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8682
8683 static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
8684 ParseTokenList *tokenlist)
8685 {
8686 int i;
@@ -8699,18 +8836,19 @@
8699 }
8700
8701 script->len = i;
8702 }
8703
8704 static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result)
8705 {
8706 int scriptTextLen;
8707 const char *scriptText = Jim_GetString(objPtr, &scriptTextLen);
8708 struct JimParserCtx parser;
8709 struct ScriptObj *script;
8710 ParseTokenList tokenlist;
8711 int line = 1;
 
8712
8713
8714 if (objPtr->typePtr == &sourceObjType) {
8715 line = objPtr->internalRep.sourceValue.lineNumber;
8716 }
@@ -8722,16 +8860,12 @@
8722 while (!parser.eof) {
8723 JimParseScript(&parser);
8724 ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
8725 parser.tline);
8726 }
8727 if (result && parser.missing != ' ') {
8728 ScriptTokenListFree(&tokenlist);
8729 result->missing = parser.missing;
8730 result->line = parser.missingline;
8731 return JIM_ERR;
8732 }
8733
8734
8735 ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0);
8736
8737
@@ -8742,10 +8876,11 @@
8742 script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
8743 }
8744 else {
8745 script->fileNameObj = interp->emptyObj;
8746 }
 
8747 Jim_IncrRefCount(script->fileNameObj);
8748
8749 ScriptObjAddTokens(interp, script, &tokenlist);
8750
8751
@@ -8754,11 +8889,11 @@
8754
8755 Jim_FreeIntRep(interp, objPtr);
8756 Jim_SetIntRepPtr(objPtr, script);
8757 objPtr->typePtr = &scriptObjType;
8758
8759 return JIM_OK;
8760 }
8761
8762 ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr)
8763 {
8764 if (objPtr == interp->emptyObj) {
@@ -8765,11 +8900,13 @@
8765
8766 objPtr = interp->nullScriptObj;
8767 }
8768
8769 if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) {
8770 SetScriptFromAny(interp, objPtr, NULL);
 
 
8771 }
8772 return (ScriptObj *) Jim_GetIntRepPtr(objPtr);
8773 }
8774
8775 static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr)
@@ -8850,10 +8987,26 @@
8850 nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
8851 Jim_AppendStrings(interp, nsObj, "::", name, NULL);
8852 }
8853 return nsObj;
8854 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8855
8856 static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr)
8857 {
8858 Jim_Obj *objPtr = interp->emptyObj;
8859
@@ -8877,10 +9030,15 @@
8877
8878 #else
8879
8880 #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME))
8881 #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY)
 
 
 
 
 
8882 #endif
8883
8884 static int JimCreateCommand(Jim_Interp *interp, const char *name, Jim_Cmd *cmd)
8885 {
8886 Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, name);
@@ -8889,12 +9047,12 @@
8889 Jim_InterpIncrProcEpoch(interp);
8890 }
8891
8892 if (he && interp->local) {
8893
8894 cmd->prevCmd = he->u.val;
8895 he->u.val = cmd;
8896 }
8897 else {
8898 if (he) {
8899
8900 Jim_DeleteHashEntry(&interp->commands, name);
@@ -8933,19 +9091,19 @@
8933 }
8934
8935 cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable));
8936 Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp);
8937 for (i = 0; i < len; i++) {
8938 Jim_Obj *objPtr = NULL, *initObjPtr = NULL, *nameObjPtr = NULL;
8939 Jim_Var *varPtr;
8940 int subLen;
8941
8942 Jim_ListIndex(interp, staticsListObjPtr, i, &objPtr, JIM_NONE);
8943
8944 subLen = Jim_ListLength(interp, objPtr);
8945 if (subLen == 1 || subLen == 2) {
8946 Jim_ListIndex(interp, objPtr, 0, &nameObjPtr, JIM_NONE);
8947 if (subLen == 1) {
8948 initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
8949 if (initObjPtr == NULL) {
8950 Jim_SetResultFormatted(interp,
8951 "variable for initialization of static \"%#s\" not found in the local context",
@@ -8952,11 +9110,11 @@
8952 nameObjPtr);
8953 return JIM_ERR;
8954 }
8955 }
8956 else {
8957 Jim_ListIndex(interp, objPtr, 1, &initObjPtr, JIM_NONE);
8958 }
8959 if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) {
8960 return JIM_ERR;
8961 }
8962
@@ -9038,11 +9196,11 @@
9038 Jim_Obj *nameObjPtr;
9039 Jim_Obj *defaultObjPtr;
9040 int len;
9041
9042
9043 Jim_ListIndex(interp, argListObjPtr, i, &argPtr, JIM_NONE);
9044 len = Jim_ListLength(interp, argPtr);
9045 if (len == 0) {
9046 Jim_SetResultString(interp, "argument with no name", -1);
9047 err:
9048 JimDecrCmdRefCount(interp, cmdPtr);
@@ -9053,12 +9211,12 @@
9053 goto err;
9054 }
9055
9056 if (len == 2) {
9057
9058 Jim_ListIndex(interp, argPtr, 0, &nameObjPtr, JIM_NONE);
9059 Jim_ListIndex(interp, argPtr, 1, &defaultObjPtr, JIM_NONE);
9060 }
9061 else {
9062
9063 nameObjPtr = argPtr;
9064 defaultObjPtr = NULL;
@@ -9132,11 +9290,11 @@
9132 else if (Jim_FindHashEntry(&interp->commands, fqnew)) {
9133 Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName);
9134 }
9135 else {
9136
9137 cmdPtr = he->u.val;
9138 JimIncrCmdRefCount(cmdPtr);
9139 JimUpdateProcNamespace(interp, cmdPtr, fqnew);
9140 Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr);
9141
9142
@@ -9217,11 +9375,11 @@
9217 return NULL;
9218 }
9219 #ifdef jim_ext_namespace
9220 found:
9221 #endif
9222 cmd = (Jim_Cmd *)he->u.val;
9223
9224
9225 Jim_FreeIntRep(interp, objPtr);
9226 objPtr->typePtr = &commandObjType;
9227 objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch;
@@ -9323,11 +9481,11 @@
9323
9324
9325 Jim_FreeIntRep(interp, objPtr);
9326 objPtr->typePtr = &variableObjType;
9327 objPtr->internalRep.varValue.callFrameId = framePtr->id;
9328 objPtr->internalRep.varValue.varPtr = he->u.val;
9329 objPtr->internalRep.varValue.global = global;
9330 return JIM_OK;
9331 }
9332
9333
@@ -9641,11 +9799,11 @@
9641 }
9642
9643 retval = Jim_DeleteHashEntry(&framePtr->vars, name);
9644 if (retval == JIM_OK) {
9645
9646 JimChangeCallFrameId(interp, framePtr);
9647 }
9648 }
9649 }
9650 if (retval != JIM_OK && (flags & JIM_ERRMSG)) {
9651 Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such variable", nameObjPtr);
@@ -9725,28 +9883,17 @@
9725 return NULL;
9726 }
9727
9728 ret = Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
9729 if (ret != JIM_OK) {
9730 resObjPtr = NULL;
9731 if (ret < 0) {
9732 Jim_SetResultFormatted(interp,
9733 "can't read \"%#s(%#s)\": variable isn't array", varObjPtr, keyObjPtr);
9734 }
9735 else {
9736 Jim_SetResultFormatted(interp,
9737 "can't read \"%#s(%#s)\": no such element in array", varObjPtr, keyObjPtr);
9738 }
9739 }
9740 else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) {
9741 dictObjPtr = Jim_DuplicateObj(interp, dictObjPtr);
9742 if (Jim_SetVariable(interp, varObjPtr, dictObjPtr) != JIM_OK) {
9743
9744 JimPanic((1, "SetVariable failed for JIM_UNSHARED"));
9745 }
9746
9747 Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
9748 }
9749
9750 return resObjPtr;
9751 }
9752
@@ -9843,68 +9990,67 @@
9843 Jim_CallFrame *cf;
9844
9845 if (interp->freeFramesList) {
9846 cf = interp->freeFramesList;
9847 interp->freeFramesList = cf->next;
 
 
 
 
 
 
 
 
 
 
 
9848 }
9849 else {
9850 cf = Jim_Alloc(sizeof(*cf));
9851 cf->vars.table = NULL;
 
 
9852 }
9853
9854 cf->id = interp->callFrameEpoch++;
9855 cf->parent = parent;
9856 cf->level = parent ? parent->level + 1 : 0;
9857 cf->argv = NULL;
9858 cf->argc = 0;
9859 cf->procArgsObjPtr = NULL;
9860 cf->procBodyObjPtr = NULL;
9861 cf->next = NULL;
9862 cf->staticVars = NULL;
9863 cf->localCommands = NULL;
9864
9865 cf->nsObj = nsObj;
9866 Jim_IncrRefCount(nsObj);
9867 if (cf->vars.table == NULL)
9868 Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp);
9869 return cf;
9870 }
9871
9872
9873 static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf)
9874 {
9875 cf->id = interp->callFrameEpoch++;
9876 }
9877
9878 static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands)
9879 {
9880
9881 if (localCommands) {
9882 Jim_Obj *cmdNameObj;
9883
9884 while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) {
9885 Jim_HashEntry *he;
9886 Jim_Obj *fqObjName;
 
9887
9888 const char *fqname = JimQualifyName(interp, Jim_String(cmdNameObj), &fqObjName);
9889
9890 he = Jim_FindHashEntry(&interp->commands, fqname);
9891
9892 if (he) {
9893 Jim_Cmd *cmd = he->u.val;
9894 if (cmd->prevCmd) {
9895 Jim_Cmd *prevCmd = cmd->prevCmd;
9896 cmd->prevCmd = NULL;
9897
9898
9899 JimDecrCmdRefCount(interp, cmd);
9900
9901
9902 he->u.val = prevCmd;
9903 }
9904 else {
9905 Jim_DeleteHashEntry(&interp->commands, fqname);
9906 Jim_InterpIncrProcEpoch(interp);
9907 }
9908 }
9909 Jim_DecrRefCount(interp, cmdNameObj);
9910 JimFreeQualifiedName(interp, fqObjName);
@@ -9914,47 +10060,45 @@
9914 }
9915 return JIM_OK;
9916 }
9917
9918
9919 #define JIM_FCF_NONE 0
9920 #define JIM_FCF_NOHT 1
9921 static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags)
9922 {
 
 
9923 if (cf->procArgsObjPtr)
9924 Jim_DecrRefCount(interp, cf->procArgsObjPtr);
9925 if (cf->procBodyObjPtr)
9926 Jim_DecrRefCount(interp, cf->procBodyObjPtr);
9927 Jim_DecrRefCount(interp, cf->nsObj);
9928 if (!(flags & JIM_FCF_NOHT))
9929 Jim_FreeHashTable(&cf->vars);
9930 else {
9931 int i;
9932 Jim_HashEntry **table = cf->vars.table, *he;
9933
9934 for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) {
9935 he = table[i];
9936 while (he != NULL) {
9937 Jim_HashEntry *nextEntry = he->next;
9938 Jim_Var *varPtr = (void *)he->u.val;
9939
9940 Jim_DecrRefCount(interp, varPtr->objPtr);
9941 Jim_Free(he->u.val);
9942 Jim_Free((void *)he->key);
9943 Jim_Free(he);
9944 table[i] = NULL;
9945 he = nextEntry;
9946 }
9947 }
9948 cf->vars.used = 0;
9949 }
9950
9951 JimDeleteLocalProcs(interp, cf->localCommands);
9952
9953 cf->next = interp->freeFramesList;
9954 interp->freeFramesList = cf;
9955
9956 }
9957
9958
9959 #ifdef JIM_REFERENCES
9960
@@ -10031,21 +10175,16 @@
10031 NULL,
10032 UpdateStringOfReference,
10033 JIM_TYPE_REFERENCES,
10034 };
10035
10036 void UpdateStringOfReference(struct Jim_Obj *objPtr)
10037 {
10038 int len;
10039 char buf[JIM_REFERENCE_SPACE + 1];
10040 Jim_Reference *refPtr;
10041
10042 refPtr = objPtr->internalRep.refValue.refPtr;
10043 len = JimFormatReference(buf, refPtr, objPtr->internalRep.refValue.id);
10044 objPtr->bytes = Jim_Alloc(len + 1);
10045 memcpy(objPtr->bytes, buf, len + 1);
10046 objPtr->length = len;
10047 }
10048
10049 static int isrefchar(int c)
10050 {
10051 return (c == '_' || isalnum(c));
@@ -10096,11 +10235,11 @@
10096 he = Jim_FindHashEntry(&interp->references, &value);
10097 if (he == NULL) {
10098 Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr);
10099 return JIM_ERR;
10100 }
10101 refPtr = he->u.val;
10102
10103 Jim_FreeIntRep(interp, objPtr);
10104 objPtr->typePtr = &referenceObjType;
10105 objPtr->internalRep.refValue.id = value;
10106 objPtr->internalRep.refValue.refPtr = refPtr;
@@ -10279,13 +10418,20 @@
10279 return i;
10280 }
10281
10282 void Jim_FreeInterp(Jim_Interp *i)
10283 {
10284 Jim_CallFrame *cf = i->framePtr, *prevcf, *nextcf;
 
10285 Jim_Obj *objPtr, *nextObjPtr;
10286
 
 
 
 
 
 
10287 Jim_DecrRefCount(i, i->emptyObj);
10288 Jim_DecrRefCount(i, i->trueObj);
10289 Jim_DecrRefCount(i, i->falseObj);
10290 Jim_DecrRefCount(i, i->result);
10291 Jim_DecrRefCount(i, i->stackTrace);
@@ -10300,61 +10446,54 @@
10300 #endif
10301 Jim_FreeHashTable(&i->packages);
10302 Jim_Free(i->prngState);
10303 Jim_FreeHashTable(&i->assocData);
10304
10305
10306 while (cf) {
10307 prevcf = cf->parent;
10308 JimFreeCallFrame(i, cf, JIM_FCF_NONE);
10309 cf = prevcf;
10310 }
10311 if (i->liveList != NULL) {
10312 objPtr = i->liveList;
10313
10314 printf(JIM_NL "-------------------------------------" JIM_NL);
10315 printf("Objects still in the free list:" JIM_NL);
10316 while (objPtr) {
10317 const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string";
10318
10319 if (objPtr->bytes && strlen(objPtr->bytes) > 20) {
10320 printf("%p (%d) %-10s: '%.20s...'" JIM_NL,
10321 (void *)objPtr, objPtr->refCount, type, objPtr->bytes);
10322 }
10323 else {
10324 printf("%p (%d) %-10s: '%s'" JIM_NL,
10325 (void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)");
10326 }
10327 if (objPtr->typePtr == &sourceObjType) {
10328 printf("FILE %s LINE %d" JIM_NL,
10329 Jim_String(objPtr->internalRep.sourceValue.fileNameObj),
10330 objPtr->internalRep.sourceValue.lineNumber);
10331 }
10332 objPtr = objPtr->nextObjPtr;
10333 }
10334 printf("-------------------------------------" JIM_NL JIM_NL);
10335 JimPanic((1, "Live list non empty freeing the interpreter! Leak?"));
10336 }
 
 
10337
10338 objPtr = i->freeList;
10339 while (objPtr) {
10340 nextObjPtr = objPtr->nextObjPtr;
10341 Jim_Free(objPtr);
10342 objPtr = nextObjPtr;
10343 }
 
10344
10345 cf = i->freeFramesList;
10346 while (cf) {
10347 nextcf = cf->next;
10348 if (cf->vars.table != NULL)
10349 Jim_Free(cf->vars.table);
10350 Jim_Free(cf);
10351 cf = nextcf;
10352 }
10353 #ifdef jim_ext_load
10354 Jim_FreeLoadHandles(i);
10355 #endif
10356
10357
10358 Jim_Free(i);
10359 }
10360
@@ -10455,11 +10594,10 @@
10455 interp->addStackTrace = 1;
10456 }
10457 }
10458 }
10459
10460
10461 static void JimAppendStackTrace(Jim_Interp *interp, const char *procname,
10462 Jim_Obj *fileNameObj, int linenr)
10463 {
10464 if (strcmp(procname, "unknown") == 0) {
10465 procname = "";
@@ -10513,12 +10651,11 @@
10513 void *Jim_GetAssocData(Jim_Interp *interp, const char *key)
10514 {
10515 Jim_HashEntry *entryPtr = Jim_FindHashEntry(&interp->assocData, key);
10516
10517 if (entryPtr != NULL) {
10518 AssocDataValue *assocEntryPtr = (AssocDataValue *) entryPtr->u.val;
10519
10520 return assocEntryPtr->data;
10521 }
10522 return NULL;
10523 }
10524
@@ -10552,20 +10689,44 @@
10552 };
10553
10554
10555 static void UpdateStringOfInt(struct Jim_Obj *objPtr)
10556 {
10557 int len;
10558 char buf[JIM_INTEGER_SPACE + 1];
 
 
10559
10560 len = JimWideToString(buf, JimWideValue(objPtr));
10561 objPtr->bytes = Jim_Alloc(len + 1);
10562 memcpy(objPtr->bytes, buf, len + 1);
10563 objPtr->length = len;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10564 }
10565
10566 int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
10567 {
10568 jim_wide wideValue;
10569 const char *str;
10570
10571 if (objPtr->typePtr == &coercedDoubleObjType) {
@@ -10653,22 +10814,65 @@
10653 NULL,
10654 UpdateStringOfDouble,
10655 JIM_TYPE_NONE,
10656 };
10657
10658 void UpdateStringOfDouble(struct Jim_Obj *objPtr)
10659 {
10660 int len;
10661 char buf[JIM_DOUBLE_SPACE + 1];
10662
10663 len = Jim_DoubleToString(buf, objPtr->internalRep.doubleValue);
10664 objPtr->bytes = Jim_Alloc(len + 1);
10665 memcpy(objPtr->bytes, buf, len + 1);
10666 objPtr->length = len;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10667 }
10668
10669 int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
10670 {
10671 double doubleValue;
10672 jim_wide wideValue;
10673 const char *str;
10674
@@ -10876,15 +11080,15 @@
10876 return JIM_ELESTR_SIMPLE;
10877 }
10878 return JIM_ELESTR_QUOTE;
10879 }
10880
10881 static int BackslashQuoteString(const char *s, char *q)
10882 {
10883 char *p = q;
10884
10885 while (*s) {
10886 switch (*s) {
10887 case ' ':
10888 case '$':
10889 case '"':
10890 case '[':
@@ -10996,11 +11200,11 @@
10996 case JIM_ELESTR_QUOTE:
10997 if (i == 0 && strRep[0] == '#') {
10998 *p++ = '\\';
10999 realLength++;
11000 }
11001 qlen = BackslashQuoteString(strRep, p);
11002 p += qlen;
11003 realLength += qlen;
11004 break;
11005 }
11006
@@ -11032,11 +11236,11 @@
11032
11033 if (objPtr->typePtr == &listObjType) {
11034 return JIM_OK;
11035 }
11036
11037 if (Jim_IsDict(objPtr) && !Jim_IsShared(objPtr)) {
11038 Jim_Obj **listObjPtrPtr;
11039 int len;
11040 int i;
11041
11042 listObjPtrPtr = JimDictPairs(objPtr, &len);
@@ -11136,15 +11340,17 @@
11136 Jim_Interp *interp;
11137 enum {
11138 JIM_LSORT_ASCII,
11139 JIM_LSORT_NOCASE,
11140 JIM_LSORT_INTEGER,
 
11141 JIM_LSORT_COMMAND
11142 } type;
11143 int order;
11144 int index;
11145 int indexed;
 
11146 int (*subfn)(Jim_Obj **, Jim_Obj **);
11147 };
11148
11149 static struct lsort_info *sort_info;
11150
@@ -11179,10 +11385,27 @@
11179 longjmp(sort_info->jmpbuf, JIM_ERR);
11180 }
11181
11182 return JimSign(lhs - rhs) * sort_info->order;
11183 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11184
11185 static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
11186 {
11187 Jim_Obj *compare_script;
11188 int rc;
@@ -11201,10 +11424,34 @@
11201 }
11202
11203 return JimSign(ret) * sort_info->order;
11204 }
11205
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11206
11207 static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info)
11208 {
11209 struct lsort_info *prev_info;
11210
@@ -11212,11 +11459,11 @@
11212 int (*fn) (Jim_Obj **, Jim_Obj **);
11213 Jim_Obj **vector;
11214 int len;
11215 int rc;
11216
11217 JimPanic((Jim_IsShared(listObjPtr), "Jim_ListSortElements called with shared object"));
11218 SetListFromAny(interp, listObjPtr);
11219
11220
11221 prev_info = sort_info;
11222 sort_info = info;
@@ -11231,10 +11478,13 @@
11231 fn = ListSortStringNoCase;
11232 break;
11233 case JIM_LSORT_INTEGER:
11234 fn = ListSortInteger;
11235 break;
 
 
 
11236 case JIM_LSORT_COMMAND:
11237 fn = ListSortCommand;
11238 break;
11239 default:
11240 fn = NULL;
@@ -11247,12 +11497,17 @@
11247 fn = ListSortIndexHelper;
11248 }
11249
11250 if ((rc = setjmp(info->jmpbuf)) == 0) {
11251 qsort(vector, len, sizeof(Jim_Obj *), (qsort_comparator *) fn);
 
 
 
 
 
 
11252 }
11253 Jim_InvalidateStringRep(listObjPtr);
11254 sort_info = prev_info;
11255
11256 return rc;
11257 }
11258
@@ -11377,11 +11632,11 @@
11377 listPtr->internalRep.listValue.ele[idx] = newObjPtr;
11378 Jim_IncrRefCount(newObjPtr);
11379 return JIM_OK;
11380 }
11381
11382 int Jim_SetListIndex(Jim_Interp *interp, Jim_Obj *varNamePtr,
11383 Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr)
11384 {
11385 Jim_Obj *varObjPtr, *objPtr, *listObjPtr;
11386 int shared, i, idx;
11387
@@ -11425,14 +11680,11 @@
11425 int i;
11426 int listLen = Jim_ListLength(interp, listObjPtr);
11427 Jim_Obj *resObjPtr = Jim_NewEmptyStringObj(interp);
11428
11429 for (i = 0; i < listLen; ) {
11430 Jim_Obj *objPtr;
11431
11432 Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE);
11433 Jim_AppendObj(interp, resObjPtr, objPtr);
11434 if (++i != listLen) {
11435 Jim_AppendString(interp, resObjPtr, joinStr, joinStrLen);
11436 }
11437 }
11438 return resObjPtr;
@@ -11458,43 +11710,42 @@
11458 int len = 0, objLen;
11459 char *bytes, *p;
11460
11461
11462 for (i = 0; i < objc; i++) {
11463 Jim_GetString(objv[i], &objLen);
11464 len += objLen;
11465 }
11466 if (objc)
11467 len += objc - 1;
11468
11469 p = bytes = Jim_Alloc(len + 1);
11470 for (i = 0; i < objc; i++) {
11471 const char *s = Jim_GetString(objv[i], &objLen);
11472
11473
11474 while (objLen && (*s == ' ' || *s == '\t' || *s == '\n')) {
11475 s++;
11476 objLen--;
11477 len--;
11478 }
11479
11480 while (objLen && (s[objLen - 1] == ' ' ||
11481 s[objLen - 1] == '\n' || s[objLen - 1] == '\t')) {
11482
11483 if (objLen > 1 && s[objLen - 2] == '\\') {
11484 break;
11485 }
11486 objLen--;
11487 len--;
11488 }
11489 memcpy(p, s, objLen);
11490 p += objLen;
11491 if (objLen && i + 1 != objc) {
11492 *p++ = ' ';
11493 }
11494 else if (i + 1 != objc) {
11495 len--;
 
11496 }
11497 }
11498 *p = '\0';
11499 return Jim_NewStringObjNoAlloc(interp, bytes, len);
11500 }
@@ -11534,20 +11785,26 @@
11534
11535 static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2)
11536 {
11537 return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2);
11538 }
 
 
 
 
 
 
11539
11540 static void JimObjectHTKeyValDestructor(void *interp, void *val)
11541 {
11542 Jim_DecrRefCount(interp, (Jim_Obj *)val);
11543 }
11544
11545 static const Jim_HashTableType JimDictHashTableType = {
11546 JimObjectHTHashFunction,
11547 NULL,
11548 NULL,
11549 JimObjectHTKeyCompare,
11550 JimObjectHTKeyValDestructor,
11551 JimObjectHTKeyValDestructor
11552 };
11553
@@ -11580,16 +11837,11 @@
11580 if (ht->size != 0)
11581 Jim_ExpandHashTable(dupHt, ht->size);
11582
11583 JimInitHashTableIterator(ht, &htiter);
11584 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
11585 const Jim_Obj *keyObjPtr = he->key;
11586 Jim_Obj *valObjPtr = he->u.val;
11587
11588 Jim_IncrRefCount((Jim_Obj *)keyObjPtr);
11589 Jim_IncrRefCount(valObjPtr);
11590 Jim_AddHashEntry(dupHt, keyObjPtr, valObjPtr);
11591 }
11592
11593 dupPtr->internalRep.ptr = dupHt;
11594 dupPtr->typePtr = &dictObjType;
11595 }
@@ -11607,12 +11859,12 @@
11607
11608 objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
11609 JimInitHashTableIterator(ht, &htiter);
11610 i = 0;
11611 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
11612 objv[i++] = (Jim_Obj *)he->key;
11613 objv[i++] = he->u.val;
11614 }
11615 *len = i;
11616 return objv;
11617 }
11618
@@ -11620,10 +11872,11 @@
11620 {
11621
11622 int len;
11623 Jim_Obj **objv = JimDictPairs(objPtr, &len);
11624
 
11625 JimMakeListStringRep(objPtr, objv, len);
11626
11627 Jim_Free(objv);
11628 }
11629
@@ -11633,11 +11886,13 @@
11633
11634 if (objPtr->typePtr == &dictObjType) {
11635 return JIM_OK;
11636 }
11637
11638 Jim_String(objPtr);
 
 
11639
11640
11641 listlen = Jim_ListLength(interp, objPtr);
11642 if (listlen % 2) {
11643 Jim_SetResultString(interp, "missing value to go with key", -1);
@@ -11650,28 +11905,14 @@
11650
11651 ht = Jim_Alloc(sizeof(*ht));
11652 Jim_InitHashTable(ht, &JimDictHashTableType, interp);
11653
11654 for (i = 0; i < listlen; i += 2) {
11655 Jim_Obj *keyObjPtr;
11656 Jim_Obj *valObjPtr;
11657
11658 Jim_ListIndex(interp, objPtr, i, &keyObjPtr, JIM_NONE);
11659 Jim_ListIndex(interp, objPtr, i + 1, &valObjPtr, JIM_NONE);
11660
11661 Jim_IncrRefCount(keyObjPtr);
11662 Jim_IncrRefCount(valObjPtr);
11663
11664 if (Jim_AddHashEntry(ht, keyObjPtr, valObjPtr) != JIM_OK) {
11665 Jim_HashEntry *he;
11666
11667 he = Jim_FindHashEntry(ht, keyObjPtr);
11668 Jim_DecrRefCount(interp, keyObjPtr);
11669
11670 Jim_DecrRefCount(interp, (Jim_Obj *)he->u.val);
11671 he->u.val = valObjPtr;
11672 }
11673 }
11674
11675 Jim_FreeIntRep(interp, objPtr);
11676 objPtr->typePtr = &dictObjType;
11677 objPtr->internalRep.ptr = ht;
@@ -11688,31 +11929,23 @@
11688 Jim_HashTable *ht = objPtr->internalRep.ptr;
11689
11690 if (valueObjPtr == NULL) {
11691 return Jim_DeleteHashEntry(ht, keyObjPtr);
11692 }
11693 Jim_IncrRefCount(keyObjPtr);
11694 Jim_IncrRefCount(valueObjPtr);
11695 if (Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr)) {
11696
11697 Jim_DecrRefCount(interp, keyObjPtr);
11698 }
11699 return JIM_OK;
11700 }
11701
11702 int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
11703 Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
11704 {
11705 int retcode;
11706
11707 JimPanic((Jim_IsShared(objPtr), "Jim_DictAddElement called with shared object"));
11708 if (SetDictFromAny(interp, objPtr) != JIM_OK) {
11709 return JIM_ERR;
11710 }
11711 retcode = DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr);
11712 Jim_InvalidateStringRep(objPtr);
11713 return retcode;
11714 }
11715
11716 Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len)
11717 {
11718 Jim_Obj *objPtr;
@@ -11839,10 +12072,11 @@
11839 }
11840 objPtr = Jim_NewDictObj(interp, NULL, 0);
11841 DictAddElement(interp, dictObjPtr, keyv[i], objPtr);
11842 }
11843 }
 
11844 Jim_InvalidateStringRep(objPtr);
11845 Jim_InvalidateStringRep(varObjPtr);
11846 if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
11847 goto err;
11848 }
@@ -11864,28 +12098,29 @@
11864 NULL,
11865 UpdateStringOfIndex,
11866 JIM_TYPE_NONE,
11867 };
11868
11869 void UpdateStringOfIndex(struct Jim_Obj *objPtr)
11870 {
11871 int len;
11872 char buf[JIM_INTEGER_SPACE + 1];
11873
11874 if (objPtr->internalRep.intValue >= 0)
11875 len = sprintf(buf, "%d", objPtr->internalRep.intValue);
11876 else if (objPtr->internalRep.intValue == -1)
11877 len = sprintf(buf, "end");
11878 else {
11879 len = sprintf(buf, "end%d", objPtr->internalRep.intValue + 1);
 
 
 
 
 
 
 
 
11880 }
11881 objPtr->bytes = Jim_Alloc(len + 1);
11882 memcpy(objPtr->bytes, buf, len + 1);
11883 objPtr->length = len;
11884 }
11885
11886 int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
11887 {
11888 int idx, end = 0;
11889 const char *str;
11890 char *endptr;
11891
@@ -11953,14 +12188,17 @@
11953 {
11954
11955 if (objPtr->typePtr == &intObjType) {
11956 jim_wide val = JimWideValue(objPtr);
11957
11958 if (!(val < LONG_MIN) && !(val > LONG_MAX)) {
11959 *indexPtr = (val < 0) ? -INT_MAX : (long)val;;
11960 return JIM_OK;
11961 }
 
 
 
11962 }
11963 if (objPtr->typePtr != &indexObjType && SetIndexFromAny(interp, objPtr) == JIM_ERR)
11964 return JIM_ERR;
11965 *indexPtr = objPtr->internalRep.intValue;
11966 return JIM_OK;
@@ -11980,12 +12218,10 @@
11980 NULL
11981 };
11982
11983 #define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes))
11984
11985 static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
11986
11987 static const Jim_ObjType returnCodeObjType = {
11988 "return-code",
11989 NULL,
11990 NULL,
11991 NULL,
@@ -12000,11 +12236,11 @@
12000 else {
12001 return jimReturnCodes[code];
12002 }
12003 }
12004
12005 int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
12006 {
12007 int returnCode;
12008 jim_wide wideValue;
12009
12010
@@ -12152,24 +12388,21 @@
12152 return e->stack[--e->stacklen];
12153 }
12154
12155 static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e)
12156 {
12157 int intresult = 0;
12158 int rc = JIM_OK;
12159 Jim_Obj *A = ExprPop(e);
12160 double dA, dC = 0;
12161 jim_wide wA, wC = 0;
12162
12163 if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) {
12164 intresult = 1;
12165
12166 switch (e->opcode) {
12167 case JIM_EXPROP_FUNC_INT:
12168 wC = wA;
12169 break;
12170 case JIM_EXPROP_FUNC_ROUND:
 
12171 wC = wA;
12172 break;
12173 case JIM_EXPROP_FUNC_DOUBLE:
12174 dC = wA;
12175 intresult = 0;
@@ -12178,13 +12411,10 @@
12178 wC = wA >= 0 ? wA : -wA;
12179 break;
12180 case JIM_EXPROP_UNARYMINUS:
12181 wC = -wA;
12182 break;
12183 case JIM_EXPROP_UNARYPLUS:
12184 wC = wA;
12185 break;
12186 case JIM_EXPROP_NOT:
12187 wC = !wA;
12188 break;
12189 default:
12190 abort();
@@ -12192,31 +12422,29 @@
12192 }
12193 else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) {
12194 switch (e->opcode) {
12195 case JIM_EXPROP_FUNC_INT:
12196 wC = dA;
12197 intresult = 1;
12198 break;
12199 case JIM_EXPROP_FUNC_ROUND:
12200 wC = dA < 0 ? (dA - 0.5) : (dA + 0.5);
12201 intresult = 1;
12202 break;
12203 case JIM_EXPROP_FUNC_DOUBLE:
 
12204 dC = dA;
 
12205 break;
12206 case JIM_EXPROP_FUNC_ABS:
12207 dC = dA >= 0 ? dA : -dA;
 
12208 break;
12209 case JIM_EXPROP_UNARYMINUS:
12210 dC = -dA;
12211 break;
12212 case JIM_EXPROP_UNARYPLUS:
12213 dC = dA;
12214 break;
12215 case JIM_EXPROP_NOT:
12216 wC = !dA;
12217 intresult = 1;
12218 break;
12219 default:
12220 abort();
12221 }
12222 }
@@ -12427,11 +12655,11 @@
12427
12428
12429
12430 static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
12431 {
12432 int intresult = 0;
12433 int rc = JIM_OK;
12434 double dA, dB, dC = 0;
12435 jim_wide wA, wB, wC = 0;
12436
12437 Jim_Obj *B = ExprPop(e);
@@ -12441,12 +12669,10 @@
12441 (B->typePtr != &doubleObjType || B->bytes) &&
12442 JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) {
12443
12444
12445
12446 intresult = 1;
12447
12448 switch (e->opcode) {
12449 case JIM_EXPROP_POW:
12450 case JIM_EXPROP_FUNC_POW:
12451 wC = JimPowWide(wA, wB);
12452 break;
@@ -12496,10 +12722,11 @@
12496 default:
12497 abort();
12498 }
12499 }
12500 else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) {
 
12501 switch (e->opcode) {
12502 case JIM_EXPROP_POW:
12503 case JIM_EXPROP_FUNC_POW:
12504 #ifdef JIM_MATH_FUNCTIONS
12505 dC = pow(dA, dB);
@@ -12561,12 +12788,10 @@
12561
12562
12563
12564 int i = Jim_StringCompareObj(interp, A, B, 0);
12565
12566 intresult = 1;
12567
12568 switch (e->opcode) {
12569 case JIM_EXPROP_LT:
12570 wC = i < 0;
12571 break;
12572 case JIM_EXPROP_GT:
@@ -12610,15 +12835,11 @@
12610 int listlen;
12611 int i;
12612
12613 listlen = Jim_ListLength(interp, listObjPtr);
12614 for (i = 0; i < listlen; i++) {
12615 Jim_Obj *objPtr;
12616
12617 Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE);
12618
12619 if (Jim_StringEqObj(objPtr, valObj)) {
12620 return 1;
12621 }
12622 }
12623 return 0;
12624 }
@@ -12630,23 +12851,16 @@
12630
12631 jim_wide wC;
12632
12633 switch (e->opcode) {
12634 case JIM_EXPROP_STREQ:
12635 case JIM_EXPROP_STRNE: {
12636 int Alen, Blen;
12637 const char *sA = Jim_GetString(A, &Alen);
12638 const char *sB = Jim_GetString(B, &Blen);
12639
12640 if (e->opcode == JIM_EXPROP_STREQ) {
12641 wC = (Alen == Blen && memcmp(sA, sB, Alen) == 0);
12642 }
12643 else {
12644 wC = (Alen != Blen || memcmp(sA, sB, Alen) != 0);
12645 }
12646 break;
12647 }
12648 case JIM_EXPROP_STRIN:
12649 wC = JimSearchList(interp, B, A);
12650 break;
12651 case JIM_EXPROP_STRNI:
12652 wC = !JimSearchList(interp, B, A);
@@ -12818,96 +13032,98 @@
12818 LAZY_OP,
12819 LAZY_LEFT,
12820 LAZY_RIGHT
12821 };
12822
12823 #define OPRINIT(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1}
 
12824
12825 static const struct Jim_ExprOperator Jim_ExprOperators[] = {
12826 OPRINIT("*", 110, 2, JimExprOpBin, LAZY_NONE),
12827 OPRINIT("/", 110, 2, JimExprOpBin, LAZY_NONE),
12828 OPRINIT("%", 110, 2, JimExprOpIntBin, LAZY_NONE),
12829
12830 OPRINIT("-", 100, 2, JimExprOpBin, LAZY_NONE),
12831 OPRINIT("+", 100, 2, JimExprOpBin, LAZY_NONE),
12832
12833 OPRINIT("<<", 90, 2, JimExprOpIntBin, LAZY_NONE),
12834 OPRINIT(">>", 90, 2, JimExprOpIntBin, LAZY_NONE),
12835
12836 OPRINIT("<<<", 90, 2, JimExprOpIntBin, LAZY_NONE),
12837 OPRINIT(">>>", 90, 2, JimExprOpIntBin, LAZY_NONE),
12838
12839 OPRINIT("<", 80, 2, JimExprOpBin, LAZY_NONE),
12840 OPRINIT(">", 80, 2, JimExprOpBin, LAZY_NONE),
12841 OPRINIT("<=", 80, 2, JimExprOpBin, LAZY_NONE),
12842 OPRINIT(">=", 80, 2, JimExprOpBin, LAZY_NONE),
12843
12844 OPRINIT("==", 70, 2, JimExprOpBin, LAZY_NONE),
12845 OPRINIT("!=", 70, 2, JimExprOpBin, LAZY_NONE),
12846
12847 OPRINIT("&", 50, 2, JimExprOpIntBin, LAZY_NONE),
12848 OPRINIT("^", 49, 2, JimExprOpIntBin, LAZY_NONE),
12849 OPRINIT("|", 48, 2, JimExprOpIntBin, LAZY_NONE),
12850
12851 OPRINIT("&&", 10, 2, NULL, LAZY_OP),
12852 OPRINIT(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT),
12853 OPRINIT(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT),
12854
12855 OPRINIT("||", 9, 2, NULL, LAZY_OP),
12856 OPRINIT(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT),
12857 OPRINIT(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT),
12858
12859 OPRINIT("?", 5, 2, JimExprOpNull, LAZY_OP),
12860 OPRINIT(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT),
12861 OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
12862
12863 OPRINIT(":", 5, 2, JimExprOpNull, LAZY_OP),
12864 OPRINIT(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT),
12865 OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
12866
12867 OPRINIT("**", 250, 2, JimExprOpBin, LAZY_NONE),
12868
12869 OPRINIT("eq", 60, 2, JimExprOpStrBin, LAZY_NONE),
12870 OPRINIT("ne", 60, 2, JimExprOpStrBin, LAZY_NONE),
12871
12872 OPRINIT("in", 55, 2, JimExprOpStrBin, LAZY_NONE),
12873 OPRINIT("ni", 55, 2, JimExprOpStrBin, LAZY_NONE),
12874
12875 OPRINIT("!", 150, 1, JimExprOpNumUnary, LAZY_NONE),
12876 OPRINIT("~", 150, 1, JimExprOpIntUnary, LAZY_NONE),
12877 OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE),
12878 OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE),
12879
12880
12881
12882 OPRINIT("int", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12883 OPRINIT("abs", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12884 OPRINIT("double", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12885 OPRINIT("round", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12886 OPRINIT("rand", 200, 0, JimExprOpNone, LAZY_NONE),
12887 OPRINIT("srand", 200, 1, JimExprOpIntUnary, LAZY_NONE),
12888
12889 #ifdef JIM_MATH_FUNCTIONS
12890 OPRINIT("sin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12891 OPRINIT("cos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12892 OPRINIT("tan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12893 OPRINIT("asin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12894 OPRINIT("acos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12895 OPRINIT("atan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12896 OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12897 OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12898 OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12899 OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12900 OPRINIT("floor", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12901 OPRINIT("exp", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12902 OPRINIT("log", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12903 OPRINIT("log10", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12904 OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12905 OPRINIT("pow", 200, 2, JimExprOpBin, LAZY_NONE),
12906 #endif
12907 };
12908 #undef OPRINIT
 
12909
12910 #define JIM_EXPR_OPERATORS_NUM \
12911 (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))
12912
12913 static int JimParseExpression(struct JimParserCtx *pc)
@@ -12919,13 +13135,16 @@
12919 }
12920 pc->p++;
12921 pc->len--;
12922 }
12923
 
 
 
 
12924 if (pc->len == 0) {
12925 pc->tstart = pc->tend = pc->p;
12926 pc->tline = pc->linenr;
12927 pc->tt = JIM_TT_EOL;
12928 pc->eof = 1;
12929 return JIM_OK;
12930 }
12931 switch (*(pc->p)) {
@@ -12936,12 +13155,11 @@
12936 pc->tt = JIM_TT_SUBEXPR_END;
12937 goto singlechar;
12938 case ',':
12939 pc->tt = JIM_TT_SUBEXPR_COMMA;
12940 singlechar:
12941 pc->tstart = pc->tend = pc->p;
12942 pc->tline = pc->linenr;
12943 pc->p++;
12944 pc->len--;
12945 break;
12946 case '[':
12947 return JimParseCmd(pc);
@@ -12987,82 +13205,44 @@
12987 return JIM_OK;
12988 }
12989
12990 static int JimParseExprNumber(struct JimParserCtx *pc)
12991 {
12992 int allowdot = 1;
12993 int base = 10;
12994
12995
12996 pc->tt = JIM_TT_EXPR_INT;
12997 pc->tstart = pc->p;
12998 pc->tline = pc->linenr;
12999
13000
13001 if (pc->p[0] == '0') {
13002 switch (pc->p[1]) {
13003 case 'x':
13004 case 'X':
13005 base = 16;
13006 allowdot = 0;
13007 pc->p += 2;
13008 pc->len -= 2;
13009 break;
13010 case 'o':
13011 case 'O':
13012 base = 8;
13013 allowdot = 0;
13014 pc->p += 2;
13015 pc->len -= 2;
13016 break;
13017 case 'b':
13018 case 'B':
13019 base = 2;
13020 allowdot = 0;
13021 pc->p += 2;
13022 pc->len -= 2;
13023 break;
13024 }
13025 }
13026
13027 while (isdigit(UCHAR(*pc->p))
13028 || (base == 16 && isxdigit(UCHAR(*pc->p)))
13029 || (base == 8 && *pc->p >= '0' && *pc->p <= '7')
13030 || (base == 2 && (*pc->p == '0' || *pc->p == '1'))
13031 || (allowdot && *pc->p == '.')
13032 ) {
13033 if (*pc->p == '.') {
13034 allowdot = 0;
13035 pc->tt = JIM_TT_EXPR_DOUBLE;
13036 }
13037 pc->p++;
13038 pc->len--;
13039 if (base == 10 && (*pc->p == 'e' || *pc->p == 'E') && (pc->p[1] == '-' || pc->p[1] == '+'
13040 || isdigit(UCHAR(pc->p[1])))) {
13041 pc->p += 2;
13042 pc->len -= 2;
13043 pc->tt = JIM_TT_EXPR_DOUBLE;
13044 }
13045 }
13046 pc->tend = pc->p - 1;
 
13047 return JIM_OK;
13048 }
13049
13050 static int JimParseExprIrrational(struct JimParserCtx *pc)
13051 {
13052 const char *Tokens[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL };
13053 const char **token;
13054
13055 for (token = Tokens; *token != NULL; token++) {
13056 int len = strlen(*token);
13057
13058 if (strncmp(*token, pc->p, len) == 0) {
13059 pc->tstart = pc->p;
13060 pc->tend = pc->p + len - 1;
13061 pc->p += len;
13062 pc->len -= len;
13063 pc->tline = pc->linenr;
13064 pc->tt = JIM_TT_EXPR_DOUBLE;
13065 return JIM_OK;
13066 }
13067 }
13068 return JIM_ERR;
@@ -13102,15 +13282,13 @@
13102 }
13103 if (*p != '(') {
13104 return JIM_ERR;
13105 }
13106 }
13107 pc->tstart = pc->p;
13108 pc->tend = pc->p + bestLen - 1;
13109 pc->p += bestLen;
13110 pc->len -= bestLen;
13111 pc->tline = pc->linenr;
13112
13113 pc->tt = bestIdx;
13114 return JIM_OK;
13115 }
13116
@@ -13608,17 +13786,23 @@
13608 }
13609
13610 #ifdef DEBUG_SHOW_EXPR_TOKENS
13611 {
13612 int i;
13613 printf("==== Expr Tokens ====\n");
13614 for (i = 0; i < tokenlist.count; i++) {
13615 printf("[%2d]@%d %s '%.*s'\n", i, tokenlist.list[i].line, jim_tt_name(tokenlist.list[i].type),
13616 tokenlist.list[i].len, tokenlist.list[i].token);
13617 }
13618 }
13619 #endif
 
 
 
 
 
 
13620
13621
13622 expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj);
13623
13624
@@ -13665,10 +13849,24 @@
13665 return NULL;
13666 }
13667 }
13668 return (ExprByteCode *) Jim_GetIntRepPtr(objPtr);
13669 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13670
13671 #define JIM_EE_STATICSTACK_LEN 10
13672
13673 int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr)
13674 {
@@ -13688,102 +13886,69 @@
13688 Jim_Obj *objPtr;
13689
13690
13691 switch (expr->len) {
13692 case 1:
13693 if (expr->token[0].type == JIM_TT_EXPR_INT) {
13694 *exprResultPtrPtr = expr->token[0].objPtr;
13695 Jim_IncrRefCount(*exprResultPtrPtr);
13696 return JIM_OK;
13697 }
13698 if (expr->token[0].type == JIM_TT_VAR) {
13699 objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_ERRMSG);
13700 if (objPtr) {
13701 *exprResultPtrPtr = objPtr;
13702 Jim_IncrRefCount(*exprResultPtrPtr);
13703 return JIM_OK;
13704 }
13705 }
13706 break;
13707
13708 case 2:
13709 if (expr->token[1].type == JIM_EXPROP_NOT && expr->token[0].type == JIM_TT_VAR) {
13710 jim_wide wideValue;
13711
13712 objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE);
13713 if (objPtr && JimIsWide(objPtr)
13714 && Jim_GetWide(interp, objPtr, &wideValue) == JIM_OK) {
13715 *exprResultPtrPtr = wideValue ? interp->falseObj : interp->trueObj;
13716 Jim_IncrRefCount(*exprResultPtrPtr);
13717 return JIM_OK;
13718 }
13719 }
13720 break;
13721
13722 case 3:
13723 if (expr->token[0].type == JIM_TT_VAR && (expr->token[1].type == JIM_TT_EXPR_INT
13724 || expr->token[1].type == JIM_TT_VAR)) {
13725 switch (expr->token[2].type) {
13726 case JIM_EXPROP_LT:
13727 case JIM_EXPROP_LTE:
13728 case JIM_EXPROP_GT:
13729 case JIM_EXPROP_GTE:
13730 case JIM_EXPROP_NUMEQ:
13731 case JIM_EXPROP_NUMNE:{
13732
13733 jim_wide wideValueA;
13734 jim_wide wideValueB;
13735
13736 objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE);
13737 if (objPtr && JimIsWide(objPtr)
13738 && Jim_GetWide(interp, objPtr, &wideValueA) == JIM_OK) {
13739 if (expr->token[1].type == JIM_TT_VAR) {
13740 objPtr =
13741 Jim_GetVariable(interp, expr->token[1].objPtr,
13742 JIM_NONE);
13743 }
13744 else {
13745 objPtr = expr->token[1].objPtr;
13746 }
13747 if (objPtr && JimIsWide(objPtr)
13748 && Jim_GetWide(interp, objPtr, &wideValueB) == JIM_OK) {
13749 int cmpRes;
13750
13751 switch (expr->token[2].type) {
13752 case JIM_EXPROP_LT:
13753 cmpRes = wideValueA < wideValueB;
13754 break;
13755 case JIM_EXPROP_LTE:
13756 cmpRes = wideValueA <= wideValueB;
13757 break;
13758 case JIM_EXPROP_GT:
13759 cmpRes = wideValueA > wideValueB;
13760 break;
13761 case JIM_EXPROP_GTE:
13762 cmpRes = wideValueA >= wideValueB;
13763 break;
13764 case JIM_EXPROP_NUMEQ:
13765 cmpRes = wideValueA == wideValueB;
13766 break;
13767 case JIM_EXPROP_NUMNE:
13768 cmpRes = wideValueA != wideValueB;
13769 break;
13770 default:
13771 cmpRes = 0;
13772 }
13773 *exprResultPtrPtr =
13774 cmpRes ? interp->trueObj : interp->falseObj;
13775 Jim_IncrRefCount(*exprResultPtrPtr);
13776 return JIM_OK;
13777 }
13778 }
13779 }
13780 }
13781 }
13782 break;
13783 }
13784 }
13785 #endif
13786
13787 expr->inUse++;
13788
13789
@@ -13952,16 +14117,13 @@
13952 memcpy(newVec, srcPtr->internalRep.ptr, size);
13953 dupPtr->internalRep.ptr = newVec;
13954 dupPtr->typePtr = &scanFmtStringObjType;
13955 }
13956
13957 void UpdateStringOfScanFmt(Jim_Obj *objPtr)
13958 {
13959 char *bytes = ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep;
13960
13961 objPtr->bytes = Jim_StrDup(bytes);
13962 objPtr->length = strlen(bytes);
13963 }
13964
13965
13966 static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
13967 {
@@ -14171,11 +14333,10 @@
14171 Jim_Obj *tmpObj = NULL;
14172
14173
14174 *valObjPtr = 0;
14175 if (descr->prefix) {
14176
14177 for (i = 0; pos < strLen && descr->prefix[i]; ++i) {
14178
14179 if (isspace(UCHAR(descr->prefix[i])))
14180 while (pos < strLen && isspace(UCHAR(str[pos])))
14181 ++pos;
@@ -14512,34 +14673,55 @@
14512 }
14513
14514 static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
14515 {
14516 int retcode;
14517 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
14518
14519 if (cmdPtr == NULL) {
14520 return JimUnknown(interp, objc, objv);
 
 
 
14521 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14522 if (interp->evalDepth == interp->maxEvalDepth) {
14523 Jim_SetResultString(interp, "Infinite eval recursion", -1);
14524 return JIM_ERR;
 
14525 }
14526 interp->evalDepth++;
14527
14528
14529 JimIncrCmdRefCount(cmdPtr);
14530 Jim_SetEmptyResult(interp);
14531 if (cmdPtr->isproc) {
14532 retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
14533 }
14534 else {
14535 interp->cmdPrivData = cmdPtr->u.native.privData;
14536 retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
14537 }
14538 JimDecrCmdRefCount(interp, cmdPtr);
14539 interp->evalDepth--;
14540
 
 
 
14541 return retcode;
14542 }
14543
14544 int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
14545 {
@@ -14717,10 +14899,15 @@
14717 objPtr->typePtr = &interpolatedObjType;
14718 objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr;
14719 objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2];
14720 Jim_IncrRefCount(intv[2]);
14721 }
 
 
 
 
 
14722
14723 s = objPtr->bytes = Jim_Alloc(totlen + 1);
14724 objPtr->length = totlen;
14725 for (i = 0; i < tokens; i++) {
14726 if (intv[i]) {
@@ -14772,10 +14959,14 @@
14772 return JimEvalObjList(interp, scriptObjPtr);
14773 }
14774
14775 Jim_IncrRefCount(scriptObjPtr);
14776 script = Jim_GetScript(interp, scriptObjPtr);
 
 
 
 
14777
14778 Jim_SetEmptyResult(interp);
14779
14780 token = script->token;
14781
@@ -15046,26 +15237,20 @@
15046 retcode = Jim_EvalObj(interp, scriptObj);
15047 }
15048
15049
15050 interp->framePtr = interp->framePtr->parent;
15051 if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) {
15052 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE);
15053 }
15054 else {
15055 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT);
15056 }
15057
15058 return retcode;
15059 }
15060 #endif
15061
15062 static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv)
15063 {
15064 Jim_CallFrame *callFramePtr;
15065 int i, d, retcode, optargs;
15066 Jim_Stack *localCommands;
15067 ScriptObj *script;
15068
15069
15070 if (argc - 1 < cmd->u.proc.reqArity ||
15071 (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) {
@@ -15145,37 +15330,42 @@
15145
15146
15147 retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr);
15148
15149 badargset:
 
15150
15151
15152 localCommands = callFramePtr->localCommands;
15153 callFramePtr->localCommands = NULL;
15154
15155 interp->framePtr = interp->framePtr->parent;
15156 if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) {
15157 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE);
15158 }
15159 else {
15160 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT);
15161 }
15162
15163
15164 while (retcode == JIM_EVAL) {
15165 Jim_Obj *resultScriptObjPtr = Jim_GetResult(interp);
15166
15167 Jim_IncrRefCount(resultScriptObjPtr);
15168
15169 JimPanic((!Jim_IsList(resultScriptObjPtr), "tailcall (JIM_EVAL) returned non-list"));
15170
15171 retcode = JimEvalObjList(interp, resultScriptObjPtr);
15172 if (retcode == JIM_RETURN) {
15173 interp->returnLevel++;
15174 }
15175 Jim_DecrRefCount(interp, resultScriptObjPtr);
15176 }
 
 
 
 
 
 
 
 
15177
15178 if (retcode == JIM_RETURN) {
15179 if (--interp->returnLevel <= 0) {
15180 retcode = interp->returnCode;
15181 interp->returnCode = JIM_OK;
@@ -15187,13 +15377,10 @@
15187 Jim_DecrRefCount(interp, interp->errorProc);
15188 interp->errorProc = argv[0];
15189 Jim_IncrRefCount(interp->errorProc);
15190 }
15191
15192
15193 JimDeleteLocalProcs(interp, localCommands);
15194
15195 return retcode;
15196 }
15197
15198 int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script)
15199 {
@@ -15261,11 +15448,10 @@
15261 Jim_Obj *scriptObjPtr;
15262 Jim_Obj *prevScriptObj;
15263 struct stat sb;
15264 int retcode;
15265 int readlen;
15266 struct JimParseResult result;
15267
15268 if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) {
15269 Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno));
15270 return JIM_ERR;
15271 }
@@ -15288,31 +15474,13 @@
15288 scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen);
15289 JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1);
15290 Jim_IncrRefCount(scriptObjPtr);
15291
15292
15293 if (SetScriptFromAny(interp, scriptObjPtr, &result) == JIM_ERR) {
15294 const char *msg;
15295 char linebuf[20];
15296
15297 switch (result.missing) {
15298 case '[':
15299 msg = "unmatched \"[\"";
15300 break;
15301 case '{':
15302 msg = "missing close-brace";
15303 break;
15304 case '"':
15305 default:
15306 msg = "missing quote";
15307 break;
15308 }
15309
15310 snprintf(linebuf, sizeof(linebuf), "%d", result.line);
15311
15312 Jim_SetResultFormatted(interp, "%s in \"%s\" at line %s",
15313 msg, filename, linebuf);
15314 Jim_DecrRefCount(interp, scriptObjPtr);
15315 return JIM_ERR;
15316 }
15317
15318 prevScriptObj = interp->currentScriptObj;
@@ -15475,11 +15643,11 @@
15475 }
15476
15477 typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr,
15478 Jim_HashEntry *he, int type);
15479
15480 #define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL)
15481
15482 static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
15483 JimHashtableIteratorCallbackType *callback, int type)
15484 {
15485 Jim_HashEntry *he;
@@ -15510,11 +15678,11 @@
15510 #define JIM_CMDLIST_CHANNELS 2
15511
15512 static void JimCommandMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
15513 Jim_HashEntry *he, int type)
15514 {
15515 Jim_Cmd *cmdPtr = (Jim_Cmd *)he->u.val;
15516 Jim_Obj *objPtr;
15517
15518 if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) {
15519
15520 return;
@@ -15543,11 +15711,11 @@
15543 #define JIM_VARLIST_VALUES 0x1000
15544
15545 static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
15546 Jim_HashEntry *he, int type)
15547 {
15548 Jim_Var *varPtr = (Jim_Var *)he->u.val;
15549
15550 if (type != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) {
15551 Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1));
15552 if (type & JIM_VARLIST_VALUES) {
15553 Jim_ListAppendElement(interp, listObjPtr, varPtr->objPtr);
@@ -15865,11 +16033,11 @@
15865
15866 expr = JimGetExpression(interp, argv[2]);
15867 incrScript = Jim_GetScript(interp, argv[3]);
15868
15869
15870 if (incrScript->len != 3 || !expr || expr->len != 3) {
15871 goto evalstart;
15872 }
15873
15874 if (incrScript->token[1].type != JIM_TT_ESC ||
15875 expr->token[0].type != JIM_TT_VAR ||
@@ -16088,11 +16256,11 @@
16088 }
16089
16090
16091 static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap)
16092 {
16093 int result = JIM_ERR;
16094 int i, numargs;
16095 Jim_ListIter twoiters[2];
16096 Jim_ListIter *iters;
16097 Jim_Obj *script;
16098 Jim_Obj *resultObj;
@@ -16111,13 +16279,16 @@
16111 iters = Jim_Alloc(numargs * sizeof(*iters));
16112 }
16113 for (i = 0; i < numargs; i++) {
16114 JimListIterInit(&iters[i], argv[i + 1]);
16115 if (i % 2 == 0 && JimListIterDone(interp, &iters[i])) {
16116 Jim_SetResultString(interp, "foreach varlist is empty", -1);
16117 return JIM_ERR;
16118 }
 
 
 
 
16119 }
16120
16121 if (doMap) {
16122 resultObj = Jim_NewListObj(interp, NULL, 0);
16123 }
@@ -16430,12 +16601,12 @@
16430 {
16431 Jim_Obj *objPtr, *listObjPtr;
16432 int i;
16433 int idx;
16434
16435 if (argc < 3) {
16436 Jim_WrongNumArgs(interp, 1, argv, "list index ?...?");
16437 return JIM_ERR;
16438 }
16439 objPtr = argv[1];
16440 Jim_IncrRefCount(objPtr);
16441 for (i = 2; i < argc; i++) {
@@ -16547,14 +16718,13 @@
16547 Jim_IncrRefCount(commandObj);
16548 }
16549
16550 listlen = Jim_ListLength(interp, argv[0]);
16551 for (i = 0; i < listlen; i++) {
16552 Jim_Obj *objPtr;
16553 int eq = 0;
 
16554
16555 Jim_ListIndex(interp, argv[0], i, &objPtr, JIM_NONE);
16556 switch (opt_match) {
16557 case OPT_EXACT:
16558 eq = Jim_StringCompareObj(interp, argv[1], objPtr, opt_nocase) == 0;
16559 break;
16560
@@ -16744,29 +16914,27 @@
16744 if (argc < 3) {
16745 Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal");
16746 return JIM_ERR;
16747 }
16748 else if (argc == 3) {
 
16749 if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
16750 return JIM_ERR;
16751 Jim_SetResult(interp, argv[2]);
16752 return JIM_OK;
16753 }
16754 if (Jim_SetListIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1])
16755 == JIM_ERR)
16756 return JIM_ERR;
16757 return JIM_OK;
16758 }
16759
16760
16761 static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[])
16762 {
16763 static const char * const options[] = {
16764 "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-index", NULL
16765 };
16766 enum
16767 { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_INDEX };
16768 Jim_Obj *resObj;
16769 int i;
16770 int retCode;
16771
16772 struct lsort_info info;
@@ -16777,17 +16945,18 @@
16777 }
16778
16779 info.type = JIM_LSORT_ASCII;
16780 info.order = 1;
16781 info.indexed = 0;
 
16782 info.command = NULL;
16783 info.interp = interp;
16784
16785 for (i = 1; i < (argc - 1); i++) {
16786 int option;
16787
16788 if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG)
16789 != JIM_OK)
16790 return JIM_ERR;
16791 switch (option) {
16792 case OPT_ASCII:
16793 info.type = JIM_LSORT_ASCII;
@@ -16796,16 +16965,22 @@
16796 info.type = JIM_LSORT_NOCASE;
16797 break;
16798 case OPT_INTEGER:
16799 info.type = JIM_LSORT_INTEGER;
16800 break;
 
 
 
16801 case OPT_INCREASING:
16802 info.order = 1;
16803 break;
16804 case OPT_DECREASING:
16805 info.order = -1;
16806 break;
 
 
 
16807 case OPT_COMMAND:
16808 if (i >= (argc - 2)) {
16809 Jim_SetResultString(interp, "\"-command\" option must be followed by comparison command", -1);
16810 return JIM_ERR;
16811 }
@@ -16915,20 +17090,20 @@
16915 static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
16916 {
16917 if (argc >= 2) {
16918 int retcode;
16919 Jim_CallFrame *savedCallFrame, *targetCallFrame;
16920 Jim_Obj *objPtr;
16921 const char *str;
16922
16923
16924 savedCallFrame = interp->framePtr;
16925
16926
16927 str = Jim_String(argv[1]);
16928 if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') {
16929 targetCallFrame =Jim_GetCallFrameByLevel(interp, argv[1]);
16930 argc--;
16931 argv++;
16932 }
16933 else {
16934 targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL);
@@ -16935,25 +17110,25 @@
16935 }
16936 if (targetCallFrame == NULL) {
16937 return JIM_ERR;
16938 }
16939 if (argc < 2) {
16940 argv--;
16941 Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
16942 return JIM_ERR;
16943 }
16944
16945 interp->framePtr = targetCallFrame;
 
 
 
16946 if (argc == 2) {
16947 retcode = Jim_EvalObj(interp, argv[1]);
16948 }
16949 else {
16950 objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1);
16951 Jim_IncrRefCount(objPtr);
16952 retcode = Jim_EvalObj(interp, objPtr);
16953 Jim_DecrRefCount(interp, objPtr);
16954 }
 
16955 interp->framePtr = savedCallFrame;
16956 return retcode;
16957 }
16958 else {
16959 Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
@@ -17064,12 +17239,39 @@
17064 }
17065
17066
17067 static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17068 {
17069 Jim_SetResult(interp, Jim_NewListObj(interp, argv + 1, argc - 1));
17070 return JIM_EVAL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17071 }
17072
17073 static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17074 {
17075 Jim_Obj *cmdList;
@@ -17354,11 +17556,11 @@
17354 for (i = 0; i < numMaps; i += 2) {
17355 Jim_Obj *objPtr;
17356 const char *k;
17357 int kl;
17358
17359 Jim_ListIndex(interp, mapListObjPtr, i, &objPtr, JIM_NONE);
17360 k = Jim_String(objPtr);
17361 kl = Jim_Utf8Length(interp, objPtr);
17362
17363 if (strLen >= kl && kl) {
17364 int rc;
@@ -17366,12 +17568,11 @@
17366 if (rc == 0) {
17367 if (noMatchStart) {
17368 Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart);
17369 noMatchStart = NULL;
17370 }
17371 Jim_ListIndex(interp, mapListObjPtr, i + 1, &objPtr, JIM_NONE);
17372 Jim_AppendObj(interp, resultObjPtr, objPtr);
17373 str += utf8_index(str, kl);
17374 strLen -= kl;
17375 break;
17376 }
17377 }
@@ -17851,15 +18052,17 @@
17851
17852 exitCode = JIM_SIGNAL;
17853 }
17854 else {
17855 exitCode = Jim_EvalObj(interp, argv[0]);
 
 
17856 }
17857 interp->signal_level -= sig;
17858
17859
17860 if (exitCode >= 0 && exitCode < max_ignore_code && ((1 << exitCode) & ignore_mask)) {
17861
17862 return exitCode;
17863 }
17864
17865 if (sig && exitCode == JIM_SIGNAL) {
@@ -18009,11 +18212,11 @@
18009 listObjPtr = Jim_NewListObj(interp, NULL, 0);
18010
18011 JimInitHashTableIterator(&interp->references, &htiter);
18012 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18013 char buf[JIM_REFERENCE_SPACE + 1];
18014 Jim_Reference *refPtr = he->u.val;
18015 const unsigned long *refId = he->key;
18016
18017 JimFormatReference(buf, refPtr, *refId);
18018 Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1));
18019 }
@@ -18043,11 +18246,11 @@
18043
18044 static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type)
18045 {
18046 Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
18047 if (type & JIM_DICTMATCH_VALUES) {
18048 Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->u.val);
18049 }
18050 }
18051
18052 static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
18053 JimDictMatchCallbackType *callback, int type)
@@ -18092,21 +18295,65 @@
18092 return -1;
18093 }
18094 return ((Jim_HashTable *)objPtr->internalRep.ptr)->used;
18095 }
18096
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18097
18098 static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18099 {
18100 Jim_Obj *objPtr;
18101 int option;
18102 static const char * const options[] = {
18103 "create", "get", "set", "unset", "exists", "keys", "merge", "size", "with", NULL
 
 
18104 };
18105 enum
18106 {
18107 OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXIST, OPT_KEYS, OPT_MERGE, OPT_SIZE, OPT_WITH,
 
 
18108 };
18109
18110 if (argc < 2) {
18111 Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?");
18112 return JIM_ERR;
@@ -18117,11 +18364,11 @@
18117 }
18118
18119 switch (option) {
18120 case OPT_GET:
18121 if (argc < 3) {
18122 Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?");
18123 return JIM_ERR;
18124 }
18125 if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr,
18126 JIM_ERRMSG) != JIM_OK) {
18127 return JIM_ERR;
@@ -18134,82 +18381,87 @@
18134 Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...? value");
18135 return JIM_ERR;
18136 }
18137 return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG);
18138
18139 case OPT_EXIST:
18140 if (argc < 3) {
18141 Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?");
18142 return JIM_ERR;
18143 }
18144 Jim_SetResultBool(interp, Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3,
18145 &objPtr, JIM_ERRMSG) == JIM_OK);
18146 return JIM_OK;
 
 
 
 
 
18147
18148 case OPT_UNSET:
18149 if (argc < 4) {
18150 Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?");
18151 return JIM_ERR;
18152 }
18153 return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_NONE);
 
 
 
18154
18155 case OPT_KEYS:
18156 if (argc != 3 && argc != 4) {
18157 Jim_WrongNumArgs(interp, 2, argv, "dictVar ?pattern?");
18158 return JIM_ERR;
18159 }
18160 return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL);
18161
18162 case OPT_SIZE: {
18163 int size;
18164
18165 if (argc != 3) {
18166 Jim_WrongNumArgs(interp, 2, argv, "dictVar");
18167 return JIM_ERR;
18168 }
18169
18170 size = Jim_DictSize(interp, argv[2]);
18171 if (size < 0) {
18172 return JIM_ERR;
18173 }
18174 Jim_SetResultInt(interp, size);
18175 return JIM_OK;
18176 }
18177
18178 case OPT_MERGE:
18179 if (argc == 2) {
18180 return JIM_OK;
18181 }
18182 else if (SetDictFromAny(interp, argv[2]) != JIM_OK) {
18183 return JIM_ERR;
18184 }
18185 else {
18186 return Jim_EvalPrefix(interp, "dict merge", argc - 2, argv + 2);
18187 }
18188
18189 case OPT_WITH:
18190 if (argc < 4) {
18191 Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script");
18192 return JIM_ERR;
18193 }
18194 else if (Jim_GetVariable(interp, argv[2], JIM_ERRMSG) == NULL) {
18195 return JIM_ERR;
18196 }
18197 else {
18198 return Jim_EvalPrefix(interp, "dict with", argc - 2, argv + 2);
18199 }
18200
18201 case OPT_CREATE:
18202 if (argc % 2) {
18203 Jim_WrongNumArgs(interp, 2, argv, "?key value ...?");
18204 return JIM_ERR;
18205 }
18206 objPtr = Jim_NewDictObj(interp, argv + 2, argc - 2);
18207 Jim_SetResult(interp, objPtr);
18208 return JIM_OK;
 
 
 
 
 
 
 
18209 }
18210 return JIM_ERR;
 
18211 }
18212
18213
18214 static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18215 {
@@ -18267,11 +18519,11 @@
18267 };
18268 enum
18269 { INFO_BODY, INFO_STATICS, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL,
18270 INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS,
18271 INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE,
18272 INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS
18273 };
18274
18275 #ifdef jim_ext_namespace
18276 int nons = 0;
18277
@@ -19047,11 +19299,11 @@
19047 }
19048 }
19049
19050 static const struct {
19051 const char *name;
19052 Jim_CmdProc cmdProc;
19053 } Jim_CoreCommandsTable[] = {
19054 {"alias", Jim_AliasCoreCommand},
19055 {"set", Jim_SetCoreCommand},
19056 {"unset", Jim_UnsetCoreCommand},
19057 {"puts", Jim_PutsCoreCommand},
@@ -19279,10 +19531,12 @@
19279 }
19280
19281 len += extra;
19282 buf = Jim_Alloc(len + 1);
19283 len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]);
 
 
19284
19285 Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len));
19286 }
19287
19288
@@ -19530,23 +19784,22 @@
19530
19531 #include <ctype.h>
19532 #include <string.h>
19533
19534
19535 #define JIM_UTF_MAX 3
19536 #define JIM_INTEGER_SPACE 24
19537 #define MAX_FLOAT_WIDTH 320
19538
19539 Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv)
19540 {
19541 const char *span, *format, *formatEnd, *msg;
19542 int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0;
19543 static const char * const mixedXPG =
19544 "cannot mix \"%\" and \"%n$\" conversion specifiers";
19545 static const char * const badIndex[2] = {
19546 "not enough arguments for all format specifiers",
19547 "\"%n$\" argument index out of range"
19548 };
19549 int formatLen;
19550 Jim_Obj *resultPtr;
19551
19552 char *num_buffer = NULL;
@@ -19555,319 +19808,349 @@
19555 span = format = Jim_GetString(fmtObjPtr, &formatLen);
19556 formatEnd = format + formatLen;
19557 resultPtr = Jim_NewEmptyStringObj(interp);
19558
19559 while (format != formatEnd) {
19560 char *end;
19561 int gotMinus, sawFlag;
19562 int gotPrecision, useShort;
19563 long width, precision;
19564 int newXpg;
19565 int ch;
19566 int step;
19567 int doubleType;
19568 char pad = ' ';
19569 char spec[2*JIM_INTEGER_SPACE + 12];
19570 char *p;
19571
19572 int formatted_chars;
19573 int formatted_bytes;
19574 const char *formatted_buf;
19575
19576 step = utf8_tounicode(format, &ch);
19577 format += step;
19578 if (ch != '%') {
19579 numBytes += step;
19580 continue;
19581 }
19582 if (numBytes) {
19583 Jim_AppendString(interp, resultPtr, span, numBytes);
19584 numBytes = 0;
19585 }
19586
19587
19588 step = utf8_tounicode(format, &ch);
19589 if (ch == '%') {
19590 span = format;
19591 numBytes = step;
19592 format += step;
19593 continue;
19594 }
19595
19596
19597 newXpg = 0;
19598 if (isdigit(ch)) {
19599 int position = strtoul(format, &end, 10);
19600 if (*end == '$') {
19601 newXpg = 1;
19602 objIndex = position - 1;
19603 format = end + 1;
19604 step = utf8_tounicode(format, &ch);
19605 }
19606 }
19607 if (newXpg) {
19608 if (gotSequential) {
19609 msg = mixedXPG;
19610 goto errorMsg;
19611 }
19612 gotXpg = 1;
19613 } else {
19614 if (gotXpg) {
19615 msg = mixedXPG;
19616 goto errorMsg;
19617 }
19618 gotSequential = 1;
19619 }
19620 if ((objIndex < 0) || (objIndex >= objc)) {
19621 msg = badIndex[gotXpg];
19622 goto errorMsg;
19623 }
19624
19625 p = spec;
19626 *p++ = '%';
19627
19628 gotMinus = 0;
19629 sawFlag = 1;
19630 do {
19631 switch (ch) {
19632 case '-':
19633 gotMinus = 1;
19634 break;
19635 case '0':
19636 pad = ch;
19637 break;
19638 case ' ':
19639 case '+':
19640 case '#':
19641 break;
19642 default:
19643 sawFlag = 0;
19644 continue;
19645 }
19646 *p++ = ch;
19647 format += step;
19648 step = utf8_tounicode(format, &ch);
19649 } while (sawFlag);
19650
19651
19652 width = 0;
19653 if (isdigit(ch)) {
19654 width = strtoul(format, &end, 10);
19655 format = end;
19656 step = utf8_tounicode(format, &ch);
19657 } else if (ch == '*') {
19658 if (objIndex >= objc - 1) {
19659 msg = badIndex[gotXpg];
19660 goto errorMsg;
19661 }
19662 if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) {
19663 goto error;
19664 }
19665 if (width < 0) {
19666 width = -width;
19667 if (!gotMinus) {
19668 *p++ = '-';
19669 gotMinus = 1;
19670 }
19671 }
19672 objIndex++;
19673 format += step;
19674 step = utf8_tounicode(format, &ch);
19675 }
19676
19677
19678 gotPrecision = precision = 0;
19679 if (ch == '.') {
19680 gotPrecision = 1;
19681 format += step;
19682 step = utf8_tounicode(format, &ch);
19683 }
19684 if (isdigit(ch)) {
19685 precision = strtoul(format, &end, 10);
19686 format = end;
19687 step = utf8_tounicode(format, &ch);
19688 } else if (ch == '*') {
19689 if (objIndex >= objc - 1) {
19690 msg = badIndex[gotXpg];
19691 goto errorMsg;
19692 }
19693 if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) {
19694 goto error;
19695 }
19696
19697
19698 if (precision < 0) {
19699 precision = 0;
19700 }
19701 objIndex++;
19702 format += step;
19703 step = utf8_tounicode(format, &ch);
19704 }
19705
19706
19707 useShort = 0;
19708 if (ch == 'h') {
19709 useShort = 1;
19710 format += step;
19711 step = utf8_tounicode(format, &ch);
19712 } else if (ch == 'l') {
19713
19714 format += step;
19715 step = utf8_tounicode(format, &ch);
19716 if (ch == 'l') {
19717 format += step;
19718 step = utf8_tounicode(format, &ch);
19719 }
19720 }
19721
19722 format += step;
19723 span = format;
19724
19725
19726 if (ch == 'i') {
19727 ch = 'd';
19728 }
19729
19730 doubleType = 0;
19731
19732 switch (ch) {
19733 case '\0':
19734 msg = "format string ended in middle of field specifier";
19735 goto errorMsg;
19736 case 's': {
19737 formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
19738 formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
19739 if (gotPrecision && (precision < formatted_chars)) {
19740
19741 formatted_chars = precision;
19742 formatted_bytes = utf8_index(formatted_buf, precision);
19743 }
19744 break;
19745 }
19746 case 'c': {
19747 jim_wide code;
19748
19749 if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
19750 goto error;
19751 }
19752
19753 formatted_bytes = utf8_fromunicode(spec, code);
19754 formatted_buf = spec;
19755 formatted_chars = 1;
19756 break;
19757 }
19758
19759 case 'e':
19760 case 'E':
19761 case 'f':
19762 case 'g':
19763 case 'G':
19764 doubleType = 1;
19765
19766 case 'd':
19767 case 'u':
19768 case 'o':
19769 case 'x':
19770 case 'X': {
19771 jim_wide w;
19772 double d;
19773 int length;
19774
19775
19776 if (width) {
19777 p += sprintf(p, "%ld", width);
19778 }
19779 if (gotPrecision) {
19780 p += sprintf(p, ".%ld", precision);
19781 }
19782
19783
19784 if (doubleType) {
19785 if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
19786 goto error;
19787 }
19788 length = MAX_FLOAT_WIDTH;
19789 }
19790 else {
19791 if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) {
19792 goto error;
19793 }
19794 length = JIM_INTEGER_SPACE;
19795 if (useShort) {
19796 *p++ = 'h';
19797 if (ch == 'd') {
19798 w = (short)w;
19799 }
19800 else {
19801 w = (unsigned short)w;
19802 }
19803 }
19804 else {
19805 *p++ = 'l';
19806 #ifdef HAVE_LONG_LONG
19807 if (sizeof(long long) == sizeof(jim_wide)) {
19808 *p++ = 'l';
19809 }
19810 #endif
19811 }
19812 }
19813
19814 *p++ = (char) ch;
19815 *p = '\0';
19816
19817
19818 if (width > length) {
19819 length = width;
19820 }
19821 if (gotPrecision) {
19822 length += precision;
19823 }
19824
19825
19826 if (num_buffer_size < length + 1) {
19827 num_buffer_size = length + 1;
19828 num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
19829 }
19830
19831 if (doubleType) {
19832 snprintf(num_buffer, length + 1, spec, d);
19833 }
19834 else {
19835 formatted_bytes = snprintf(num_buffer, length + 1, spec, w);
19836 }
19837 formatted_chars = formatted_bytes = strlen(num_buffer);
19838 formatted_buf = num_buffer;
19839 break;
19840 }
19841
19842 default: {
19843
19844 spec[0] = ch;
19845 spec[1] = '\0';
19846 Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
19847 goto error;
19848 }
19849 }
19850
19851 if (!gotMinus) {
19852 while (formatted_chars < width) {
19853 Jim_AppendString(interp, resultPtr, &pad, 1);
19854 formatted_chars++;
19855 }
19856 }
19857
19858 Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes);
19859
19860 while (formatted_chars < width) {
19861 Jim_AppendString(interp, resultPtr, &pad, 1);
19862 formatted_chars++;
19863 }
19864
19865 objIndex += gotSequential;
19866 }
19867 if (numBytes) {
19868 Jim_AppendString(interp, resultPtr, span, numBytes);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19869 }
19870
19871 Jim_Free(num_buffer);
19872 return resultPtr;
19873
@@ -19876,21 +20159,22 @@
19876 error:
19877 Jim_FreeNewObj(interp, resultPtr);
19878 Jim_Free(num_buffer);
19879 return NULL;
19880 }
 
 
 
19881 #include <stdio.h>
19882 #include <ctype.h>
19883 #include <stdlib.h>
19884 #include <string.h>
19885
19886
19887 #if !defined(HAVE_REGCOMP) || defined(JIM_REGEXP)
19888
19889
19890
19891 #define REG_MAX_PAREN 100
 
19892
19893
19894 #define END 0
19895 #define BOL 1
19896 #define EOL 2
@@ -19899,23 +20183,27 @@
19899 #define ANYBUT 5
19900 #define BRANCH 6
19901 #define BACK 7
19902 #define EXACTLY 8
19903 #define NOTHING 9
19904 #define REP 10
19905 #define REPMIN 11
19906 #define REPX 12
19907 #define REPXMIN 13
19908
19909 #define WORDA 15
19910 #define WORDZ 16
19911 #define OPENNC 19
19912 #define OPEN 20
 
19913
19914 #define CLOSE (OPEN+REG_MAX_PAREN+1)
 
 
 
 
19915 #define CLOSE_END (CLOSE+REG_MAX_PAREN)
19916 #define CLOSENC (CLOSE-1)
19917
19918 #define REG_MAGIC 0xFADED00D
19919
19920
19921 #define OP(preg, p) (preg->program[p])
@@ -19925,15 +20213,15 @@
19925
19926
19927
19928 #define FAIL(R,M) { (R)->err = (M); return (M); }
19929 #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{')
19930 #define META "^$.[()|?{+*"
19931
19932 #define HASWIDTH 01
19933 #define SIMPLE 02
19934 #define SPSTART 04
19935 #define WORST 0
19936
19937 #define MAX_REP_COUNT 1000000
19938
19939 static int reg(regex_t *preg, int paren , int *flagp );
@@ -19942,13 +20230,13 @@
19942 static int regatom(regex_t *preg, int *flagp );
19943 static int regnode(regex_t *preg, int op );
19944 static int regnext(regex_t *preg, int p );
19945 static void regc(regex_t *preg, int b );
19946 static int reginsert(regex_t *preg, int op, int size, int opnd );
19947 static void regtail_(regex_t *preg, int p, int val, int line );
19948 static void regoptail(regex_t *preg, int p, int val );
19949 #define regtail(PREG, P, VAL) regtail_(PREG, P, VAL, __LINE__)
19950
19951 static int reg_range_find(const int *string, int c);
19952 static const char *str_find(const char *string, int c, int nocase);
19953 static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase);
19954
@@ -19985,13 +20273,10 @@
19985 FAIL(preg, REG_ERR_NULL_ARGUMENT);
19986
19987
19988 preg->cflags = cflags;
19989 preg->regparse = exp;
19990
19991 preg->program = NULL;
19992 preg->proglen = 0;
19993
19994
19995 preg->proglen = (strlen(exp) + 1) * 5;
19996 preg->program = malloc(preg->proglen * sizeof(int));
19997 if (preg->program == NULL)
@@ -20152,11 +20437,10 @@
20152 {
20153 int ret;
20154 char op;
20155 int next;
20156 int flags;
20157 int chain = 0;
20158 int min;
20159 int max;
20160
20161 ret = regatom(preg, &flags);
20162 if (ret == 0)
@@ -20235,11 +20519,11 @@
20235 if (ISMULT(*preg->regparse)) {
20236 preg->err = REG_ERR_NESTED_COUNT;
20237 return 0;
20238 }
20239
20240 return chain ? chain : ret;
20241 }
20242
20243 static void reg_addrange(regex_t *preg, int lower, int upper)
20244 {
20245 if (lower > upper) {
@@ -20329,10 +20613,11 @@
20329 break;
20330 case 'U':
20331 if ((n = parse_hex(s, 8, ch)) > 0) {
20332 s += n;
20333 }
 
20334 case 'x':
20335 if ((n = parse_hex(s, 2, ch)) > 0) {
20336 s += n;
20337 }
20338 break;
@@ -20577,10 +20862,11 @@
20577
20578 static int regnode(regex_t *preg, int op)
20579 {
20580 reg_grow(preg, 2);
20581
 
20582 preg->program[preg->p++] = op;
20583 preg->program[preg->p++] = 0;
20584
20585
20586 return preg->p - 2;
@@ -20606,11 +20892,11 @@
20606 preg->p += size;
20607
20608 return opnd + size;
20609 }
20610
20611 static void regtail_(regex_t *preg, int p, int val, int line )
20612 {
20613 int scan;
20614 int temp;
20615 int offset;
20616
@@ -20669,36 +20955,16 @@
20669 preg->pmatch = pmatch;
20670 preg->nmatch = nmatch;
20671 preg->start = string;
20672
20673
20674 for (scan = OPERAND(1); scan != 0; ) {
20675 switch (OP(preg, scan)) {
20676 case REP:
20677 case REPMIN:
20678 case REPX:
20679 case REPXMIN:
20680 preg->program[scan + 4] = 0;
20681 scan += 5;
20682 break;
20683
20684 case ANYOF:
20685 case ANYBUT:
20686 case EXACTLY:
20687 scan += 2;
20688 while (preg->program[scan++]) {
20689 }
20690 break;
20691
20692 case END:
20693 scan = 0;
20694 break;
20695
20696 default:
20697 scan += 2;
20698 break;
20699 }
20700 }
20701
20702
20703 if (preg->regmust != 0) {
20704 s = string;
@@ -20950,10 +21216,11 @@
20950
20951 static int regmatch(regex_t *preg, int prog)
20952 {
20953 int scan;
20954 int next;
 
20955
20956 scan = prog;
20957
20958 #ifdef DEBUG
20959 if (scan != 0 && regnarrate)
@@ -21038,27 +21305,24 @@
21038 break;
21039 case NOTHING:
21040 break;
21041 case BACK:
21042 break;
21043 case BRANCH: {
21044 const char *save;
21045
21046 if (OP(preg, next) != BRANCH)
21047 next = OPERAND(scan);
21048 else {
21049 do {
21050 save = preg->reginput;
21051 if (regmatch(preg, OPERAND(scan))) {
21052 return(1);
21053 }
21054 preg->reginput = save;
21055 scan = regnext(preg, scan);
21056 } while (scan != 0 && OP(preg, scan) == BRANCH);
21057 return(0);
21058
21059 }
21060 }
21061 break;
21062 case REP:
21063 case REPMIN:
21064 return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN);
@@ -21066,43 +21330,35 @@
21066 case REPX:
21067 case REPXMIN:
21068 return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN);
21069
21070 case END:
21071 return(1);
21072 break;
21073
21074 case OPENNC:
21075 case CLOSENC:
21076 if (regmatch(preg, next)) {
21077 return 1;
21078 }
21079 return 0;
21080
21081 default:
21082 if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) {
21083 const char *save;
21084
21085 save = preg->reginput;
21086
21087 if (regmatch(preg, next)) {
21088 int no;
21089 if (OP(preg, scan) < CLOSE) {
21090 no = OP(preg, scan) - OPEN;
21091 if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) {
21092 preg->pmatch[no].rm_so = save - preg->start;
21093 }
21094 }
21095 else {
21096 no = OP(preg, scan) - CLOSE;
21097 if (no < preg->nmatch && preg->pmatch[no].rm_eo == -1) {
21098 preg->pmatch[no].rm_eo = save - preg->start;
21099 }
21100 }
21101 return(1);
21102 } else
21103 return(0);
21104 }
21105 return REG_ERR_INTERNAL;
21106 }
21107
21108 scan = next;
@@ -21181,10 +21437,32 @@
21181 if (OP(preg, p) == BACK)
21182 return(p-offset);
21183 else
21184 return(p+offset);
21185 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21186
21187
21188 size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
21189 {
21190 static const char *error_strings[] = {
@@ -21359,19 +21637,24 @@
21359 char *Jim_HistoryGetline(const char *prompt)
21360 {
21361 #ifdef USE_LINENOISE
21362 return linenoise(prompt);
21363 #else
 
21364 char *line = malloc(MAX_LINE_LEN);
21365
21366 fputs(prompt, stdout);
21367 fflush(stdout);
21368
21369 if (fgets(line, MAX_LINE_LEN, stdin) == NULL) {
21370 free(line);
21371 return NULL;
21372 }
 
 
 
 
21373 return line;
21374 #endif
21375 }
21376
21377 void Jim_HistoryLoad(const char *filename)
@@ -21422,11 +21705,11 @@
21422 snprintf(history_file, history_len, "%s/.jim_history", home);
21423 Jim_HistoryLoad(history_file);
21424 }
21425 #endif
21426
21427 printf("Welcome to Jim version %d.%d" JIM_NL,
21428 JIM_VERSION / 100, JIM_VERSION % 100);
21429 Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1");
21430
21431 while (1) {
21432 Jim_Obj *scriptObjPtr;
@@ -21534,10 +21817,16 @@
21534 }
21535
21536 Jim_SetVariableStr(interp, "argv", listObj);
21537 Jim_SetVariableStr(interp, "argc", Jim_NewIntObj(interp, argc));
21538 }
 
 
 
 
 
 
21539
21540 int main(int argc, char *const argv[])
21541 {
21542 int retcode;
21543 Jim_Interp *interp;
@@ -21551,22 +21840,20 @@
21551 interp = Jim_CreateInterp();
21552 Jim_RegisterCoreCommands(interp);
21553
21554
21555 if (Jim_InitStaticExtensions(interp) != JIM_OK) {
21556 Jim_MakeErrorMessage(interp);
21557 fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21558 }
21559
21560 Jim_SetVariableStrWithStr(interp, "jim_argv0", argv[0]);
21561 Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0");
21562 retcode = Jim_initjimshInit(interp);
21563
21564 if (argc == 1) {
21565 if (retcode == JIM_ERR) {
21566 Jim_MakeErrorMessage(interp);
21567 fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21568 }
21569 if (retcode != JIM_EXIT) {
21570 JimSetArgv(interp, 0, NULL);
21571 retcode = Jim_InteractivePrompt(interp);
21572 }
@@ -21583,12 +21870,11 @@
21583 Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1));
21584 JimSetArgv(interp, argc - 2, argv + 2);
21585 retcode = Jim_EvalFile(interp, argv[1]);
21586 }
21587 if (retcode == JIM_ERR) {
21588 Jim_MakeErrorMessage(interp);
21589 fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21590 }
21591 }
21592 if (retcode == JIM_EXIT) {
21593 retcode = Jim_GetExitCode(interp);
21594 }
21595
--- autosetup/jimsh0.c
+++ autosetup/jimsh0.c
@@ -1,6 +1,6 @@
1 /* This is single source file, bootstrap version of Jim Tcl. See http://jim.tcl.tk/ */
2 #define _GNU_SOURCE
3 #define JIM_TCL_COMPAT
4 #define JIM_REFERENCES
5 #define JIM_ANSIC
6 #define JIM_REGEXP
@@ -47,10 +47,14 @@
47 #define JIM_VERSION 75
48 #ifndef JIM_WIN32COMPAT_H
49 #define JIM_WIN32COMPAT_H
50
51
52
53 #ifdef __cplusplus
54 extern "C" {
55 #endif
56
57
58 #if defined(_WIN32) || defined(WIN32)
59
60 #define HAVE_DLOPEN
@@ -106,17 +110,31 @@
110 } DIR;
111
112 DIR *opendir(const char *name);
113 int closedir(DIR *dir);
114 struct dirent *readdir(DIR *dir);
115
116 #elif defined(__MINGW32__)
117
118 #define strtod __strtod
119
120 #endif
121
122 #endif
123
124 #ifdef __cplusplus
125 }
126 #endif
127
128 #endif
129 #ifndef UTF8_UTIL_H
130 #define UTF8_UTIL_H
131
132 #ifdef __cplusplus
133 extern "C" {
134 #endif
135
136
137
138 #define MAX_UTF8_LEN 4
139
140 int utf8_fromunicode(char *p, unsigned uc);
@@ -125,10 +143,11 @@
143 #include <ctype.h>
144
145
146 #define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B))
147 #define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
148 #define utf8_getchars(CP, C) (*(CP) = (C), 1)
149 #define utf8_upper(C) toupper(C)
150 #define utf8_title(C) toupper(C)
151 #define utf8_lower(C) tolower(C)
152 #define utf8_index(C, I) (I)
153 #define utf8_charlen(C) 1
@@ -135,10 +154,14 @@
154 #define utf8_prev_len(S, L) 1
155
156 #else
157
158 #endif
159
160 #ifdef __cplusplus
161 }
162 #endif
163
164 #endif
165
166 #ifndef __JIM__H
167 #define __JIM__H
@@ -199,44 +222,34 @@
222 #define JIM_EVAL 7
223
224 #define JIM_MAX_CALLFRAME_DEPTH 1000
225 #define JIM_MAX_EVAL_DEPTH 2000
226
227
228 #define JIM_PRIV_FLAG_SHIFT 20
229
230 #define JIM_NONE 0
231 #define JIM_ERRMSG 1
232 #define JIM_ENUM_ABBREV 2
233 #define JIM_UNSHARED 4
234 #define JIM_MUSTEXIST 8
235
236
237 #define JIM_SUBST_NOVAR 1
238 #define JIM_SUBST_NOCMD 2
239 #define JIM_SUBST_NOESC 4
240 #define JIM_SUBST_FLAG 128
241
 
 
 
 
 
 
242
243 #define JIM_CASESENS 0
244 #define JIM_NOCASE 1
245
246
247 #define JIM_PATH_LEN 1024
248
249
250 #define JIM_NOTUSED(V) ((void) V)
 
 
 
 
251
252 #define JIM_LIBPATH "auto_path"
253 #define JIM_INTERACTIVE "tcl_interactive"
254
255
@@ -266,21 +279,22 @@
279 } Jim_HashTableType;
280
281 typedef struct Jim_HashTable {
282 Jim_HashEntry **table;
283 const Jim_HashTableType *type;
284 void *privdata;
285 unsigned int size;
286 unsigned int sizemask;
287 unsigned int used;
288 unsigned int collisions;
289 unsigned int uniq;
290 } Jim_HashTable;
291
292 typedef struct Jim_HashTableIterator {
293 Jim_HashTable *ht;
 
294 Jim_HashEntry *entry, *nextEntry;
295 int index;
296 } Jim_HashTableIterator;
297
298
299 #define JIM_HT_INITIAL_SIZE 16
300
@@ -289,35 +303,35 @@
303 if ((ht)->type->valDestructor) \
304 (ht)->type->valDestructor((ht)->privdata, (entry)->u.val)
305
306 #define Jim_SetHashVal(ht, entry, _val_) do { \
307 if ((ht)->type->valDup) \
308 (entry)->u.val = (ht)->type->valDup((ht)->privdata, (_val_)); \
309 else \
310 (entry)->u.val = (_val_); \
311 } while(0)
312
313 #define Jim_FreeEntryKey(ht, entry) \
314 if ((ht)->type->keyDestructor) \
315 (ht)->type->keyDestructor((ht)->privdata, (entry)->key)
316
317 #define Jim_SetHashKey(ht, entry, _key_) do { \
318 if ((ht)->type->keyDup) \
319 (entry)->key = (ht)->type->keyDup((ht)->privdata, (_key_)); \
320 else \
321 (entry)->key = (void *)(_key_); \
322 } while(0)
323
324 #define Jim_CompareHashKeys(ht, key1, key2) \
325 (((ht)->type->keyCompare) ? \
326 (ht)->type->keyCompare((ht)->privdata, (key1), (key2)) : \
327 (key1) == (key2))
328
329 #define Jim_HashKey(ht, key) ((ht)->type->hashFunction(key) + (ht)->uniq)
330
331 #define Jim_GetHashEntryKey(he) ((he)->key)
332 #define Jim_GetHashEntryVal(he) ((he)->u.val)
333 #define Jim_GetHashTableCollisions(ht) ((ht)->collisions)
334 #define Jim_GetHashTableSize(ht) ((ht)->size)
335 #define Jim_GetHashTableUsed(ht) ((ht)->used)
336
337
@@ -341,19 +355,19 @@
355 void *ptr1;
356 void *ptr2;
357 } twoPtrValue;
358
359 struct {
 
360 struct Jim_Var *varPtr;
361 unsigned long callFrameId;
362 int global;
363 } varValue;
364
365 struct {
 
366 struct Jim_Obj *nsObj;
367 struct Jim_Cmd *cmdPtr;
368 unsigned long procEpoch;
369 } cmdValue;
370
371 struct {
372 struct Jim_Obj **ele;
373 int len;
@@ -379,12 +393,12 @@
393 struct Jim_Obj *varNameObjPtr;
394 struct Jim_Obj *indexObjPtr;
395 } dictSubstValue;
396
397 struct {
 
398 void *compre;
399 unsigned flags;
400 } regexpValue;
401 struct {
402 int line;
403 int argc;
404 } scriptLineValue;
@@ -453,21 +467,24 @@
467 struct Jim_CallFrame *next;
468 Jim_Obj *nsObj;
469 Jim_Obj *fileNameObj;
470 int line;
471 Jim_Stack *localCommands;
472 int tailcall;
473 struct Jim_Obj *tailcallObj;
474 struct Jim_Cmd *tailcallCmd;
475 } Jim_CallFrame;
476
477 typedef struct Jim_Var {
478 Jim_Obj *objPtr;
479 struct Jim_CallFrame *linkFramePtr;
480 } Jim_Var;
481
482
483 typedef int Jim_CmdProc(struct Jim_Interp *interp, int argc,
484 Jim_Obj *const *argv);
485 typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData);
486
487
488
489 typedef struct Jim_Cmd {
490 int inUse;
@@ -474,12 +491,12 @@
491 int isproc;
492 struct Jim_Cmd *prevCmd;
493 union {
494 struct {
495
496 Jim_CmdProc *cmdProc;
497 Jim_DelCmdProc *delProc;
498 void *privData;
499 } native;
500 struct {
501
502 Jim_Obj *argListObjPtr;
@@ -589,15 +606,11 @@
606 Jim_Obj *finalizerCmdNamePtr;
607 char tag[JIM_REFERENCE_TAGLEN+1];
608 } Jim_Reference;
609
610
 
611 #define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0)
 
 
 
612 #define Jim_FreeHashTableIterator(iter) Jim_Free(iter)
613
614 #define JIM_EXPORT
615
616
@@ -608,10 +621,11 @@
621 JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);
622
623
624 JIM_EXPORT char **Jim_GetEnviron(void);
625 JIM_EXPORT void Jim_SetEnviron(char **env);
626 JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *template);
627
628
629 JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);
630
631
@@ -739,13 +753,12 @@
753 JIM_EXPORT int Jim_SetVariableStrWithStr (Jim_Interp *interp,
754 const char *name, const char *val);
755 JIM_EXPORT int Jim_SetVariableLink (Jim_Interp *interp,
756 Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr,
757 Jim_CallFrame *targetCallFrame);
758 JIM_EXPORT Jim_Obj * Jim_MakeGlobalNamespaceName(Jim_Interp *interp,
759 Jim_Obj *nameObjPtr);
 
760 JIM_EXPORT Jim_Obj * Jim_GetVariable (Jim_Interp *interp,
761 Jim_Obj *nameObjPtr, int flags);
762 JIM_EXPORT Jim_Obj * Jim_GetGlobalVariable (Jim_Interp *interp,
763 Jim_Obj *nameObjPtr, int flags);
764 JIM_EXPORT Jim_Obj * Jim_GetVariableStr (Jim_Interp *interp,
@@ -804,10 +817,11 @@
817 JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
818 Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr);
819 JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj);
820 JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr);
821 JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr);
822 JIM_EXPORT int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr);
823
824
825 JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr,
826 int *intPtr);
827
@@ -869,19 +883,19 @@
883
884
885 JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp);
886 JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base);
887 JIM_EXPORT int Jim_IsBigEndian(void);
888
889 #define Jim_CheckSignal(i) ((i)->signal_level && (i)->sigmask)
890
891
892 JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName);
893 JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp);
894
895
896 JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command);
 
897
898
899 JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr);
900 JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr);
901
@@ -903,16 +917,16 @@
917 #define JIM_MODFLAG_HIDDEN 0x0001
918 #define JIM_MODFLAG_FULLARGV 0x0002
919
920
921
922 typedef int jim_subcmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
923
924 typedef struct {
925 const char *cmd;
926 const char *args;
927 jim_subcmd_function *function;
928 short minargs;
929 short maxargs;
930 unsigned short flags;
931 } jim_subcmd_type;
932
@@ -929,22 +943,16 @@
943
944 #endif
945 #ifndef JIMREGEXP_H
946 #define JIMREGEXP_H
947
948
949 #ifdef __cplusplus
950 extern "C" {
951 #endif
952
 
 
 
 
 
 
953 #include <stdlib.h>
 
954
955 typedef struct {
956 int rm_so;
957 int rm_eo;
958 } regmatch_t;
@@ -1013,10 +1021,12 @@
1021 int regcomp(regex_t *preg, const char *regex, int cflags);
1022 int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
1023 size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);
1024 void regfree(regex_t *preg);
1025
1026 #ifdef __cplusplus
1027 }
1028 #endif
1029
1030 #endif
1031 int Jim_bootstrapInit(Jim_Interp *interp)
1032 {
@@ -1079,10 +1089,15 @@
1089 "\n"
1090 "package require readdir\n"
1091 "\n"
1092 "\n"
1093 "proc glob.globdir {dir pattern} {\n"
1094 " if {[file exists $dir/$pattern]} {\n"
1095 "\n"
1096 " return $pattern\n"
1097 " }\n"
1098 "\n"
1099 " set result {}\n"
1100 " set files [readdir $dir]\n"
1101 " lappend files . ..\n"
1102 "\n"
1103 " foreach name $files {\n"
@@ -1261,10 +1276,12 @@
1276 {
1277 if (Jim_PackageProvide(interp, "stdlib", "1.0", JIM_ERRMSG))
1278 return JIM_ERR;
1279
1280 return Jim_EvalSource(interp, "stdlib.tcl", 1,
1281 "\n"
1282 "\n"
1283 "\n"
1284 "proc lambda {arglist args} {\n"
1285 " tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n"
1286 "}\n"
1287 "\n"
@@ -1290,46 +1307,48 @@
1307 "}\n"
1308 "\n"
1309 "\n"
1310 "\n"
1311 "\n"
1312 "proc stacktrace {{skip 0}} {\n"
1313 " set trace {}\n"
1314 " incr skip\n"
1315 " foreach level [range $skip [info level]] {\n"
1316 " lappend trace {*}[info frame -$level]\n"
1317 " }\n"
1318 " return $trace\n"
1319 "}\n"
1320 "\n"
1321 "\n"
1322 "proc stackdump {stacktrace} {\n"
1323 " set lines {}\n"
 
1324 " foreach {l f p} [lreverse $stacktrace] {\n"
1325 " set line {}\n"
 
 
 
1326 " if {$p ne \"\"} {\n"
1327 " append line \"in procedure '$p' \"\n"
1328 " if {$f ne \"\"} {\n"
1329 " append line \"called \"\n"
1330 " }\n"
1331 " }\n"
1332 " if {$f ne \"\"} {\n"
1333 " append line \"at file \\\"$f\\\", line $l\"\n"
1334 " }\n"
1335 " if {$line ne \"\"} {\n"
1336 " lappend lines $line\n"
1337 " }\n"
1338 " }\n"
1339 " join $lines \\n\n"
1340 "}\n"
1341 "\n"
1342 "\n"
1343 "\n"
1344 "proc errorInfo {msg {stacktrace \"\"}} {\n"
1345 " if {$stacktrace eq \"\"} {\n"
1346 "\n"
1347 " set stacktrace [info stacktrace]\n"
1348 "\n"
1349 " lappend stacktrace {*}[stacktrace 1]\n"
1350 " }\n"
1351 " lassign $stacktrace p f l\n"
1352 " if {$f ne \"\"} {\n"
1353 " set result \"Runtime Error: $f:$l: \"\n"
1354 " }\n"
@@ -1356,25 +1375,46 @@
1375 " }\n"
1376 " return \"\"\n"
1377 "}\n"
1378 "\n"
1379 "\n"
1380 "proc {dict with} {&dictVar {args key} script} {\n"
 
1381 " set keys {}\n"
1382 " foreach {n v} [dict get $dictVar {*}$key] {\n"
1383 " upvar $n var_$n\n"
1384 " set var_$n $v\n"
1385 " lappend keys $n\n"
1386 " }\n"
1387 " catch {uplevel 1 $script} msg opts\n"
1388 " if {[info exists dictVar] && ([llength $key] == 0 || [dict exists $dictVar {*}$key])} {\n"
1389 " foreach n $keys {\n"
1390 " if {[info exists var_$n]} {\n"
1391 " dict set dictVar {*}$key $n [set var_$n]\n"
1392 " } else {\n"
1393 " dict unset dictVar {*}$key $n\n"
1394 " }\n"
1395 " }\n"
1396 " }\n"
1397 " return {*}$opts $msg\n"
1398 "}\n"
1399 "\n"
1400 "\n"
1401 "proc {dict update} {&varName args script} {\n"
1402 " set keys {}\n"
1403 " foreach {n v} $args {\n"
1404 " upvar $v var_$v\n"
1405 " if {[dict exists $varName $n]} {\n"
1406 " set var_$v [dict get $varName $n]\n"
1407 " }\n"
1408 " }\n"
1409 " catch {uplevel 1 $script} msg opts\n"
1410 " if {[info exists varName]} {\n"
1411 " foreach {n v} $args {\n"
1412 " if {[info exists var_$v]} {\n"
1413 " dict set varName $n [set var_$v]\n"
1414 " } else {\n"
1415 " dict unset varName $n\n"
1416 " }\n"
1417 " }\n"
1418 " }\n"
1419 " return {*}$opts $msg\n"
1420 "}\n"
@@ -1389,10 +1429,69 @@
1429 " dict set dict $k $v\n"
1430 " }\n"
1431 " }\n"
1432 " return $dict\n"
1433 "}\n"
1434 "\n"
1435 "proc {dict replace} {dictionary {args {key value}}} {\n"
1436 " if {[llength ${key value}] % 2} {\n"
1437 " tailcall {dict replace}\n"
1438 " }\n"
1439 " tailcall dict merge $dictionary ${key value}\n"
1440 "}\n"
1441 "\n"
1442 "\n"
1443 "proc {dict lappend} {varName key {args value}} {\n"
1444 " upvar $varName dict\n"
1445 " if {[exists dict] && [dict exists $dict $key]} {\n"
1446 " set list [dict get $dict $key]\n"
1447 " }\n"
1448 " lappend list {*}$value\n"
1449 " dict set dict $key $list\n"
1450 "}\n"
1451 "\n"
1452 "\n"
1453 "proc {dict append} {varName key {args value}} {\n"
1454 " upvar $varName dict\n"
1455 " if {[exists dict] && [dict exists $dict $key]} {\n"
1456 " set str [dict get $dict $key]\n"
1457 " }\n"
1458 " append str {*}$value\n"
1459 " dict set dict $key $str\n"
1460 "}\n"
1461 "\n"
1462 "\n"
1463 "proc {dict incr} {varName key {increment 1}} {\n"
1464 " upvar $varName dict\n"
1465 " if {[exists dict] && [dict exists $dict $key]} {\n"
1466 " set value [dict get $dict $key]\n"
1467 " }\n"
1468 " incr value $increment\n"
1469 " dict set dict $key $value\n"
1470 "}\n"
1471 "\n"
1472 "\n"
1473 "proc {dict remove} {dictionary {args key}} {\n"
1474 " foreach k $key {\n"
1475 " dict unset dictionary $k\n"
1476 " }\n"
1477 " return $dictionary\n"
1478 "}\n"
1479 "\n"
1480 "\n"
1481 "proc {dict values} {dictionary {pattern *}} {\n"
1482 " dict keys [lreverse $dictionary] $pattern\n"
1483 "}\n"
1484 "\n"
1485 "\n"
1486 "proc {dict for} {vars dictionary script} {\n"
1487 " if {[llength $vars] != 2} {\n"
1488 " return -code error \"must have exactly two variable names\"\n"
1489 " }\n"
1490 " dict size $dictionary\n"
1491 " tailcall foreach $vars $dictionary $script\n"
1492 "}\n"
1493 );
1494 }
1495 int Jim_tclcompatInit(Jim_Interp *interp)
1496 {
1497 if (Jim_PackageProvide(interp, "tclcompat", "1.0", JIM_ERRMSG))
@@ -1403,12 +1502,14 @@
1502 "\n"
1503 "\n"
1504 "\n"
1505 "\n"
1506 "\n"
1507 "\n"
1508 "\n"
1509 "set env [env]\n"
1510 "\n"
1511 "\n"
1512 "if {[info commands stdout] ne \"\"} {\n"
1513 "\n"
1514 " foreach p {gets flush close eof seek tell} {\n"
1515 " proc $p {chan args} {p} {\n"
@@ -1455,51 +1556,10 @@
1556 " }\n"
1557 " }\n"
1558 " }\n"
1559 "}\n"
1560 "\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1561 "\n"
1562 "proc fileevent {args} {\n"
1563 " tailcall {*}$args\n"
1564 "}\n"
1565 "\n"
@@ -1529,13 +1589,25 @@
1589 " error \"bad option \\\"$force\\\": should be -force\"\n"
1590 " }\n"
1591 "\n"
1592 " set in [open $source]\n"
1593 "\n"
1594 " if {[file exists $target]} {\n"
1595 " if {$force eq \"\"} {\n"
1596 " error \"error copying \\\"$source\\\" to \\\"$target\\\": file already exists\"\n"
1597 " }\n"
1598 "\n"
1599 " if {$source eq $target} {\n"
1600 " return\n"
1601 " }\n"
1602 "\n"
1603 "\n"
1604 " file stat $source ss\n"
1605 " file stat $target ts\n"
1606 " if {$ss(dev) == $ts(dev) && $ss(ino) == $ts(ino) && $ss(ino)} {\n"
1607 " return\n"
1608 " }\n"
1609 " }\n"
1610 " set out [open $target w]\n"
1611 " $in copyto $out\n"
1612 " $out close\n"
1613 " } on error {msg opts} {\n"
@@ -1580,18 +1652,18 @@
1652 " error $error\n"
1653 " }\n"
1654 "}\n"
1655 "\n"
1656 "\n"
1657 "local proc pid {{channelId {}}} {\n"
1658 " if {$channelId eq \"\"} {\n"
1659 " tailcall upcall pid\n"
1660 " }\n"
1661 " if {[catch {$channelId tell}]} {\n"
1662 " return -code error \"can not find channel named \\\"$channelId\\\"\"\n"
1663 " }\n"
1664 " if {[catch {$channelId pid} pids]} {\n"
1665 " return \"\"\n"
1666 " }\n"
1667 " return $pids\n"
1668 "}\n"
1669 "\n"
@@ -1680,23 +1752,25 @@
1752 "}\n"
1753 );
1754 }
1755
1756
 
1757 #include <stdio.h>
1758 #include <string.h>
1759 #include <errno.h>
1760 #include <fcntl.h>
1761 #ifdef HAVE_UNISTD_H
1762 #include <unistd.h>
1763 #include <sys/stat.h>
1764 #endif
1765
1766
1767 #if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H)
1768 #include <sys/socket.h>
1769 #include <netinet/in.h>
1770 #include <arpa/inet.h>
1771 #include <netdb.h>
 
1772 #ifdef HAVE_SYS_UN_H
1773 #include <sys/un.h>
1774 #endif
1775 #else
1776 #define JIM_ANSIC
@@ -1728,15 +1802,12 @@
1802 typedef struct AioFile
1803 {
1804 FILE *fp;
1805 Jim_Obj *filename;
1806 int type;
1807 int openFlags;
1808 int fd;
 
 
 
1809 Jim_Obj *rEvent;
1810 Jim_Obj *wEvent;
1811 Jim_Obj *eEvent;
1812 int addr_family;
1813 } AioFile;
@@ -1760,20 +1831,21 @@
1831 {
1832 AioFile *af = privData;
1833
1834 JIM_NOTUSED(interp);
1835
 
 
 
 
1836 Jim_DecrRefCount(interp, af->filename);
1837
1838 #ifdef jim_ext_eventloop
1839
1840 Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION);
1841 #endif
1842
1843 if (!(af->openFlags & AIO_KEEPOPEN)) {
1844 fclose(af->fp);
1845 }
1846
1847 Jim_Free(af);
1848 }
1849
1850 static int JimCheckStreamError(Jim_Interp *interp, AioFile *af)
1851 {
@@ -2020,12 +2092,31 @@
2092 return JIM_OK;
2093 }
2094
2095 static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2096 {
2097 if (argc == 3) {
2098 #if !defined(JIM_ANSIC) && defined(HAVE_SHUTDOWN)
2099 static const char * const options[] = { "r", "w", NULL };
2100 enum { OPT_R, OPT_W, };
2101 int option;
2102 AioFile *af = Jim_CmdPrivData(interp);
2103
2104 if (Jim_GetEnum(interp, argv[2], options, &option, NULL, JIM_ERRMSG) != JIM_OK) {
2105 return JIM_ERR;
2106 }
2107 if (shutdown(af->fd, option == OPT_R ? SHUT_RD : SHUT_WR) == 0) {
2108 return JIM_OK;
2109 }
2110 JimAioSetError(interp, NULL);
2111 #else
2112 Jim_SetResultString(interp, "async close not supported", -1);
2113 #endif
2114 return JIM_ERR;
2115 }
2116
2117 return Jim_DeleteCommand(interp, Jim_String(argv[0]));
2118 }
2119
2120 static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2121 {
2122 AioFile *af = Jim_CmdPrivData(interp);
@@ -2072,11 +2163,11 @@
2163 #ifdef O_NDELAY
2164 static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2165 {
2166 AioFile *af = Jim_CmdPrivData(interp);
2167
2168 int fmode = fcntl(af->fd, F_GETFL);
2169
2170 if (argc) {
2171 long nb;
2172
2173 if (Jim_GetLong(interp, argv[0], &nb) != JIM_OK) {
@@ -2086,12 +2177,11 @@
2177 fmode |= O_NDELAY;
2178 }
2179 else {
2180 fmode &= ~O_NDELAY;
2181 }
2182 (void)fcntl(af->fd, F_SETFL, fmode);
 
2183 }
2184 Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0);
2185 return JIM_OK;
2186 }
2187 #endif
@@ -2195,11 +2285,11 @@
2285
2286 static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2287 {
2288 AioFile *af = Jim_CmdPrivData(interp);
2289
2290 return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->eEvent, argc, argv);
2291 }
2292 #endif
2293
2294 static const jim_subcmd_type aio_command_table[] = {
2295 { "read",
@@ -2250,14 +2340,14 @@
2340 0,
2341 0,
2342
2343 },
2344 { "close",
2345 "?r(ead)|w(rite)?",
2346 aio_cmd_close,
2347 0,
2348 1,
2349 JIM_MODFLAG_FULLARGV,
2350
2351 },
2352 { "seek",
2353 "offset ?start|current|end",
@@ -2329,30 +2419,32 @@
2419
2420 static int JimAioOpenCommand(Jim_Interp *interp, int argc,
2421 Jim_Obj *const *argv)
2422 {
2423 const char *mode;
 
2424
2425 if (argc != 2 && argc != 3) {
2426 Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?");
2427 return JIM_ERR;
2428 }
2429
2430 mode = (argc == 3) ? Jim_String(argv[2]) : "r";
 
2431
2432 #ifdef jim_ext_tclcompat
2433 {
2434 const char *filename = Jim_String(argv[1]);
2435
2436
2437 if (*filename == '|') {
2438 Jim_Obj *evalObj[3];
2439
2440 evalObj[0] = Jim_NewStringObj(interp, "::popen", -1);
2441 evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1);
2442 evalObj[2] = Jim_NewStringObj(interp, mode, -1);
2443
2444 return Jim_EvalObjVector(interp, 3, evalObj);
2445 }
2446 }
2447 #endif
2448 return JimMakeChannel(interp, NULL, -1, argv[1], "aio.handle%ld", 0, mode);
2449 }
2450
@@ -2359,70 +2451,129 @@
2451 static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename,
2452 const char *hdlfmt, int family, const char *mode)
2453 {
2454 AioFile *af;
2455 char buf[AIO_CMD_LEN];
2456 int openFlags = 0;
2457
2458 if (fh) {
2459 filename = Jim_NewStringObj(interp, hdlfmt, -1);
2460 openFlags = AIO_KEEPOPEN;
2461 }
2462
2463 Jim_IncrRefCount(filename);
2464
2465 if (fh == NULL) {
2466 #if !defined(JIM_ANSIC)
2467 if (fd >= 0) {
 
 
2468 fh = fdopen(fd, mode);
2469 }
2470 else
2471 #endif
2472 fh = fopen(Jim_String(filename), mode);
 
2473
2474 if (fh == NULL) {
2475 JimAioSetError(interp, filename);
2476 #if !defined(JIM_ANSIC)
2477 if (fd >= 0) {
2478 close(fd);
2479 }
2480 #endif
2481 Jim_DecrRefCount(interp, filename);
2482 return JIM_ERR;
2483 }
 
 
 
2484 }
2485
2486
2487 af = Jim_Alloc(sizeof(*af));
2488 memset(af, 0, sizeof(*af));
2489 af->fp = fh;
2490 af->fd = fileno(fh);
2491 af->filename = filename;
2492 #ifdef FD_CLOEXEC
2493 if ((openFlags & AIO_KEEPOPEN) == 0) {
2494 (void)fcntl(af->fd, F_SETFD, FD_CLOEXEC);
2495 }
2496 #endif
2497 af->openFlags = openFlags;
 
 
 
2498 af->addr_family = family;
2499 snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp));
2500 Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);
2501
2502 Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, Jim_NewStringObj(interp, buf, -1)));
2503
2504 return JIM_OK;
2505 }
2506
2507 static int JimMakeChannelPair(Jim_Interp *interp, int p[2], Jim_Obj *filename,
2508 const char *hdlfmt, int family, const char *mode[2])
2509 {
2510 if (JimMakeChannel(interp, NULL, p[0], filename, hdlfmt, family, mode[0]) == JIM_OK) {
2511 Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
2512 Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
2513
2514 if (JimMakeChannel(interp, NULL, p[1], filename, hdlfmt, family, mode[1]) == JIM_OK) {
2515 Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
2516 Jim_SetResult(interp, objPtr);
2517 return JIM_OK;
2518 }
2519 }
2520
2521
2522 close(p[0]);
2523 close(p[1]);
2524 JimAioSetError(interp, NULL);
2525 return JIM_ERR;
2526 }
2527
2528
2529 int Jim_MakeTempFile(Jim_Interp *interp, const char *template)
2530 {
2531 #ifdef HAVE_MKSTEMP
2532 int fd;
2533 mode_t mask;
2534 Jim_Obj *filenameObj;
2535
2536 if (template == NULL) {
2537 const char *tmpdir = getenv("TMPDIR");
2538 if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) {
2539 tmpdir = "/tmp/";
2540 }
2541 filenameObj = Jim_NewStringObj(interp, tmpdir, -1);
2542 if (tmpdir[0] && tmpdir[strlen(tmpdir) - 1] != '/') {
2543 Jim_AppendString(interp, filenameObj, "/", 1);
2544 }
2545 Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1);
2546 }
2547 else {
2548 filenameObj = Jim_NewStringObj(interp, template, -1);
2549 }
2550
2551 mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
2552
2553
2554 fd = mkstemp(filenameObj->bytes);
2555 umask(mask);
2556 if (fd < 0) {
2557 Jim_SetResultString(interp, "Failed to create tempfile", -1);
2558 Jim_FreeNewObj(interp, filenameObj);
2559 return -1;
2560 }
2561
2562 Jim_SetResult(interp, filenameObj);
2563 return fd;
2564 #else
2565 Jim_SetResultString(interp, "tempfile not supported", -1);
2566 return -1;
2567 #endif
2568 }
2569
2570 FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command)
2571 {
2572 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
2573
2574
2575 if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
2576 return ((AioFile *) cmdPtr->u.native.privData)->fp;
2577 }
2578 Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command);
2579 return NULL;
@@ -2443,11 +2594,10 @@
2594 JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w");
2595 JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w");
2596
2597 return JIM_OK;
2598 }
 
2599
2600 #include <errno.h>
2601 #include <stdio.h>
2602 #include <string.h>
2603
@@ -2479,28 +2629,29 @@
2629 return JIM_OK;
2630 }
2631 Jim_SetResultString(interp, strerror(errno), -1);
2632 return JIM_ERR;
2633 }
2634 else {
2635 Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
2636
2637 while ((entryPtr = readdir(dirPtr)) != NULL) {
2638 if (entryPtr->d_name[0] == '.') {
2639 if (entryPtr->d_name[1] == '\0') {
2640 continue;
2641 }
2642 if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0'))
2643 continue;
2644 }
2645 Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, entryPtr->d_name, -1));
2646 }
2647 closedir(dirPtr);
2648
2649 Jim_SetResult(interp, listObj);
2650
2651 return JIM_OK;
2652 }
2653 }
2654
2655 int Jim_readdirInit(Jim_Interp *interp)
2656 {
2657 if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG))
@@ -2511,10 +2662,14 @@
2662 }
2663
2664 #include <stdlib.h>
2665 #include <string.h>
2666
2667 #if defined(JIM_REGEXP)
2668 #else
2669 #include <regex.h>
2670 #endif
2671
2672 static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
2673 {
2674 regfree(objPtr->internalRep.regexpValue.compre);
2675 Jim_Free(objPtr->internalRep.regexpValue.compre);
@@ -3058,58 +3213,61 @@
3213 }
3214 #endif
3215 return "unknown";
3216 }
3217
3218 static void AppendStatElement(Jim_Interp *interp, Jim_Obj *listObj, const char *key, jim_wide value)
3219 {
3220 Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, key, -1));
3221 Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3222 }
3223
3224 static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb)
3225 {
3226
3227 Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
3228
3229 AppendStatElement(interp, listObj, "dev", sb->st_dev);
3230 AppendStatElement(interp, listObj, "ino", sb->st_ino);
3231 AppendStatElement(interp, listObj, "mode", sb->st_mode);
3232 AppendStatElement(interp, listObj, "nlink", sb->st_nlink);
3233 AppendStatElement(interp, listObj, "uid", sb->st_uid);
3234 AppendStatElement(interp, listObj, "gid", sb->st_gid);
3235 AppendStatElement(interp, listObj, "size", sb->st_size);
3236 AppendStatElement(interp, listObj, "atime", sb->st_atime);
3237 AppendStatElement(interp, listObj, "mtime", sb->st_mtime);
3238 AppendStatElement(interp, listObj, "ctime", sb->st_ctime);
3239 Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1));
3240 Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1));
3241
3242
3243 if (varName) {
3244 Jim_Obj *objPtr = Jim_GetVariable(interp, varName, JIM_NONE);
3245 if (objPtr) {
3246 if (Jim_DictSize(interp, objPtr) < 0) {
3247
3248 Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName);
3249 Jim_FreeNewObj(interp, listObj);
3250 return JIM_ERR;
3251 }
3252
3253 if (Jim_IsShared(objPtr))
3254 objPtr = Jim_DuplicateObj(interp, objPtr);
3255
3256
3257 Jim_ListAppendList(interp, objPtr, listObj);
3258 Jim_DictSize(interp, objPtr);
3259 Jim_InvalidateStringRep(objPtr);
3260
3261 Jim_FreeNewObj(interp, listObj);
3262 listObj = objPtr;
3263 }
3264 Jim_SetVariable(interp, varName, listObj);
3265 }
3266
3267
3268 Jim_SetResult(interp, listObj);
3269
3270 return JIM_OK;
3271 }
3272
3273 static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -3264,14 +3422,11 @@
3422 return JIM_OK;
3423 }
3424
3425 static int file_access(Jim_Interp *interp, Jim_Obj *filename, int mode)
3426 {
3427 Jim_SetResultBool(interp, access(Jim_String(filename), mode) != -1);
 
 
 
3428
3429 return JIM_OK;
3430 }
3431
3432 static int file_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -3287,10 +3442,11 @@
3442 static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3443 {
3444 #ifdef X_OK
3445 return file_access(interp, argv[0], X_OK);
3446 #else
3447
3448 Jim_SetResultBool(interp, 1);
3449 return JIM_OK;
3450 #endif
3451 }
3452
@@ -3391,33 +3547,21 @@
3547 argv++;
3548 }
3549 return JIM_OK;
3550 }
3551
 
3552 static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3553 {
3554 int fd = Jim_MakeTempFile(interp, (argc >= 1) ? Jim_String(argv[0]) : NULL);
3555
3556 if (fd < 0) {
 
 
 
 
 
 
 
 
 
3557 return JIM_ERR;
3558 }
3559 close(fd);
3560
 
3561 return JIM_OK;
3562 }
 
3563
3564 static int file_cmd_rename(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3565 {
3566 const char *source;
3567 const char *dest;
@@ -3459,14 +3603,11 @@
3603 return JIM_ERR;
3604 }
3605 return JIM_OK;
3606 }
3607
3608 #ifdef HAVE_LSTAT
 
 
 
3609 static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb)
3610 {
3611 const char *path = Jim_String(filename);
3612
3613 if (lstat(path, sb) == -1) {
@@ -3473,10 +3614,13 @@
3614 Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno));
3615 return JIM_ERR;
3616 }
3617 return JIM_OK;
3618 }
3619 #else
3620 #define file_lstat file_stat
3621 #endif
3622
3623 static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3624 {
3625 struct stat sb;
3626
@@ -3601,28 +3745,32 @@
3745 }
3746 Jim_SetResultString(interp, JimGetFileType((int)sb.st_mode), -1);
3747 return JIM_OK;
3748 }
3749
3750 #ifdef HAVE_LSTAT
3751 static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3752 {
3753 struct stat sb;
3754
3755 if (file_lstat(interp, argv[0], &sb) != JIM_OK) {
3756 return JIM_ERR;
3757 }
3758 return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
3759 }
3760 #else
3761 #define file_cmd_lstat file_cmd_stat
3762 #endif
3763
3764 static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3765 {
3766 struct stat sb;
3767
3768 if (file_stat(interp, argv[0], &sb) != JIM_OK) {
3769 return JIM_ERR;
3770 }
3771 return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
3772 }
3773
3774 static const jim_subcmd_type file_command_table[] = {
3775 { "atime",
3776 "name",
@@ -3727,19 +3875,17 @@
3875 file_cmd_mkdir,
3876 1,
3877 -1,
3878
3879 },
 
3880 { "tempfile",
3881 "?template?",
3882 file_cmd_tempfile,
3883 0,
3884 1,
3885
3886 },
 
3887 { "rename",
3888 "?-force? source dest",
3889 file_cmd_rename,
3890 2,
3891 3,
@@ -3760,20 +3906,20 @@
3906 1,
3907 1,
3908
3909 },
3910 { "stat",
3911 "name ?var?",
3912 file_cmd_stat,
3913 1,
3914 2,
3915
3916 },
3917 { "lstat",
3918 "name ?var?",
3919 file_cmd_lstat,
3920 1,
3921 2,
3922
3923 },
3924 { "type",
3925 "name",
@@ -3829,15 +3975,15 @@
3975 return JIM_OK;
3976 }
3977
3978 static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
3979 {
3980 char *cwd = Jim_Alloc(MAXPATHLEN);
 
3981
3982 if (getcwd(cwd, MAXPATHLEN) == NULL) {
3983 Jim_SetResultString(interp, "Failed to get pwd", -1);
3984 Jim_Free(cwd);
3985 return JIM_ERR;
3986 }
3987 #if defined(__MINGW32__) || defined(_MSC_VER)
3988 {
3989
@@ -3848,11 +3994,11 @@
3994 }
3995 #endif
3996
3997 Jim_SetResultString(interp, cwd, -1);
3998
3999 Jim_Free(cwd);
4000 return JIM_OK;
4001 }
4002
4003 int Jim_fileInit(Jim_Interp *interp)
4004 {
@@ -3917,10 +4063,11 @@
4063
4064 int Jim_execInit(Jim_Interp *interp)
4065 {
4066 if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
4067 return JIM_ERR;
4068
4069 Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL);
4070 return JIM_OK;
4071 }
4072 #else
4073
@@ -3960,10 +4107,11 @@
4107 static int JimErrno(void);
4108 #else
4109 #include <unistd.h>
4110 #include <fcntl.h>
4111 #include <sys/wait.h>
4112 #include <sys/stat.h>
4113
4114 typedef int fdtype;
4115 typedef int pidtype;
4116 #define JimPipe pipe
4117 #define JimErrno() errno
@@ -4034,23 +4182,12 @@
4182 Jim_RemoveTrailingNewline(strObj);
4183 fclose(fh);
4184 return JIM_OK;
4185 }
4186
 
 
 
 
 
 
 
 
 
 
4187 static char **JimBuildEnv(Jim_Interp *interp)
4188 {
 
4189 int i;
4190 int size;
4191 int num;
4192 int n;
4193 char **envptr;
@@ -4064,10 +4201,11 @@
4201
4202
4203
4204 num = Jim_ListLength(interp, objPtr);
4205 if (num % 2) {
4206
4207 num--;
4208 }
4209 size = Jim_Length(objPtr) + 2;
4210
4211 envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size);
@@ -4090,22 +4228,17 @@
4228 }
4229 envptr[n] = NULL;
4230 *envdata = 0;
4231
4232 return envptr;
 
 
 
4233 }
4234
4235 static void JimFreeEnv(char **env, char **original_environ)
4236 {
 
4237 if (env != original_environ) {
4238 Jim_Free(env);
4239 }
 
4240 }
4241
4242 static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus)
4243 {
4244 Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0);
@@ -4154,19 +4287,19 @@
4287 }
4288
4289
4290 struct WaitInfo
4291 {
4292 pidtype pid;
4293 int status;
4294 int flags;
4295 };
4296
4297 struct WaitInfoTable {
4298 struct WaitInfo *info;
4299 int size;
4300 int used;
4301 };
4302
4303
4304 #define WI_DETACHED 2
4305
@@ -4189,14 +4322,12 @@
4322 return table;
4323 }
4324
4325 static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
4326 {
4327 fdtype outputId;
4328 fdtype errorId;
 
 
4329 pidtype *pidPtr;
4330 int numPids, result;
4331
4332 if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) {
4333 Jim_Obj *listObj;
@@ -4243,26 +4374,32 @@
4374
4375 static void JimReapDetachedPids(struct WaitInfoTable *table)
4376 {
4377 struct WaitInfo *waitPtr;
4378 int count;
4379 int dest;
4380
4381 if (!table) {
4382 return;
4383 }
4384
4385 waitPtr = table->info;
4386 dest = 0;
4387 for (count = table->used; count > 0; waitPtr++, count--) {
4388 if (waitPtr->flags & WI_DETACHED) {
4389 int status;
4390 pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG);
4391 if (pid == waitPtr->pid) {
4392
 
 
4393 table->used--;
4394 continue;
4395 }
4396 }
4397 if (waitPtr != &table->info[dest]) {
4398 table->info[dest] = *waitPtr;
4399 }
4400 dest++;
4401 }
4402 }
4403
4404 static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr)
4405 {
@@ -4284,11 +4421,10 @@
4421 }
4422
4423
4424 return JIM_BAD_PID;
4425 }
 
4426
4427 static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr)
4428 {
4429 int j;
4430 struct WaitInfoTable *table = Jim_CmdPrivData(interp);
@@ -4609,27 +4745,23 @@
4745 }
4746 outputId = pipeIds[1];
4747 }
4748
4749
4750 if (pipe_dup_err) {
4751 errorId = outputId;
4752 }
4753
4754
4755
4756 #ifdef __MINGW32__
4757 pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId);
4758 if (pid == JIM_BAD_PID) {
4759 Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]);
4760 goto error;
4761 }
4762 #else
 
 
 
 
 
 
 
 
 
4763 pid = vfork();
4764 if (pid < 0) {
4765 Jim_SetResultErrno(interp, "couldn't fork child process");
4766 goto error;
4767 }
@@ -4642,14 +4774,17 @@
4774
4775 for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) {
4776 close(i);
4777 }
4778
4779
4780 (void)signal(SIGPIPE, SIG_DFL);
4781
4782 execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron());
4783
4784
4785 fprintf(stderr, "couldn't exec \"%s\"\n", arg_array[firstArg]);
4786 _exit(127);
4787 }
4788 #endif
4789
4790
@@ -4751,19 +4886,24 @@
4886 if (JimAppendStreamToString(interp, errorId, Jim_GetResult(interp)) != JIM_OK) {
4887 result = JIM_ERR;
4888 }
4889 }
4890
4891 Jim_RemoveTrailingNewline(Jim_GetResult(interp));
4892
4893 return result;
4894 }
4895
4896 int Jim_execInit(Jim_Interp *interp)
4897 {
4898 if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
4899 return JIM_ERR;
4900
4901 #ifdef SIGPIPE
4902 (void)signal(SIGPIPE, SIG_IGN);
4903 #endif
4904
4905 Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable);
4906 return JIM_OK;
4907 }
4908
4909 #if defined(__MINGW32__)
@@ -5088,28 +5228,26 @@
5228 {
5229 STARTUPINFO startInfo;
5230 PROCESS_INFORMATION procInfo;
5231 HANDLE hProcess, h;
5232 char execPath[MAX_PATH];
 
5233 pidtype pid = JIM_BAD_PID;
5234 Jim_Obj *cmdLineObj;
5235
5236 if (JimWinFindExecutable(argv[0], execPath) < 0) {
5237 return JIM_BAD_PID;
5238 }
 
5239 argv[0] = execPath;
5240
5241 hProcess = GetCurrentProcess();
5242 cmdLineObj = JimWinBuildCommandLine(interp, argv);
5243
5244
5245 ZeroMemory(&startInfo, sizeof(startInfo));
5246 startInfo.cb = sizeof(startInfo);
5247 startInfo.dwFlags = STARTF_USESTDHANDLES;
5248 startInfo.hStdInput = INVALID_HANDLE_VALUE;
5249 startInfo.hStdOutput= INVALID_HANDLE_VALUE;
5250 startInfo.hStdError = INVALID_HANDLE_VALUE;
5251
5252 if (inputId == JIM_BAD_FD) {
5253 if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) {
@@ -5182,18 +5320,17 @@
5320 return lseek(fd, 0L, SEEK_SET);
5321 }
5322
5323 static int JimCreateTemp(Jim_Interp *interp, const char *contents, int len)
5324 {
5325 int fd = Jim_MakeTempFile(interp, NULL);
5326
 
5327 if (fd == JIM_BAD_FD) {
5328 Jim_SetResultErrno(interp, "couldn't create temp file");
5329 return -1;
5330 }
5331 unlink(Jim_String(Jim_GetResult(interp)));
5332 if (contents) {
5333 if (write(fd, contents, len) != len) {
5334 Jim_SetResultErrno(interp, "couldn't write temp file");
5335 close(fd);
5336 return -1;
@@ -5217,11 +5354,10 @@
5354 }
5355 #endif
5356 #endif
5357
5358
 
5359 #ifndef _XOPEN_SOURCE
5360 #define _XOPEN_SOURCE 500
5361 #endif
5362
5363 #include <stdlib.h>
@@ -5239,11 +5375,11 @@
5375
5376 char buf[100];
5377 time_t t;
5378 long seconds;
5379
5380 const char *format = "%a %b %d %H:%M:%S %Z %Y";
5381
5382 if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) {
5383 return -1;
5384 }
5385
@@ -5254,11 +5390,14 @@
5390 if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) {
5391 return JIM_ERR;
5392 }
5393 t = seconds;
5394
5395 if (strftime(buf, sizeof(buf), format, localtime(&t)) == 0) {
5396 Jim_SetResultString(interp, "format string too long", -1);
5397 return JIM_ERR;
5398 }
5399
5400 Jim_SetResultString(interp, buf, -1);
5401
5402 return JIM_OK;
5403 }
@@ -5374,11 +5513,10 @@
5513
5514 Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL);
5515 return JIM_OK;
5516 }
5517
 
5518 #include <limits.h>
5519 #include <stdlib.h>
5520 #include <string.h>
5521 #include <stdio.h>
5522 #include <errno.h>
@@ -5392,33 +5530,29 @@
5530 }
5531
5532 static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5533 {
5534 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5535 Jim_Obj *patternObj;
5536
5537 if (!objPtr) {
5538 return JIM_OK;
5539 }
5540
5541 patternObj = (argc == 1) ? NULL : argv[1];
5542
5543
5544 if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) {
5545 if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) {
5546
5547 Jim_SetResult(interp, objPtr);
5548 return JIM_OK;
5549 }
 
 
 
 
 
5550 }
5551
5552
5553 return Jim_DictValues(interp, objPtr, patternObj);
5554 }
5555
5556 static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5557 {
5558 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
@@ -5443,10 +5577,15 @@
5577 Jim_UnsetVariable(interp, argv[0], JIM_NONE);
5578 return JIM_OK;
5579 }
5580
5581 objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5582
5583 if (objPtr == NULL) {
5584
5585 return JIM_OK;
5586 }
5587
5588 if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
5589 return JIM_ERR;
5590 }
5591
@@ -5480,10 +5619,20 @@
5619
5620 Jim_SetResultInt(interp, len);
5621
5622 return JIM_OK;
5623 }
5624
5625 static int array_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5626 {
5627 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
5628 if (objPtr) {
5629 return Jim_DictInfo(interp, objPtr);
5630 }
5631 Jim_SetResultFormatted(interp, "\"%#s\" isn't an array", argv[0], NULL);
5632 return JIM_ERR;
5633 }
5634
5635 static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
5636 {
5637 int i;
5638 int len;
@@ -5498,10 +5647,13 @@
5647
5648 dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
5649 if (!dictObj) {
5650
5651 return Jim_SetVariable(interp, argv[0], listObj);
5652 }
5653 else if (Jim_DictSize(interp, dictObj) < 0) {
5654 return JIM_ERR;
5655 }
5656
5657 if (Jim_IsShared(dictObj)) {
5658 dictObj = Jim_DuplicateObj(interp, dictObj);
5659 }
@@ -5551,10 +5703,17 @@
5703 "arrayName",
5704 array_cmd_size,
5705 1,
5706 1,
5707
5708 },
5709 { "stat",
5710 "arrayName",
5711 array_cmd_stat,
5712 1,
5713 1,
5714
5715 },
5716 { "unset",
5717 "arrayName ?pattern?",
5718 array_cmd_unset,
5719 1,
@@ -5597,11 +5756,10 @@
5756 Jim_arrayInit(interp);
5757 Jim_stdlibInit(interp);
5758 Jim_tclcompatInit(interp);
5759 return JIM_OK;
5760 }
 
5761 #define JIM_OPTIMIZATION
5762
5763 #include <stdio.h>
5764 #include <stdlib.h>
5765
@@ -5661,21 +5819,20 @@
5819 #define JIM_INTEGER_SPACE 24
5820
5821 const char *jim_tt_name(int type);
5822
5823 #ifdef JIM_DEBUG_PANIC
5824 static void JimPanicDump(int fail_condition, const char *fmt, ...);
5825 #define JimPanic(X) JimPanicDump X
5826 #else
5827 #define JimPanic(X)
5828 #endif
5829
5830
5831 static char JimEmptyStringRep[] = "";
5832
5833 static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action);
 
5834 static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
5835 int flags);
5836 static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands);
5837 static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr);
5838 static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
@@ -5922,44 +6079,10 @@
6079 }
6080 return n;
6081 }
6082 #endif
6083
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6084 static int JimCheckConversion(const char *str, const char *endptr)
6085 {
6086 if (str[0] == '\0' || str == endptr) {
6087 return JIM_ERR;
6088 }
@@ -6070,48 +6193,10 @@
6193 }
6194
6195 return JimCheckConversion(str, endptr);
6196 }
6197
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6198 int Jim_StringToDouble(const char *str, double *doublePtr)
6199 {
6200 char *endptr;
6201
6202
@@ -6133,23 +6218,23 @@
6218 }
6219 return res;
6220 }
6221
6222 #ifdef JIM_DEBUG_PANIC
6223 static void JimPanicDump(int condition, const char *fmt, ...)
6224 {
6225 va_list ap;
6226
6227 if (!condition) {
6228 return;
6229 }
6230
6231 va_start(ap, fmt);
6232
6233 fprintf(stderr, "\nJIM INTERPRETER PANIC: ");
6234 vfprintf(stderr, fmt, ap);
6235 fprintf(stderr, "\n\n");
6236 va_end(ap);
6237
6238 #ifdef HAVE_BACKTRACE
6239 {
6240 void *array[40];
@@ -6157,13 +6242,13 @@
6242 char **strings;
6243
6244 size = backtrace(array, 40);
6245 strings = backtrace_symbols(array, size);
6246 for (i = 0; i < size; i++)
6247 fprintf(stderr, "[backtrace] %s\n", strings[i]);
6248 fprintf(stderr, "[backtrace] Include the above lines and the output\n");
6249 fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report.\n");
6250 }
6251 #endif
6252
6253 exit(1);
6254 }
@@ -6237,18 +6322,24 @@
6322 h += (h << 3) + *buf++;
6323 return h;
6324 }
6325
6326
6327
6328
6329 static void JimResetHashTable(Jim_HashTable *ht)
6330 {
6331 ht->table = NULL;
6332 ht->size = 0;
6333 ht->sizemask = 0;
6334 ht->used = 0;
6335 ht->collisions = 0;
6336 #ifdef JIM_RANDOMISE_HASH
6337 ht->uniq = (rand() ^ time(NULL) ^ clock());
6338 #else
6339 ht->uniq = 0;
6340 #endif
6341 }
6342
6343 static void JimInitHashTableIterator(Jim_HashTable *ht, Jim_HashTableIterator *iter)
6344 {
6345 iter->ht = ht;
@@ -6286,10 +6377,12 @@
6377
6378 Jim_InitHashTable(&n, ht->type, ht->privdata);
6379 n.size = realsize;
6380 n.sizemask = realsize - 1;
6381 n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *));
6382
6383 n.uniq = ht->uniq;
6384
6385
6386 memset(n.table, 0, realsize * sizeof(Jim_HashEntry *));
6387
6388 n.used = ht->used;
@@ -6342,20 +6435,27 @@
6435 int existed;
6436 Jim_HashEntry *entry;
6437
6438 entry = JimInsertHashEntry(ht, key, 1);
6439 if (entry->key) {
6440 if (ht->type->valDestructor && ht->type->valDup) {
6441 void *newval = ht->type->valDup(ht->privdata, val);
6442 ht->type->valDestructor(ht->privdata, entry->u.val);
6443 entry->u.val = newval;
6444 }
6445 else {
6446 Jim_FreeEntryVal(ht, entry);
6447 Jim_SetHashVal(ht, entry, val);
6448 }
6449 existed = 1;
6450 }
6451 else {
6452
6453 Jim_SetHashKey(ht, entry, key);
6454 Jim_SetHashVal(ht, entry, val);
6455 existed = 0;
6456 }
 
6457
6458 return existed;
6459 }
6460
6461
@@ -6520,11 +6620,11 @@
6620 return Jim_GenHashFunction(key, strlen(key));
6621 }
6622
6623 static void *JimStringCopyHTDup(void *privdata, const void *key)
6624 {
6625 return Jim_StrDup(key);
6626 }
6627
6628 static int JimStringCopyHTKeyCompare(void *privdata, const void *key1, const void *key2)
6629 {
6630 return strcmp(key1, key2) == 0;
@@ -6620,11 +6720,11 @@
6720 freeFunc(stack->vector[i]);
6721 }
6722
6723
6724
6725 #define JIM_TT_NONE 0
6726 #define JIM_TT_STR 1
6727 #define JIM_TT_ESC 2
6728 #define JIM_TT_VAR 3
6729 #define JIM_TT_DICTSUGAR 4
6730 #define JIM_TT_CMD 5
@@ -6652,10 +6752,15 @@
6752
6753
6754 #define JIM_PS_DEF 0
6755 #define JIM_PS_QUOTE 1
6756 #define JIM_PS_DICTSUGAR 2
6757
6758 struct JimParseMissing {
6759 int ch;
6760 int line;
6761 };
6762
6763 struct JimParserCtx
6764 {
6765 const char *p;
6766 int len;
@@ -6665,17 +6770,11 @@
6770 int tline;
6771 int tt;
6772 int eof;
6773 int state;
6774 int comment;
6775 struct JimParseMissing missing;
 
 
 
 
 
 
6776 };
6777
6778 static int JimParseScript(struct JimParserCtx *pc);
6779 static int JimParseSep(struct JimParserCtx *pc);
6780 static int JimParseEol(struct JimParserCtx *pc);
@@ -6685,11 +6784,10 @@
6784 static int JimParseBrace(struct JimParserCtx *pc);
6785 static int JimParseStr(struct JimParserCtx *pc);
6786 static int JimParseComment(struct JimParserCtx *pc);
6787 static void JimParseSubCmd(struct JimParserCtx *pc);
6788 static int JimParseSubQuote(struct JimParserCtx *pc);
 
6789 static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc);
6790
6791 static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int linenr)
6792 {
6793 pc->p = prg;
@@ -6700,12 +6798,12 @@
6798 pc->tt = JIM_TT_NONE;
6799 pc->eof = 0;
6800 pc->state = JIM_PS_DEF;
6801 pc->linenr = linenr;
6802 pc->comment = 1;
6803 pc->missing.ch = ' ';
6804 pc->missing.line = linenr;
6805 }
6806
6807 static int JimParseScript(struct JimParserCtx *pc)
6808 {
6809 while (1) {
@@ -6837,12 +6935,12 @@
6935 break;
6936 }
6937 pc->p++;
6938 pc->len--;
6939 }
6940 pc->missing.ch = '{';
6941 pc->missing.line = pc->tline;
6942 pc->tend = pc->p - 1;
6943 }
6944
6945 static int JimParseSubQuote(struct JimParserCtx *pc)
6946 {
@@ -6884,12 +6982,12 @@
6982 break;
6983 }
6984 pc->p++;
6985 pc->len--;
6986 }
6987 pc->missing.ch = '"';
6988 pc->missing.line = line;
6989 pc->tend = pc->p - 1;
6990 return tt;
6991 }
6992
6993 static void JimParseSubCmd(struct JimParserCtx *pc)
@@ -6943,12 +7041,12 @@
7041 }
7042 startofword = isspace(UCHAR(*pc->p));
7043 pc->p++;
7044 pc->len--;
7045 }
7046 pc->missing.ch = '[';
7047 pc->missing.line = line;
7048 pc->tend = pc->p - 1;
7049 }
7050
7051 static int JimParseBrace(struct JimParserCtx *pc)
7052 {
@@ -7088,19 +7186,19 @@
7186 if (*pc->p == '"') {
7187 pc->state = JIM_PS_QUOTE;
7188 pc->p++;
7189 pc->len--;
7190
7191 pc->missing.line = pc->tline;
7192 }
7193 }
7194 pc->tstart = pc->p;
7195 pc->tline = pc->linenr;
7196 while (1) {
7197 if (pc->len == 0) {
7198 if (pc->state == JIM_PS_QUOTE) {
7199 pc->missing.ch = '"';
7200 }
7201 pc->tend = pc->p - 1;
7202 pc->tt = JIM_TT_ESC;
7203 return JIM_OK;
7204 }
@@ -7116,10 +7214,14 @@
7214 pc->linenr++;
7215 }
7216 pc->p++;
7217 pc->len--;
7218 }
7219 else if (pc->len == 1) {
7220
7221 pc->missing.ch = '\\';
7222 }
7223 break;
7224 case '(':
7225
7226 if (pc->len > 1 && pc->p[1] != '$') {
7227 break;
@@ -7176,17 +7278,26 @@
7278 }
7279
7280 static int JimParseComment(struct JimParserCtx *pc)
7281 {
7282 while (*pc->p) {
7283 if (*pc->p == '\\') {
7284 pc->p++;
7285 pc->len--;
7286 if (pc->len == 0) {
7287 pc->missing.ch = '\\';
7288 return JIM_OK;
7289 }
7290 if (*pc->p == '\n') {
7291 pc->linenr++;
7292 }
7293 }
7294 else if (*pc->p == '\n') {
7295 pc->p++;
7296 pc->len--;
7297 pc->linenr++;
7298 break;
 
 
 
 
7299 }
7300 pc->p++;
7301 pc->len--;
7302 }
7303 return JIM_OK;
@@ -7404,13 +7515,13 @@
7515 JimParserInit(&parser, s, len, 1);
7516 while (!parser.eof) {
7517 JimParseScript(&parser);
7518 }
7519 if (stateCharPtr) {
7520 *stateCharPtr = parser.missing.ch;
7521 }
7522 return parser.missing.ch == ' ';
7523 }
7524
7525 static int JimParseListSep(struct JimParserCtx *pc);
7526 static int JimParseListStr(struct JimParserCtx *pc);
7527 static int JimParseListQuote(struct JimParserCtx *pc);
@@ -7662,10 +7773,16 @@
7773 JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
7774 objPtr->typePtr->updateStringProc(objPtr);
7775 }
7776 return objPtr->bytes;
7777 }
7778
7779 static void JimSetStringBytes(Jim_Obj *objPtr, const char *str)
7780 {
7781 objPtr->bytes = Jim_StrDup(str);
7782 objPtr->length = strlen(str);
7783 }
7784
7785 static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
7786 static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
7787
7788 static const Jim_ObjType dictSubstObjType = {
@@ -7703,11 +7820,10 @@
7820 static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
7821 {
7822 JIM_NOTUSED(interp);
7823
7824 dupPtr->internalRep.strValue.maxLength = srcPtr->length;
 
7825 dupPtr->internalRep.strValue.charLength = srcPtr->internalRep.strValue.charLength;
7826 }
7827
7828 static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
7829 {
@@ -7752,18 +7868,17 @@
7868 if (len == -1)
7869 len = strlen(s);
7870
7871 if (len == 0) {
7872 objPtr->bytes = JimEmptyStringRep;
 
7873 }
7874 else {
7875 objPtr->bytes = Jim_Alloc(len + 1);
 
7876 memcpy(objPtr->bytes, s, len);
7877 objPtr->bytes[len] = '\0';
7878 }
7879 objPtr->length = len;
7880
7881
7882 objPtr->typePtr = NULL;
7883 return objPtr;
7884 }
@@ -7791,11 +7906,11 @@
7906 Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len)
7907 {
7908 Jim_Obj *objPtr = Jim_NewObj(interp);
7909
7910 objPtr->bytes = s;
7911 objPtr->length = (len == -1) ? strlen(s) : len;
7912 objPtr->typePtr = NULL;
7913 return objPtr;
7914 }
7915
7916 static void StringAppendString(Jim_Obj *objPtr, const char *str, int len)
@@ -7820,17 +7935,17 @@
7935 }
7936 objPtr->internalRep.strValue.maxLength = needlen;
7937 }
7938 memcpy(objPtr->bytes + objPtr->length, str, len);
7939 objPtr->bytes[objPtr->length + len] = '\0';
7940
7941 if (objPtr->internalRep.strValue.charLength >= 0) {
7942
7943 objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len);
7944 }
7945 objPtr->length += len;
7946 }
 
7947
7948 void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len)
7949 {
7950 JimPanic((Jim_IsShared(objPtr), "Jim_AppendString called with shared object"));
7951 SetStringFromAny(interp, objPtr);
@@ -7838,13 +7953,11 @@
7953 }
7954
7955 void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr)
7956 {
7957 int len;
7958 const char *str = Jim_GetString(appendObjPtr, &len);
 
 
7959 Jim_AppendString(interp, objPtr, str, len);
7960 }
7961
7962 void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...)
7963 {
@@ -7851,11 +7964,11 @@
7964 va_list ap;
7965
7966 SetStringFromAny(interp, objPtr);
7967 va_start(ap, objPtr);
7968 while (1) {
7969 const char *s = va_arg(ap, const char *);
7970
7971 if (s == NULL)
7972 break;
7973 Jim_AppendString(interp, objPtr, s, -1);
7974 }
@@ -7862,20 +7975,20 @@
7975 va_end(ap);
7976 }
7977
7978 int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr)
7979 {
7980 if (aObjPtr == bObjPtr) {
 
 
 
7981 return 1;
7982 }
7983 else {
7984 int Alen, Blen;
7985 const char *sA = Jim_GetString(aObjPtr, &Alen);
7986 const char *sB = Jim_GetString(bObjPtr, &Blen);
7987
7988 return Alen == Blen && memcmp(sA, sB, Alen) == 0;
7989 }
7990 }
7991
7992 int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase)
7993 {
7994 return JimGlobMatch(Jim_String(patternObjPtr), Jim_String(objPtr), nocase);
@@ -8036,11 +8149,11 @@
8149 static void JimStrCopyUpperLower(char *dest, const char *str, int uc)
8150 {
8151 while (*str) {
8152 int c;
8153 str += utf8_tounicode(str, &c);
8154 dest += utf8_getchars(dest, uc ? utf8_upper(c) : utf8_lower(c));
8155 }
8156 *dest = 0;
8157 }
8158
8159 static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr)
@@ -8096,11 +8209,11 @@
8209 len *= 2;
8210 #endif
8211 buf = p = Jim_Alloc(len + 1);
8212
8213 str += utf8_tounicode(str, &c);
8214 p += utf8_getchars(p, utf8_title(c));
8215
8216 JimStrCopyUpperLower(p, str, 0);
8217
8218 return Jim_NewStringObjNoAlloc(interp, buf, -1);
8219 }
@@ -8203,10 +8316,11 @@
8316 if (nontrim == NULL) {
8317
8318 return Jim_NewEmptyStringObj(interp);
8319 }
8320 if (nontrim == strObjPtr->bytes + len) {
8321
8322 return strObjPtr;
8323 }
8324
8325 if (Jim_IsShared(strObjPtr)) {
8326 strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes));
@@ -8226,14 +8340,14 @@
8340 Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr);
8341
8342
8343 strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr);
8344
8345
8346 if (objPtr != strObjPtr && objPtr->refCount == 0) {
8347
8348 Jim_FreeNewObj(interp, objPtr);
 
8349 }
8350
8351 return strObjPtr;
8352 }
8353
@@ -8270,26 +8384,26 @@
8384 return JIM_ERR;
8385 }
8386
8387 str = Jim_GetString(strObjPtr, &len);
8388 if (len == 0) {
8389 Jim_SetResultBool(interp, !strict);
8390 return JIM_OK;
8391 }
8392
8393 switch (strclass) {
8394 case STR_IS_INTEGER:
8395 {
8396 jim_wide w;
8397 Jim_SetResultBool(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK);
8398 return JIM_OK;
8399 }
8400
8401 case STR_IS_DOUBLE:
8402 {
8403 double d;
8404 Jim_SetResultBool(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE);
8405 return JIM_OK;
8406 }
8407
8408 case STR_IS_ALPHA: isclassfunc = isalpha; break;
8409 case STR_IS_ALNUM: isclassfunc = isalnum; break;
@@ -8307,15 +8421,15 @@
8421 return JIM_ERR;
8422 }
8423
8424 for (i = 0; i < len; i++) {
8425 if (!isclassfunc(str[i])) {
8426 Jim_SetResultBool(interp, 0);
8427 return JIM_OK;
8428 }
8429 }
8430 Jim_SetResultBool(interp, 1);
8431 return JIM_OK;
8432 }
8433
8434
8435
@@ -8327,17 +8441,19 @@
8441 JIM_TYPE_REFERENCES,
8442 };
8443
8444 int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str)
8445 {
8446 if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) {
8447 return 1;
8448 }
8449 else {
8450 const char *objStr = Jim_String(objPtr);
8451
8452 if (strcmp(str, objStr) != 0)
8453 return 0;
8454
8455 if (objPtr->typePtr != &comparedStringObjType) {
8456 Jim_FreeIntRep(interp, objPtr);
8457 objPtr->typePtr = &comparedStringObjType;
8458 }
8459 objPtr->internalRep.ptr = (char *)str;
@@ -8379,24 +8495,23 @@
8495
8496 static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr,
8497 Jim_Obj *fileNameObj, int lineNumber)
8498 {
8499 JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object"));
8500 JimPanic((objPtr->typePtr != NULL, "JimSetSourceInfo called with typed object"));
8501 Jim_IncrRefCount(fileNameObj);
8502 objPtr->internalRep.sourceValue.fileNameObj = fileNameObj;
8503 objPtr->internalRep.sourceValue.lineNumber = lineNumber;
8504 objPtr->typePtr = &sourceObjType;
8505 }
8506
 
8507 static const Jim_ObjType scriptLineObjType = {
8508 "scriptline",
8509 NULL,
8510 NULL,
8511 NULL,
8512 JIM_NONE,
8513 };
8514
8515 static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line)
8516 {
8517 Jim_Obj *objPtr;
@@ -8413,15 +8528,14 @@
8528 objPtr->internalRep.scriptLineValue.line = line;
8529
8530 return objPtr;
8531 }
8532
 
 
8533 static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
8534 static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
8535 static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
8536 static int JimParseCheckMissing(Jim_Interp *interp, int ch);
8537
8538 static const Jim_ObjType scriptObjType = {
8539 "script",
8540 FreeScriptInternalRep,
8541 DupScriptInternalRep,
@@ -8429,34 +8543,33 @@
8543 JIM_TYPE_REFERENCES,
8544 };
8545
8546 typedef struct ScriptToken
8547 {
 
8548 Jim_Obj *objPtr;
8549 int type;
8550 } ScriptToken;
8551
8552 typedef struct ScriptObj
8553 {
 
8554 ScriptToken *token;
8555 Jim_Obj *fileNameObj;
8556 int len;
8557 int substFlags;
8558 int inUse; /* Used to share a ScriptObj. Currently
8559 only used by Jim_EvalObj() as protection against
8560 shimmering of the currently evaluated object. */
 
8561 int firstline;
8562 int linenr;
8563 } ScriptObj;
8564
8565 void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
8566 {
8567 int i;
8568 struct ScriptObj *script = (void *)objPtr->internalRep.ptr;
8569
8570 if (--script->inUse != 0)
 
8571 return;
8572 for (i = 0; i < script->len; i++) {
8573 Jim_DecrRefCount(interp, script->token[i].objPtr);
8574 }
8575 Jim_Free(script->token);
@@ -8467,11 +8580,10 @@
8580 void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
8581 {
8582 JIM_NOTUSED(interp);
8583 JIM_NOTUSED(srcPtr);
8584
 
8585 dupPtr->typePtr = NULL;
8586 }
8587
8588 typedef struct
8589 {
@@ -8666,11 +8778,11 @@
8778 token--;
8779 }
8780
8781 script->len = token - script->token;
8782
8783 JimPanic((script->len >= count, "allocated script array is too short"));
8784
8785 #ifdef DEBUG_SHOW_SCRIPT
8786 printf("==== Script (%s) ====\n", Jim_String(script->fileNameObj));
8787 for (i = 0; i < script->len; i++) {
8788 const ScriptToken *t = &script->token[i];
@@ -8677,10 +8789,35 @@
8789 printf("[%2d] %s %s\n", i, jim_tt_name(t->type), Jim_String(t->objPtr));
8790 }
8791 #endif
8792
8793 }
8794
8795 static int JimParseCheckMissing(Jim_Interp *interp, int ch)
8796 {
8797 const char *msg;
8798
8799 switch (ch) {
8800 case '\\':
8801 case ' ':
8802 return JIM_OK;
8803
8804 case '[':
8805 msg = "unmatched \"[\"";
8806 break;
8807 case '{':
8808 msg = "missing close-brace";
8809 break;
8810 case '"':
8811 default:
8812 msg = "missing quote";
8813 break;
8814 }
8815
8816 Jim_SetResultString(interp, msg, -1);
8817 return JIM_ERR;
8818 }
8819
8820 static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
8821 ParseTokenList *tokenlist)
8822 {
8823 int i;
@@ -8699,18 +8836,19 @@
8836 }
8837
8838 script->len = i;
8839 }
8840
8841 static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
8842 {
8843 int scriptTextLen;
8844 const char *scriptText = Jim_GetString(objPtr, &scriptTextLen);
8845 struct JimParserCtx parser;
8846 struct ScriptObj *script;
8847 ParseTokenList tokenlist;
8848 int line = 1;
8849 int retcode = JIM_OK;
8850
8851
8852 if (objPtr->typePtr == &sourceObjType) {
8853 line = objPtr->internalRep.sourceValue.lineNumber;
8854 }
@@ -8722,16 +8860,12 @@
8860 while (!parser.eof) {
8861 JimParseScript(&parser);
8862 ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
8863 parser.tline);
8864 }
8865
8866 retcode = JimParseCheckMissing(interp, parser.missing.ch);
 
 
 
 
8867
8868
8869 ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0);
8870
8871
@@ -8742,10 +8876,11 @@
8876 script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
8877 }
8878 else {
8879 script->fileNameObj = interp->emptyObj;
8880 }
8881 script->linenr = parser.missing.line;
8882 Jim_IncrRefCount(script->fileNameObj);
8883
8884 ScriptObjAddTokens(interp, script, &tokenlist);
8885
8886
@@ -8754,11 +8889,11 @@
8889
8890 Jim_FreeIntRep(interp, objPtr);
8891 Jim_SetIntRepPtr(objPtr, script);
8892 objPtr->typePtr = &scriptObjType;
8893
8894 return retcode;
8895 }
8896
8897 ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr)
8898 {
8899 if (objPtr == interp->emptyObj) {
@@ -8765,11 +8900,13 @@
8900
8901 objPtr = interp->nullScriptObj;
8902 }
8903
8904 if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) {
8905 if (JimSetScriptFromAny(interp, objPtr) == JIM_ERR) {
8906 return NULL;
8907 }
8908 }
8909 return (ScriptObj *) Jim_GetIntRepPtr(objPtr);
8910 }
8911
8912 static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr)
@@ -8850,10 +8987,26 @@
8987 nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
8988 Jim_AppendStrings(interp, nsObj, "::", name, NULL);
8989 }
8990 return nsObj;
8991 }
8992
8993 Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
8994 {
8995 Jim_Obj *resultObj;
8996
8997 const char *name = Jim_String(nameObjPtr);
8998 if (name[0] == ':' && name[1] == ':') {
8999 return nameObjPtr;
9000 }
9001 Jim_IncrRefCount(nameObjPtr);
9002 resultObj = Jim_NewStringObj(interp, "::", -1);
9003 Jim_AppendObj(interp, resultObj, nameObjPtr);
9004 Jim_DecrRefCount(interp, nameObjPtr);
9005
9006 return resultObj;
9007 }
9008
9009 static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr)
9010 {
9011 Jim_Obj *objPtr = interp->emptyObj;
9012
@@ -8877,10 +9030,15 @@
9030
9031 #else
9032
9033 #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME))
9034 #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY)
9035
9036 Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
9037 {
9038 return nameObjPtr;
9039 }
9040 #endif
9041
9042 static int JimCreateCommand(Jim_Interp *interp, const char *name, Jim_Cmd *cmd)
9043 {
9044 Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, name);
@@ -8889,12 +9047,12 @@
9047 Jim_InterpIncrProcEpoch(interp);
9048 }
9049
9050 if (he && interp->local) {
9051
9052 cmd->prevCmd = Jim_GetHashEntryVal(he);
9053 Jim_SetHashVal(&interp->commands, he, cmd);
9054 }
9055 else {
9056 if (he) {
9057
9058 Jim_DeleteHashEntry(&interp->commands, name);
@@ -8933,19 +9091,19 @@
9091 }
9092
9093 cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable));
9094 Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp);
9095 for (i = 0; i < len; i++) {
9096 Jim_Obj *objPtr, *initObjPtr, *nameObjPtr;
9097 Jim_Var *varPtr;
9098 int subLen;
9099
9100 objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i);
9101
9102 subLen = Jim_ListLength(interp, objPtr);
9103 if (subLen == 1 || subLen == 2) {
9104 nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0);
9105 if (subLen == 1) {
9106 initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
9107 if (initObjPtr == NULL) {
9108 Jim_SetResultFormatted(interp,
9109 "variable for initialization of static \"%#s\" not found in the local context",
@@ -8952,11 +9110,11 @@
9110 nameObjPtr);
9111 return JIM_ERR;
9112 }
9113 }
9114 else {
9115 initObjPtr = Jim_ListGetIndex(interp, objPtr, 1);
9116 }
9117 if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) {
9118 return JIM_ERR;
9119 }
9120
@@ -9038,11 +9196,11 @@
9196 Jim_Obj *nameObjPtr;
9197 Jim_Obj *defaultObjPtr;
9198 int len;
9199
9200
9201 argPtr = Jim_ListGetIndex(interp, argListObjPtr, i);
9202 len = Jim_ListLength(interp, argPtr);
9203 if (len == 0) {
9204 Jim_SetResultString(interp, "argument with no name", -1);
9205 err:
9206 JimDecrCmdRefCount(interp, cmdPtr);
@@ -9053,12 +9211,12 @@
9211 goto err;
9212 }
9213
9214 if (len == 2) {
9215
9216 nameObjPtr = Jim_ListGetIndex(interp, argPtr, 0);
9217 defaultObjPtr = Jim_ListGetIndex(interp, argPtr, 1);
9218 }
9219 else {
9220
9221 nameObjPtr = argPtr;
9222 defaultObjPtr = NULL;
@@ -9132,11 +9290,11 @@
9290 else if (Jim_FindHashEntry(&interp->commands, fqnew)) {
9291 Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName);
9292 }
9293 else {
9294
9295 cmdPtr = Jim_GetHashEntryVal(he);
9296 JimIncrCmdRefCount(cmdPtr);
9297 JimUpdateProcNamespace(interp, cmdPtr, fqnew);
9298 Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr);
9299
9300
@@ -9217,11 +9375,11 @@
9375 return NULL;
9376 }
9377 #ifdef jim_ext_namespace
9378 found:
9379 #endif
9380 cmd = Jim_GetHashEntryVal(he);
9381
9382
9383 Jim_FreeIntRep(interp, objPtr);
9384 objPtr->typePtr = &commandObjType;
9385 objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch;
@@ -9323,11 +9481,11 @@
9481
9482
9483 Jim_FreeIntRep(interp, objPtr);
9484 objPtr->typePtr = &variableObjType;
9485 objPtr->internalRep.varValue.callFrameId = framePtr->id;
9486 objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he);
9487 objPtr->internalRep.varValue.global = global;
9488 return JIM_OK;
9489 }
9490
9491
@@ -9641,11 +9799,11 @@
9799 }
9800
9801 retval = Jim_DeleteHashEntry(&framePtr->vars, name);
9802 if (retval == JIM_OK) {
9803
9804 framePtr->id = interp->callFrameEpoch++;
9805 }
9806 }
9807 }
9808 if (retval != JIM_OK && (flags & JIM_ERRMSG)) {
9809 Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such variable", nameObjPtr);
@@ -9725,28 +9883,17 @@
9883 return NULL;
9884 }
9885
9886 ret = Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
9887 if (ret != JIM_OK) {
9888 Jim_SetResultFormatted(interp,
9889 "can't read \"%#s(%#s)\": %s array", varObjPtr, keyObjPtr,
9890 ret < 0 ? "variable isn't" : "no such element in");
 
 
 
 
 
 
9891 }
9892 else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) {
 
 
 
 
 
9893
9894 Jim_SetVariable(interp, varObjPtr, Jim_DuplicateObj(interp, dictObjPtr));
9895 }
9896
9897 return resObjPtr;
9898 }
9899
@@ -9843,68 +9990,67 @@
9990 Jim_CallFrame *cf;
9991
9992 if (interp->freeFramesList) {
9993 cf = interp->freeFramesList;
9994 interp->freeFramesList = cf->next;
9995
9996 cf->argv = NULL;
9997 cf->argc = 0;
9998 cf->procArgsObjPtr = NULL;
9999 cf->procBodyObjPtr = NULL;
10000 cf->next = NULL;
10001 cf->staticVars = NULL;
10002 cf->localCommands = NULL;
10003 cf->tailcall = 0;
10004 cf->tailcallObj = NULL;
10005 cf->tailcallCmd = NULL;
10006 }
10007 else {
10008 cf = Jim_Alloc(sizeof(*cf));
10009 memset(cf, 0, sizeof(*cf));
10010
10011 Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp);
10012 }
10013
10014 cf->id = interp->callFrameEpoch++;
10015 cf->parent = parent;
10016 cf->level = parent ? parent->level + 1 : 0;
 
 
 
 
 
 
 
 
10017 cf->nsObj = nsObj;
10018 Jim_IncrRefCount(nsObj);
10019
 
10020 return cf;
10021 }
10022
 
 
 
 
 
 
10023 static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands)
10024 {
10025
10026 if (localCommands) {
10027 Jim_Obj *cmdNameObj;
10028
10029 while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) {
10030 Jim_HashEntry *he;
10031 Jim_Obj *fqObjName;
10032 Jim_HashTable *ht = &interp->commands;
10033
10034 const char *fqname = JimQualifyName(interp, Jim_String(cmdNameObj), &fqObjName);
10035
10036 he = Jim_FindHashEntry(ht, fqname);
10037
10038 if (he) {
10039 Jim_Cmd *cmd = Jim_GetHashEntryVal(he);
10040 if (cmd->prevCmd) {
10041 Jim_Cmd *prevCmd = cmd->prevCmd;
10042 cmd->prevCmd = NULL;
10043
10044
10045 JimDecrCmdRefCount(interp, cmd);
10046
10047
10048 Jim_SetHashVal(ht, he, prevCmd);
10049 }
10050 else {
10051 Jim_DeleteHashEntry(ht, fqname);
10052 Jim_InterpIncrProcEpoch(interp);
10053 }
10054 }
10055 Jim_DecrRefCount(interp, cmdNameObj);
10056 JimFreeQualifiedName(interp, fqObjName);
@@ -9914,47 +10060,45 @@
10060 }
10061 return JIM_OK;
10062 }
10063
10064
10065 #define JIM_FCF_FULL 0
10066 #define JIM_FCF_REUSE 1
10067 static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action)
10068 {
10069 JimDeleteLocalProcs(interp, cf->localCommands);
10070
10071 if (cf->procArgsObjPtr)
10072 Jim_DecrRefCount(interp, cf->procArgsObjPtr);
10073 if (cf->procBodyObjPtr)
10074 Jim_DecrRefCount(interp, cf->procBodyObjPtr);
10075 Jim_DecrRefCount(interp, cf->nsObj);
10076 if (action == JIM_FCF_FULL || cf->vars.size != JIM_HT_INITIAL_SIZE)
10077 Jim_FreeHashTable(&cf->vars);
10078 else {
10079 int i;
10080 Jim_HashEntry **table = cf->vars.table, *he;
10081
10082 for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) {
10083 he = table[i];
10084 while (he != NULL) {
10085 Jim_HashEntry *nextEntry = he->next;
10086 Jim_Var *varPtr = Jim_GetHashEntryVal(he);
10087
10088 Jim_DecrRefCount(interp, varPtr->objPtr);
10089 Jim_Free(Jim_GetHashEntryKey(he));
10090 Jim_Free(varPtr);
10091 Jim_Free(he);
10092 table[i] = NULL;
10093 he = nextEntry;
10094 }
10095 }
10096 cf->vars.used = 0;
10097 }
 
 
 
10098 cf->next = interp->freeFramesList;
10099 interp->freeFramesList = cf;
 
10100 }
10101
10102
10103 #ifdef JIM_REFERENCES
10104
@@ -10031,21 +10175,16 @@
10175 NULL,
10176 UpdateStringOfReference,
10177 JIM_TYPE_REFERENCES,
10178 };
10179
10180 static void UpdateStringOfReference(struct Jim_Obj *objPtr)
10181 {
 
10182 char buf[JIM_REFERENCE_SPACE + 1];
 
10183
10184 JimFormatReference(buf, objPtr->internalRep.refValue.refPtr, objPtr->internalRep.refValue.id);
10185 JimSetStringBytes(objPtr, buf);
 
 
 
10186 }
10187
10188 static int isrefchar(int c)
10189 {
10190 return (c == '_' || isalnum(c));
@@ -10096,11 +10235,11 @@
10235 he = Jim_FindHashEntry(&interp->references, &value);
10236 if (he == NULL) {
10237 Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr);
10238 return JIM_ERR;
10239 }
10240 refPtr = Jim_GetHashEntryVal(he);
10241
10242 Jim_FreeIntRep(interp, objPtr);
10243 objPtr->typePtr = &referenceObjType;
10244 objPtr->internalRep.refValue.id = value;
10245 objPtr->internalRep.refValue.refPtr = refPtr;
@@ -10279,13 +10418,20 @@
10418 return i;
10419 }
10420
10421 void Jim_FreeInterp(Jim_Interp *i)
10422 {
10423 Jim_CallFrame *cf, *cfx;
10424
10425 Jim_Obj *objPtr, *nextObjPtr;
10426
10427
10428 for (cf = i->framePtr; cf; cf = cfx) {
10429 cfx = cf->parent;
10430 JimFreeCallFrame(i, cf, JIM_FCF_FULL);
10431 }
10432
10433 Jim_DecrRefCount(i, i->emptyObj);
10434 Jim_DecrRefCount(i, i->trueObj);
10435 Jim_DecrRefCount(i, i->falseObj);
10436 Jim_DecrRefCount(i, i->result);
10437 Jim_DecrRefCount(i, i->stackTrace);
@@ -10300,61 +10446,54 @@
10446 #endif
10447 Jim_FreeHashTable(&i->packages);
10448 Jim_Free(i->prngState);
10449 Jim_FreeHashTable(&i->assocData);
10450
10451 #ifdef JIM_MAINTAINER
 
 
 
 
 
10452 if (i->liveList != NULL) {
10453 objPtr = i->liveList;
10454
10455 printf("\n-------------------------------------\n");
10456 printf("Objects still in the free list:\n");
10457 while (objPtr) {
10458 const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string";
10459
10460 if (objPtr->bytes && strlen(objPtr->bytes) > 20) {
10461 printf("%p (%d) %-10s: '%.20s...'\n",
10462 (void *)objPtr, objPtr->refCount, type, objPtr->bytes);
10463 }
10464 else {
10465 printf("%p (%d) %-10s: '%s'\n",
10466 (void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)");
10467 }
10468 if (objPtr->typePtr == &sourceObjType) {
10469 printf("FILE %s LINE %d\n",
10470 Jim_String(objPtr->internalRep.sourceValue.fileNameObj),
10471 objPtr->internalRep.sourceValue.lineNumber);
10472 }
10473 objPtr = objPtr->nextObjPtr;
10474 }
10475 printf("-------------------------------------\n\n");
10476 JimPanic((1, "Live list non empty freeing the interpreter! Leak?"));
10477 }
10478 #endif
10479
10480
10481 objPtr = i->freeList;
10482 while (objPtr) {
10483 nextObjPtr = objPtr->nextObjPtr;
10484 Jim_Free(objPtr);
10485 objPtr = nextObjPtr;
10486 }
10487
10488
10489 for (cf = i->freeFramesList; cf; cf = cfx) {
10490 cfx = cf->next;
10491 if (cf->vars.table)
10492 Jim_FreeHashTable(&cf->vars);
 
10493 Jim_Free(cf);
 
10494 }
 
 
 
10495
10496
10497 Jim_Free(i);
10498 }
10499
@@ -10455,11 +10594,10 @@
10594 interp->addStackTrace = 1;
10595 }
10596 }
10597 }
10598
 
10599 static void JimAppendStackTrace(Jim_Interp *interp, const char *procname,
10600 Jim_Obj *fileNameObj, int linenr)
10601 {
10602 if (strcmp(procname, "unknown") == 0) {
10603 procname = "";
@@ -10513,12 +10651,11 @@
10651 void *Jim_GetAssocData(Jim_Interp *interp, const char *key)
10652 {
10653 Jim_HashEntry *entryPtr = Jim_FindHashEntry(&interp->assocData, key);
10654
10655 if (entryPtr != NULL) {
10656 AssocDataValue *assocEntryPtr = Jim_GetHashEntryVal(entryPtr);
 
10657 return assocEntryPtr->data;
10658 }
10659 return NULL;
10660 }
10661
@@ -10552,20 +10689,44 @@
10689 };
10690
10691
10692 static void UpdateStringOfInt(struct Jim_Obj *objPtr)
10693 {
 
10694 char buf[JIM_INTEGER_SPACE + 1];
10695 jim_wide wideValue = JimWideValue(objPtr);
10696 int pos = 0;
10697
10698 if (wideValue == 0) {
10699 buf[pos++] = '0';
10700 }
10701 else {
10702 char tmp[JIM_INTEGER_SPACE];
10703 int num = 0;
10704 int i;
10705
10706 if (wideValue < 0) {
10707 buf[pos++] = '-';
10708 i = wideValue % 10;
10709 tmp[num++] = (i > 0) ? (10 - i) : -i;
10710 wideValue /= -10;
10711 }
10712
10713 while (wideValue) {
10714 tmp[num++] = wideValue % 10;
10715 wideValue /= 10;
10716 }
10717
10718 for (i = 0; i < num; i++) {
10719 buf[pos++] = '0' + tmp[num - i - 1];
10720 }
10721 }
10722 buf[pos] = 0;
10723
10724 JimSetStringBytes(objPtr, buf);
10725 }
10726
10727 static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
10728 {
10729 jim_wide wideValue;
10730 const char *str;
10731
10732 if (objPtr->typePtr == &coercedDoubleObjType) {
@@ -10653,22 +10814,65 @@
10814 NULL,
10815 UpdateStringOfDouble,
10816 JIM_TYPE_NONE,
10817 };
10818
10819 #ifndef HAVE_ISNAN
10820 #undef isnan
10821 #define isnan(X) ((X) != (X))
10822 #endif
10823 #ifndef HAVE_ISINF
10824 #undef isinf
10825 #define isinf(X) (1.0 / (X) == 0.0)
10826 #endif
10827
10828 static void UpdateStringOfDouble(struct Jim_Obj *objPtr)
10829 {
10830 double value = objPtr->internalRep.doubleValue;
10831
10832 if (isnan(value)) {
10833 JimSetStringBytes(objPtr, "NaN");
10834 return;
10835 }
10836 if (isinf(value)) {
10837 if (value < 0) {
10838 JimSetStringBytes(objPtr, "-Inf");
10839 }
10840 else {
10841 JimSetStringBytes(objPtr, "Inf");
10842 }
10843 return;
10844 }
10845 {
10846 char buf[JIM_DOUBLE_SPACE + 1];
10847 int i;
10848 int len = sprintf(buf, "%.12g", value);
10849
10850
10851 for (i = 0; i < len; i++) {
10852 if (buf[i] == '.' || buf[i] == 'e') {
10853 #if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
10854 char *e = strchr(buf, 'e');
10855 if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
10856
10857 e += 2;
10858 memmove(e, e + 1, len - (e - buf));
10859 }
10860 #endif
10861 break;
10862 }
10863 }
10864 if (buf[i] == '\0') {
10865 buf[i++] = '.';
10866 buf[i++] = '0';
10867 buf[i] = '\0';
10868 }
10869 JimSetStringBytes(objPtr, buf);
10870 }
10871 }
10872
10873 static int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
10874 {
10875 double doubleValue;
10876 jim_wide wideValue;
10877 const char *str;
10878
@@ -10876,15 +11080,15 @@
11080 return JIM_ELESTR_SIMPLE;
11081 }
11082 return JIM_ELESTR_QUOTE;
11083 }
11084
11085 static int BackslashQuoteString(const char *s, int len, char *q)
11086 {
11087 char *p = q;
11088
11089 while (len--) {
11090 switch (*s) {
11091 case ' ':
11092 case '$':
11093 case '"':
11094 case '[':
@@ -10996,11 +11200,11 @@
11200 case JIM_ELESTR_QUOTE:
11201 if (i == 0 && strRep[0] == '#') {
11202 *p++ = '\\';
11203 realLength++;
11204 }
11205 qlen = BackslashQuoteString(strRep, len, p);
11206 p += qlen;
11207 realLength += qlen;
11208 break;
11209 }
11210
@@ -11032,11 +11236,11 @@
11236
11237 if (objPtr->typePtr == &listObjType) {
11238 return JIM_OK;
11239 }
11240
11241 if (Jim_IsDict(objPtr) && objPtr->bytes == NULL) {
11242 Jim_Obj **listObjPtrPtr;
11243 int len;
11244 int i;
11245
11246 listObjPtrPtr = JimDictPairs(objPtr, &len);
@@ -11136,15 +11340,17 @@
11340 Jim_Interp *interp;
11341 enum {
11342 JIM_LSORT_ASCII,
11343 JIM_LSORT_NOCASE,
11344 JIM_LSORT_INTEGER,
11345 JIM_LSORT_REAL,
11346 JIM_LSORT_COMMAND
11347 } type;
11348 int order;
11349 int index;
11350 int indexed;
11351 int unique;
11352 int (*subfn)(Jim_Obj **, Jim_Obj **);
11353 };
11354
11355 static struct lsort_info *sort_info;
11356
@@ -11179,10 +11385,27 @@
11385 longjmp(sort_info->jmpbuf, JIM_ERR);
11386 }
11387
11388 return JimSign(lhs - rhs) * sort_info->order;
11389 }
11390
11391 static int ListSortReal(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
11392 {
11393 double lhs = 0, rhs = 0;
11394
11395 if (Jim_GetDouble(sort_info->interp, *lhsObj, &lhs) != JIM_OK ||
11396 Jim_GetDouble(sort_info->interp, *rhsObj, &rhs) != JIM_OK) {
11397 longjmp(sort_info->jmpbuf, JIM_ERR);
11398 }
11399 if (lhs == rhs) {
11400 return 0;
11401 }
11402 if (lhs > rhs) {
11403 return sort_info->order;
11404 }
11405 return -sort_info->order;
11406 }
11407
11408 static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
11409 {
11410 Jim_Obj *compare_script;
11411 int rc;
@@ -11201,10 +11424,34 @@
11424 }
11425
11426 return JimSign(ret) * sort_info->order;
11427 }
11428
11429 static void ListRemoveDuplicates(Jim_Obj *listObjPtr, int (*comp)(Jim_Obj **lhs, Jim_Obj **rhs))
11430 {
11431 int src;
11432 int dst = 0;
11433 Jim_Obj **ele = listObjPtr->internalRep.listValue.ele;
11434
11435 for (src = 1; src < listObjPtr->internalRep.listValue.len; src++) {
11436 if (comp(&ele[dst], &ele[src]) == 0) {
11437
11438 Jim_DecrRefCount(sort_info->interp, ele[dst]);
11439 }
11440 else {
11441
11442 dst++;
11443 }
11444 ele[dst] = ele[src];
11445 }
11446
11447 ele[++dst] = ele[src];
11448
11449
11450 listObjPtr->internalRep.listValue.len = dst;
11451 }
11452
11453
11454 static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info)
11455 {
11456 struct lsort_info *prev_info;
11457
@@ -11212,11 +11459,11 @@
11459 int (*fn) (Jim_Obj **, Jim_Obj **);
11460 Jim_Obj **vector;
11461 int len;
11462 int rc;
11463
11464 JimPanic((Jim_IsShared(listObjPtr), "ListSortElements called with shared object"));
11465 SetListFromAny(interp, listObjPtr);
11466
11467
11468 prev_info = sort_info;
11469 sort_info = info;
@@ -11231,10 +11478,13 @@
11478 fn = ListSortStringNoCase;
11479 break;
11480 case JIM_LSORT_INTEGER:
11481 fn = ListSortInteger;
11482 break;
11483 case JIM_LSORT_REAL:
11484 fn = ListSortReal;
11485 break;
11486 case JIM_LSORT_COMMAND:
11487 fn = ListSortCommand;
11488 break;
11489 default:
11490 fn = NULL;
@@ -11247,12 +11497,17 @@
11497 fn = ListSortIndexHelper;
11498 }
11499
11500 if ((rc = setjmp(info->jmpbuf)) == 0) {
11501 qsort(vector, len, sizeof(Jim_Obj *), (qsort_comparator *) fn);
11502
11503 if (info->unique && len > 1) {
11504 ListRemoveDuplicates(listObjPtr, fn);
11505 }
11506
11507 Jim_InvalidateStringRep(listObjPtr);
11508 }
 
11509 sort_info = prev_info;
11510
11511 return rc;
11512 }
11513
@@ -11377,11 +11632,11 @@
11632 listPtr->internalRep.listValue.ele[idx] = newObjPtr;
11633 Jim_IncrRefCount(newObjPtr);
11634 return JIM_OK;
11635 }
11636
11637 int Jim_ListSetIndex(Jim_Interp *interp, Jim_Obj *varNamePtr,
11638 Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr)
11639 {
11640 Jim_Obj *varObjPtr, *objPtr, *listObjPtr;
11641 int shared, i, idx;
11642
@@ -11425,14 +11680,11 @@
11680 int i;
11681 int listLen = Jim_ListLength(interp, listObjPtr);
11682 Jim_Obj *resObjPtr = Jim_NewEmptyStringObj(interp);
11683
11684 for (i = 0; i < listLen; ) {
11685 Jim_AppendObj(interp, resObjPtr, Jim_ListGetIndex(interp, listObjPtr, i));
 
 
 
11686 if (++i != listLen) {
11687 Jim_AppendString(interp, resObjPtr, joinStr, joinStrLen);
11688 }
11689 }
11690 return resObjPtr;
@@ -11458,43 +11710,42 @@
11710 int len = 0, objLen;
11711 char *bytes, *p;
11712
11713
11714 for (i = 0; i < objc; i++) {
11715 len += Jim_Length(objv[i]);
 
11716 }
11717 if (objc)
11718 len += objc - 1;
11719
11720 p = bytes = Jim_Alloc(len + 1);
11721 for (i = 0; i < objc; i++) {
11722 const char *s = Jim_GetString(objv[i], &objLen);
11723
11724
11725 while (objLen && isspace(UCHAR(*s))) {
11726 s++;
11727 objLen--;
11728 len--;
11729 }
11730
11731 while (objLen && isspace(UCHAR(s[objLen - 1]))) {
 
11732
11733 if (objLen > 1 && s[objLen - 2] == '\\') {
11734 break;
11735 }
11736 objLen--;
11737 len--;
11738 }
11739 memcpy(p, s, objLen);
11740 p += objLen;
11741 if (i + 1 != objc) {
11742 if (objLen)
11743 *p++ = ' ';
11744 else {
11745 len--;
11746 }
11747 }
11748 }
11749 *p = '\0';
11750 return Jim_NewStringObjNoAlloc(interp, bytes, len);
11751 }
@@ -11534,20 +11785,26 @@
11785
11786 static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2)
11787 {
11788 return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2);
11789 }
11790
11791 static void *JimObjectHTKeyValDup(void *privdata, const void *val)
11792 {
11793 Jim_IncrRefCount((Jim_Obj *)val);
11794 return (void *)val;
11795 }
11796
11797 static void JimObjectHTKeyValDestructor(void *interp, void *val)
11798 {
11799 Jim_DecrRefCount(interp, (Jim_Obj *)val);
11800 }
11801
11802 static const Jim_HashTableType JimDictHashTableType = {
11803 JimObjectHTHashFunction,
11804 JimObjectHTKeyValDup,
11805 JimObjectHTKeyValDup,
11806 JimObjectHTKeyCompare,
11807 JimObjectHTKeyValDestructor,
11808 JimObjectHTKeyValDestructor
11809 };
11810
@@ -11580,16 +11837,11 @@
11837 if (ht->size != 0)
11838 Jim_ExpandHashTable(dupHt, ht->size);
11839
11840 JimInitHashTableIterator(ht, &htiter);
11841 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
11842 Jim_AddHashEntry(dupHt, he->key, he->u.val);
 
 
 
 
 
11843 }
11844
11845 dupPtr->internalRep.ptr = dupHt;
11846 dupPtr->typePtr = &dictObjType;
11847 }
@@ -11607,12 +11859,12 @@
11859
11860 objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
11861 JimInitHashTableIterator(ht, &htiter);
11862 i = 0;
11863 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
11864 objv[i++] = Jim_GetHashEntryKey(he);
11865 objv[i++] = Jim_GetHashEntryVal(he);
11866 }
11867 *len = i;
11868 return objv;
11869 }
11870
@@ -11620,10 +11872,11 @@
11872 {
11873
11874 int len;
11875 Jim_Obj **objv = JimDictPairs(objPtr, &len);
11876
11877
11878 JimMakeListStringRep(objPtr, objv, len);
11879
11880 Jim_Free(objv);
11881 }
11882
@@ -11633,11 +11886,13 @@
11886
11887 if (objPtr->typePtr == &dictObjType) {
11888 return JIM_OK;
11889 }
11890
11891 if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) {
11892 Jim_String(objPtr);
11893 }
11894
11895
11896 listlen = Jim_ListLength(interp, objPtr);
11897 if (listlen % 2) {
11898 Jim_SetResultString(interp, "missing value to go with key", -1);
@@ -11650,28 +11905,14 @@
11905
11906 ht = Jim_Alloc(sizeof(*ht));
11907 Jim_InitHashTable(ht, &JimDictHashTableType, interp);
11908
11909 for (i = 0; i < listlen; i += 2) {
11910 Jim_Obj *keyObjPtr = Jim_ListGetIndex(interp, objPtr, i);
11911 Jim_Obj *valObjPtr = Jim_ListGetIndex(interp, objPtr, i + 1);
11912
11913 Jim_ReplaceHashEntry(ht, keyObjPtr, valObjPtr);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11914 }
11915
11916 Jim_FreeIntRep(interp, objPtr);
11917 objPtr->typePtr = &dictObjType;
11918 objPtr->internalRep.ptr = ht;
@@ -11688,31 +11929,23 @@
11929 Jim_HashTable *ht = objPtr->internalRep.ptr;
11930
11931 if (valueObjPtr == NULL) {
11932 return Jim_DeleteHashEntry(ht, keyObjPtr);
11933 }
11934 Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr);
 
 
 
 
 
11935 return JIM_OK;
11936 }
11937
11938 int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
11939 Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
11940 {
 
 
11941 JimPanic((Jim_IsShared(objPtr), "Jim_DictAddElement called with shared object"));
11942 if (SetDictFromAny(interp, objPtr) != JIM_OK) {
11943 return JIM_ERR;
11944 }
 
11945 Jim_InvalidateStringRep(objPtr);
11946 return DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr);
11947 }
11948
11949 Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len)
11950 {
11951 Jim_Obj *objPtr;
@@ -11839,10 +12072,11 @@
12072 }
12073 objPtr = Jim_NewDictObj(interp, NULL, 0);
12074 DictAddElement(interp, dictObjPtr, keyv[i], objPtr);
12075 }
12076 }
12077
12078 Jim_InvalidateStringRep(objPtr);
12079 Jim_InvalidateStringRep(varObjPtr);
12080 if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
12081 goto err;
12082 }
@@ -11864,28 +12098,29 @@
12098 NULL,
12099 UpdateStringOfIndex,
12100 JIM_TYPE_NONE,
12101 };
12102
12103 static void UpdateStringOfIndex(struct Jim_Obj *objPtr)
12104 {
12105 if (objPtr->internalRep.intValue == -1) {
12106 JimSetStringBytes(objPtr, "end");
12107 }
 
 
 
 
12108 else {
12109 char buf[JIM_INTEGER_SPACE + 1];
12110 if (objPtr->internalRep.intValue >= 0) {
12111 sprintf(buf, "%d", objPtr->internalRep.intValue);
12112 }
12113 else {
12114
12115 sprintf(buf, "end%d", objPtr->internalRep.intValue + 1);
12116 }
12117 JimSetStringBytes(objPtr, buf);
12118 }
 
 
 
12119 }
12120
12121 static int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
12122 {
12123 int idx, end = 0;
12124 const char *str;
12125 char *endptr;
12126
@@ -11953,14 +12188,17 @@
12188 {
12189
12190 if (objPtr->typePtr == &intObjType) {
12191 jim_wide val = JimWideValue(objPtr);
12192
12193 if (val < 0)
12194 *indexPtr = -INT_MAX;
12195 else if (val > INT_MAX)
12196 *indexPtr = INT_MAX;
12197 else
12198 *indexPtr = (int)val;
12199 return JIM_OK;
12200 }
12201 if (objPtr->typePtr != &indexObjType && SetIndexFromAny(interp, objPtr) == JIM_ERR)
12202 return JIM_ERR;
12203 *indexPtr = objPtr->internalRep.intValue;
12204 return JIM_OK;
@@ -11980,12 +12218,10 @@
12218 NULL
12219 };
12220
12221 #define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes))
12222
 
 
12223 static const Jim_ObjType returnCodeObjType = {
12224 "return-code",
12225 NULL,
12226 NULL,
12227 NULL,
@@ -12000,11 +12236,11 @@
12236 else {
12237 return jimReturnCodes[code];
12238 }
12239 }
12240
12241 static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
12242 {
12243 int returnCode;
12244 jim_wide wideValue;
12245
12246
@@ -12152,24 +12388,21 @@
12388 return e->stack[--e->stacklen];
12389 }
12390
12391 static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e)
12392 {
12393 int intresult = 1;
12394 int rc = JIM_OK;
12395 Jim_Obj *A = ExprPop(e);
12396 double dA, dC = 0;
12397 jim_wide wA, wC = 0;
12398
12399 if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) {
 
 
12400 switch (e->opcode) {
12401 case JIM_EXPROP_FUNC_INT:
 
 
12402 case JIM_EXPROP_FUNC_ROUND:
12403 case JIM_EXPROP_UNARYPLUS:
12404 wC = wA;
12405 break;
12406 case JIM_EXPROP_FUNC_DOUBLE:
12407 dC = wA;
12408 intresult = 0;
@@ -12178,13 +12411,10 @@
12411 wC = wA >= 0 ? wA : -wA;
12412 break;
12413 case JIM_EXPROP_UNARYMINUS:
12414 wC = -wA;
12415 break;
 
 
 
12416 case JIM_EXPROP_NOT:
12417 wC = !wA;
12418 break;
12419 default:
12420 abort();
@@ -12192,31 +12422,29 @@
12422 }
12423 else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) {
12424 switch (e->opcode) {
12425 case JIM_EXPROP_FUNC_INT:
12426 wC = dA;
 
12427 break;
12428 case JIM_EXPROP_FUNC_ROUND:
12429 wC = dA < 0 ? (dA - 0.5) : (dA + 0.5);
 
12430 break;
12431 case JIM_EXPROP_FUNC_DOUBLE:
12432 case JIM_EXPROP_UNARYPLUS:
12433 dC = dA;
12434 intresult = 0;
12435 break;
12436 case JIM_EXPROP_FUNC_ABS:
12437 dC = dA >= 0 ? dA : -dA;
12438 intresult = 0;
12439 break;
12440 case JIM_EXPROP_UNARYMINUS:
12441 dC = -dA;
12442 intresult = 0;
 
 
12443 break;
12444 case JIM_EXPROP_NOT:
12445 wC = !dA;
 
12446 break;
12447 default:
12448 abort();
12449 }
12450 }
@@ -12427,11 +12655,11 @@
12655
12656
12657
12658 static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
12659 {
12660 int intresult = 1;
12661 int rc = JIM_OK;
12662 double dA, dB, dC = 0;
12663 jim_wide wA, wB, wC = 0;
12664
12665 Jim_Obj *B = ExprPop(e);
@@ -12441,12 +12669,10 @@
12669 (B->typePtr != &doubleObjType || B->bytes) &&
12670 JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) {
12671
12672
12673
 
 
12674 switch (e->opcode) {
12675 case JIM_EXPROP_POW:
12676 case JIM_EXPROP_FUNC_POW:
12677 wC = JimPowWide(wA, wB);
12678 break;
@@ -12496,10 +12722,11 @@
12722 default:
12723 abort();
12724 }
12725 }
12726 else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) {
12727 intresult = 0;
12728 switch (e->opcode) {
12729 case JIM_EXPROP_POW:
12730 case JIM_EXPROP_FUNC_POW:
12731 #ifdef JIM_MATH_FUNCTIONS
12732 dC = pow(dA, dB);
@@ -12561,12 +12788,10 @@
12788
12789
12790
12791 int i = Jim_StringCompareObj(interp, A, B, 0);
12792
 
 
12793 switch (e->opcode) {
12794 case JIM_EXPROP_LT:
12795 wC = i < 0;
12796 break;
12797 case JIM_EXPROP_GT:
@@ -12610,15 +12835,11 @@
12835 int listlen;
12836 int i;
12837
12838 listlen = Jim_ListLength(interp, listObjPtr);
12839 for (i = 0; i < listlen; i++) {
12840 if (Jim_StringEqObj(Jim_ListGetIndex(interp, listObjPtr, i), valObj)) {
 
 
 
 
12841 return 1;
12842 }
12843 }
12844 return 0;
12845 }
@@ -12630,23 +12851,16 @@
12851
12852 jim_wide wC;
12853
12854 switch (e->opcode) {
12855 case JIM_EXPROP_STREQ:
12856 case JIM_EXPROP_STRNE:
12857 wC = Jim_StringEqObj(A, B);
12858 if (e->opcode == JIM_EXPROP_STRNE) {
12859 wC = !wC;
 
 
 
 
 
 
12860 }
12861 break;
 
12862 case JIM_EXPROP_STRIN:
12863 wC = JimSearchList(interp, B, A);
12864 break;
12865 case JIM_EXPROP_STRNI:
12866 wC = !JimSearchList(interp, B, A);
@@ -12818,96 +13032,98 @@
13032 LAZY_OP,
13033 LAZY_LEFT,
13034 LAZY_RIGHT
13035 };
13036
13037 #define OPRINIT(N, P, A, F) {N, F, P, A, LAZY_NONE, sizeof(N) - 1}
13038 #define OPRINIT_LAZY(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1}
13039
13040 static const struct Jim_ExprOperator Jim_ExprOperators[] = {
13041 OPRINIT("*", 110, 2, JimExprOpBin),
13042 OPRINIT("/", 110, 2, JimExprOpBin),
13043 OPRINIT("%", 110, 2, JimExprOpIntBin),
13044
13045 OPRINIT("-", 100, 2, JimExprOpBin),
13046 OPRINIT("+", 100, 2, JimExprOpBin),
13047
13048 OPRINIT("<<", 90, 2, JimExprOpIntBin),
13049 OPRINIT(">>", 90, 2, JimExprOpIntBin),
13050
13051 OPRINIT("<<<", 90, 2, JimExprOpIntBin),
13052 OPRINIT(">>>", 90, 2, JimExprOpIntBin),
13053
13054 OPRINIT("<", 80, 2, JimExprOpBin),
13055 OPRINIT(">", 80, 2, JimExprOpBin),
13056 OPRINIT("<=", 80, 2, JimExprOpBin),
13057 OPRINIT(">=", 80, 2, JimExprOpBin),
13058
13059 OPRINIT("==", 70, 2, JimExprOpBin),
13060 OPRINIT("!=", 70, 2, JimExprOpBin),
13061
13062 OPRINIT("&", 50, 2, JimExprOpIntBin),
13063 OPRINIT("^", 49, 2, JimExprOpIntBin),
13064 OPRINIT("|", 48, 2, JimExprOpIntBin),
13065
13066 OPRINIT_LAZY("&&", 10, 2, NULL, LAZY_OP),
13067 OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT),
13068 OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT),
13069
13070 OPRINIT_LAZY("||", 9, 2, NULL, LAZY_OP),
13071 OPRINIT_LAZY(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT),
13072 OPRINIT_LAZY(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT),
13073
13074 OPRINIT_LAZY("?", 5, 2, JimExprOpNull, LAZY_OP),
13075 OPRINIT_LAZY(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT),
13076 OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
13077
13078 OPRINIT_LAZY(":", 5, 2, JimExprOpNull, LAZY_OP),
13079 OPRINIT_LAZY(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT),
13080 OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
13081
13082 OPRINIT("**", 250, 2, JimExprOpBin),
13083
13084 OPRINIT("eq", 60, 2, JimExprOpStrBin),
13085 OPRINIT("ne", 60, 2, JimExprOpStrBin),
13086
13087 OPRINIT("in", 55, 2, JimExprOpStrBin),
13088 OPRINIT("ni", 55, 2, JimExprOpStrBin),
13089
13090 OPRINIT("!", 150, 1, JimExprOpNumUnary),
13091 OPRINIT("~", 150, 1, JimExprOpIntUnary),
13092 OPRINIT(NULL, 150, 1, JimExprOpNumUnary),
13093 OPRINIT(NULL, 150, 1, JimExprOpNumUnary),
13094
13095
13096
13097 OPRINIT("int", 200, 1, JimExprOpNumUnary),
13098 OPRINIT("abs", 200, 1, JimExprOpNumUnary),
13099 OPRINIT("double", 200, 1, JimExprOpNumUnary),
13100 OPRINIT("round", 200, 1, JimExprOpNumUnary),
13101 OPRINIT("rand", 200, 0, JimExprOpNone),
13102 OPRINIT("srand", 200, 1, JimExprOpIntUnary),
13103
13104 #ifdef JIM_MATH_FUNCTIONS
13105 OPRINIT("sin", 200, 1, JimExprOpDoubleUnary),
13106 OPRINIT("cos", 200, 1, JimExprOpDoubleUnary),
13107 OPRINIT("tan", 200, 1, JimExprOpDoubleUnary),
13108 OPRINIT("asin", 200, 1, JimExprOpDoubleUnary),
13109 OPRINIT("acos", 200, 1, JimExprOpDoubleUnary),
13110 OPRINIT("atan", 200, 1, JimExprOpDoubleUnary),
13111 OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary),
13112 OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary),
13113 OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary),
13114 OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary),
13115 OPRINIT("floor", 200, 1, JimExprOpDoubleUnary),
13116 OPRINIT("exp", 200, 1, JimExprOpDoubleUnary),
13117 OPRINIT("log", 200, 1, JimExprOpDoubleUnary),
13118 OPRINIT("log10", 200, 1, JimExprOpDoubleUnary),
13119 OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary),
13120 OPRINIT("pow", 200, 2, JimExprOpBin),
13121 #endif
13122 };
13123 #undef OPRINIT
13124 #undef OPRINIT_LAZY
13125
13126 #define JIM_EXPR_OPERATORS_NUM \
13127 (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))
13128
13129 static int JimParseExpression(struct JimParserCtx *pc)
@@ -12919,13 +13135,16 @@
13135 }
13136 pc->p++;
13137 pc->len--;
13138 }
13139
13140
13141 pc->tline = pc->linenr;
13142 pc->tstart = pc->p;
13143
13144 if (pc->len == 0) {
13145 pc->tend = pc->p;
 
13146 pc->tt = JIM_TT_EOL;
13147 pc->eof = 1;
13148 return JIM_OK;
13149 }
13150 switch (*(pc->p)) {
@@ -12936,12 +13155,11 @@
13155 pc->tt = JIM_TT_SUBEXPR_END;
13156 goto singlechar;
13157 case ',':
13158 pc->tt = JIM_TT_SUBEXPR_COMMA;
13159 singlechar:
13160 pc->tend = pc->p;
 
13161 pc->p++;
13162 pc->len--;
13163 break;
13164 case '[':
13165 return JimParseCmd(pc);
@@ -12987,82 +13205,44 @@
13205 return JIM_OK;
13206 }
13207
13208 static int JimParseExprNumber(struct JimParserCtx *pc)
13209 {
13210 char *end;
 
13211
13212
13213 pc->tt = JIM_TT_EXPR_INT;
13214
13215 jim_strtoull(pc->p, (char **)&pc->p);
13216
13217 if (strchr("eENnIi.", *pc->p) || pc->p == pc->tstart) {
13218 if (strtod(pc->tstart, &end)) { }
13219 if (end == pc->tstart)
13220 return JIM_ERR;
13221 if (end > pc->p) {
13222
13223 pc->tt = JIM_TT_EXPR_DOUBLE;
13224 pc->p = end;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13225 }
13226 }
13227 pc->tend = pc->p - 1;
13228 pc->len -= (pc->p - pc->tstart);
13229 return JIM_OK;
13230 }
13231
13232 static int JimParseExprIrrational(struct JimParserCtx *pc)
13233 {
13234 const char *irrationals[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL };
13235 int i;
13236
13237 for (i = 0; irrationals[i]; i++) {
13238 const char *irr = irrationals[i];
13239
13240 if (strncmp(irr, pc->p, 3) == 0) {
13241 pc->p += 3;
13242 pc->len -= 3;
13243 pc->tend = pc->p - 1;
 
 
13244 pc->tt = JIM_TT_EXPR_DOUBLE;
13245 return JIM_OK;
13246 }
13247 }
13248 return JIM_ERR;
@@ -13102,15 +13282,13 @@
13282 }
13283 if (*p != '(') {
13284 return JIM_ERR;
13285 }
13286 }
 
13287 pc->tend = pc->p + bestLen - 1;
13288 pc->p += bestLen;
13289 pc->len -= bestLen;
 
13290
13291 pc->tt = bestIdx;
13292 return JIM_OK;
13293 }
13294
@@ -13608,17 +13786,23 @@
13786 }
13787
13788 #ifdef DEBUG_SHOW_EXPR_TOKENS
13789 {
13790 int i;
13791 printf("==== Expr Tokens (%s) ====\n", Jim_String(fileNameObj));
13792 for (i = 0; i < tokenlist.count; i++) {
13793 printf("[%2d]@%d %s '%.*s'\n", i, tokenlist.list[i].line, jim_tt_name(tokenlist.list[i].type),
13794 tokenlist.list[i].len, tokenlist.list[i].token);
13795 }
13796 }
13797 #endif
13798
13799 if (JimParseCheckMissing(interp, parser.missing.ch) == JIM_ERR) {
13800 ScriptTokenListFree(&tokenlist);
13801 Jim_DecrRefCount(interp, fileNameObj);
13802 return JIM_ERR;
13803 }
13804
13805
13806 expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj);
13807
13808
@@ -13665,10 +13849,24 @@
13849 return NULL;
13850 }
13851 }
13852 return (ExprByteCode *) Jim_GetIntRepPtr(objPtr);
13853 }
13854
13855 #ifdef JIM_OPTIMIZATION
13856 static Jim_Obj *JimExprIntValOrVar(Jim_Interp *interp, const ScriptToken *token)
13857 {
13858 if (token->type == JIM_TT_EXPR_INT)
13859 return token->objPtr;
13860 else if (token->type == JIM_TT_VAR)
13861 return Jim_GetVariable(interp, token->objPtr, JIM_NONE);
13862 else if (token->type == JIM_TT_DICTSUGAR)
13863 return JimExpandDictSugar(interp, token->objPtr);
13864 else
13865 return NULL;
13866 }
13867 #endif
13868
13869 #define JIM_EE_STATICSTACK_LEN 10
13870
13871 int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr)
13872 {
@@ -13688,102 +13886,69 @@
13886 Jim_Obj *objPtr;
13887
13888
13889 switch (expr->len) {
13890 case 1:
13891 objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
13892 if (objPtr) {
13893 Jim_IncrRefCount(objPtr);
13894 *exprResultPtrPtr = objPtr;
13895 return JIM_OK;
 
 
 
 
 
 
 
13896 }
13897 break;
13898
13899 case 2:
13900 if (expr->token[1].type == JIM_EXPROP_NOT) {
13901 objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
13902
13903 if (objPtr && JimIsWide(objPtr)) {
13904 *exprResultPtrPtr = JimWideValue(objPtr) ? interp->falseObj : interp->trueObj;
 
 
13905 Jim_IncrRefCount(*exprResultPtrPtr);
13906 return JIM_OK;
13907 }
13908 }
13909 break;
13910
13911 case 3:
13912 objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
13913 if (objPtr && JimIsWide(objPtr)) {
13914 Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, &expr->token[1]);
13915 if (objPtr2 && JimIsWide(objPtr2)) {
13916 jim_wide wideValueA = JimWideValue(objPtr);
13917 jim_wide wideValueB = JimWideValue(objPtr2);
13918 int cmpRes;
13919 switch (expr->token[2].type) {
13920 case JIM_EXPROP_LT:
13921 cmpRes = wideValueA < wideValueB;
13922 break;
13923 case JIM_EXPROP_LTE:
13924 cmpRes = wideValueA <= wideValueB;
13925 break;
13926 case JIM_EXPROP_GT:
13927 cmpRes = wideValueA > wideValueB;
13928 break;
13929 case JIM_EXPROP_GTE:
13930 cmpRes = wideValueA >= wideValueB;
13931 break;
13932 case JIM_EXPROP_NUMEQ:
13933 cmpRes = wideValueA == wideValueB;
13934 break;
13935 case JIM_EXPROP_NUMNE:
13936 cmpRes = wideValueA != wideValueB;
13937 break;
13938 default:
13939 goto noopt;
13940 }
13941 *exprResultPtrPtr = cmpRes ? interp->trueObj : interp->falseObj;
13942 Jim_IncrRefCount(*exprResultPtrPtr);
13943 return JIM_OK;
13944 }
13945 }
13946 break;
13947 }
13948 }
13949 noopt:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13950 #endif
13951
13952 expr->inUse++;
13953
13954
@@ -13952,16 +14117,13 @@
14117 memcpy(newVec, srcPtr->internalRep.ptr, size);
14118 dupPtr->internalRep.ptr = newVec;
14119 dupPtr->typePtr = &scanFmtStringObjType;
14120 }
14121
14122 static void UpdateStringOfScanFmt(Jim_Obj *objPtr)
14123 {
14124 JimSetStringBytes(objPtr, ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep);
 
 
 
14125 }
14126
14127
14128 static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
14129 {
@@ -14171,11 +14333,10 @@
14333 Jim_Obj *tmpObj = NULL;
14334
14335
14336 *valObjPtr = 0;
14337 if (descr->prefix) {
 
14338 for (i = 0; pos < strLen && descr->prefix[i]; ++i) {
14339
14340 if (isspace(UCHAR(descr->prefix[i])))
14341 while (pos < strLen && isspace(UCHAR(str[pos])))
14342 ++pos;
@@ -14512,34 +14673,55 @@
14673 }
14674
14675 static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
14676 {
14677 int retcode;
14678 Jim_Cmd *cmdPtr;
14679
14680 #if 0
14681 printf("invoke");
14682 int j;
14683 for (j = 0; j < objc; j++) {
14684 printf(" '%s'", Jim_String(objv[j]));
14685 }
14686 printf("\n");
14687 #endif
14688
14689 if (interp->framePtr->tailcallCmd) {
14690
14691 cmdPtr = interp->framePtr->tailcallCmd;
14692 interp->framePtr->tailcallCmd = NULL;
14693 }
14694 else {
14695 cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
14696 if (cmdPtr == NULL) {
14697 return JimUnknown(interp, objc, objv);
14698 }
14699 JimIncrCmdRefCount(cmdPtr);
14700 }
14701
14702 if (interp->evalDepth == interp->maxEvalDepth) {
14703 Jim_SetResultString(interp, "Infinite eval recursion", -1);
14704 retcode = JIM_ERR;
14705 goto out;
14706 }
14707 interp->evalDepth++;
14708
14709
 
14710 Jim_SetEmptyResult(interp);
14711 if (cmdPtr->isproc) {
14712 retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
14713 }
14714 else {
14715 interp->cmdPrivData = cmdPtr->u.native.privData;
14716 retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
14717 }
 
14718 interp->evalDepth--;
14719
14720 out:
14721 JimDecrCmdRefCount(interp, cmdPtr);
14722
14723 return retcode;
14724 }
14725
14726 int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
14727 {
@@ -14717,10 +14899,15 @@
14899 objPtr->typePtr = &interpolatedObjType;
14900 objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr;
14901 objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2];
14902 Jim_IncrRefCount(intv[2]);
14903 }
14904 else if (tokens && intv[0] && intv[0]->typePtr == &sourceObjType) {
14905
14906 JimSetSourceInfo(interp, objPtr, intv[0]->internalRep.sourceValue.fileNameObj, intv[0]->internalRep.sourceValue.lineNumber);
14907 }
14908
14909
14910 s = objPtr->bytes = Jim_Alloc(totlen + 1);
14911 objPtr->length = totlen;
14912 for (i = 0; i < tokens; i++) {
14913 if (intv[i]) {
@@ -14772,10 +14959,14 @@
14959 return JimEvalObjList(interp, scriptObjPtr);
14960 }
14961
14962 Jim_IncrRefCount(scriptObjPtr);
14963 script = Jim_GetScript(interp, scriptObjPtr);
14964 if (script == NULL) {
14965 Jim_DecrRefCount(interp, scriptObjPtr);
14966 return JIM_ERR;
14967 }
14968
14969 Jim_SetEmptyResult(interp);
14970
14971 token = script->token;
14972
@@ -15046,26 +15237,20 @@
15237 retcode = Jim_EvalObj(interp, scriptObj);
15238 }
15239
15240
15241 interp->framePtr = interp->framePtr->parent;
15242 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
 
 
 
 
 
15243
15244 return retcode;
15245 }
15246 #endif
15247
15248 static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv)
15249 {
15250 Jim_CallFrame *callFramePtr;
15251 int i, d, retcode, optargs;
 
15252 ScriptObj *script;
15253
15254
15255 if (argc - 1 < cmd->u.proc.reqArity ||
15256 (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) {
@@ -15145,37 +15330,42 @@
15330
15331
15332 retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr);
15333
15334 badargset:
15335
15336
 
 
 
 
15337 interp->framePtr = interp->framePtr->parent;
15338 JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
15339
15340 if (interp->framePtr->tailcallObj) {
15341
15342 if (interp->framePtr->tailcall++ == 0) {
15343
15344 do {
15345 Jim_Obj *tailcallObj = interp->framePtr->tailcallObj;
15346
15347 interp->framePtr->tailcallObj = NULL;
15348
15349 if (retcode == JIM_EVAL) {
15350 retcode = Jim_EvalObjList(interp, tailcallObj);
15351 if (retcode == JIM_RETURN) {
15352 interp->returnLevel++;
15353 }
15354 }
15355 Jim_DecrRefCount(interp, tailcallObj);
15356 } while (interp->framePtr->tailcallObj);
15357
15358
15359 if (interp->framePtr->tailcallCmd) {
15360 JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd);
15361 interp->framePtr->tailcallCmd = NULL;
15362 }
15363 }
15364 interp->framePtr->tailcall--;
15365 }
15366
15367
15368 if (retcode == JIM_RETURN) {
15369 if (--interp->returnLevel <= 0) {
15370 retcode = interp->returnCode;
15371 interp->returnCode = JIM_OK;
@@ -15187,13 +15377,10 @@
15377 Jim_DecrRefCount(interp, interp->errorProc);
15378 interp->errorProc = argv[0];
15379 Jim_IncrRefCount(interp->errorProc);
15380 }
15381
 
 
 
15382 return retcode;
15383 }
15384
15385 int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script)
15386 {
@@ -15261,11 +15448,10 @@
15448 Jim_Obj *scriptObjPtr;
15449 Jim_Obj *prevScriptObj;
15450 struct stat sb;
15451 int retcode;
15452 int readlen;
 
15453
15454 if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) {
15455 Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno));
15456 return JIM_ERR;
15457 }
@@ -15288,31 +15474,13 @@
15474 scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen);
15475 JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1);
15476 Jim_IncrRefCount(scriptObjPtr);
15477
15478
15479 if (Jim_GetScript(interp, scriptObjPtr) == NULL) {
15480
15481 JimAddErrorToStack(interp, JIM_ERR, (ScriptObj *)Jim_GetIntRepPtr(scriptObjPtr));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15482 Jim_DecrRefCount(interp, scriptObjPtr);
15483 return JIM_ERR;
15484 }
15485
15486 prevScriptObj = interp->currentScriptObj;
@@ -15475,11 +15643,11 @@
15643 }
15644
15645 typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr,
15646 Jim_HashEntry *he, int type);
15647
15648 #define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL)
15649
15650 static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
15651 JimHashtableIteratorCallbackType *callback, int type)
15652 {
15653 Jim_HashEntry *he;
@@ -15510,11 +15678,11 @@
15678 #define JIM_CMDLIST_CHANNELS 2
15679
15680 static void JimCommandMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
15681 Jim_HashEntry *he, int type)
15682 {
15683 Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he);
15684 Jim_Obj *objPtr;
15685
15686 if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) {
15687
15688 return;
@@ -15543,11 +15711,11 @@
15711 #define JIM_VARLIST_VALUES 0x1000
15712
15713 static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
15714 Jim_HashEntry *he, int type)
15715 {
15716 Jim_Var *varPtr = Jim_GetHashEntryVal(he);
15717
15718 if (type != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) {
15719 Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1));
15720 if (type & JIM_VARLIST_VALUES) {
15721 Jim_ListAppendElement(interp, listObjPtr, varPtr->objPtr);
@@ -15865,11 +16033,11 @@
16033
16034 expr = JimGetExpression(interp, argv[2]);
16035 incrScript = Jim_GetScript(interp, argv[3]);
16036
16037
16038 if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) {
16039 goto evalstart;
16040 }
16041
16042 if (incrScript->token[1].type != JIM_TT_ESC ||
16043 expr->token[0].type != JIM_TT_VAR ||
@@ -16088,11 +16256,11 @@
16256 }
16257
16258
16259 static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap)
16260 {
16261 int result = JIM_OK;
16262 int i, numargs;
16263 Jim_ListIter twoiters[2];
16264 Jim_ListIter *iters;
16265 Jim_Obj *script;
16266 Jim_Obj *resultObj;
@@ -16111,13 +16279,16 @@
16279 iters = Jim_Alloc(numargs * sizeof(*iters));
16280 }
16281 for (i = 0; i < numargs; i++) {
16282 JimListIterInit(&iters[i], argv[i + 1]);
16283 if (i % 2 == 0 && JimListIterDone(interp, &iters[i])) {
16284 result = JIM_ERR;
 
16285 }
16286 }
16287 if (result != JIM_OK) {
16288 Jim_SetResultString(interp, "foreach varlist is empty", -1);
16289 return result;
16290 }
16291
16292 if (doMap) {
16293 resultObj = Jim_NewListObj(interp, NULL, 0);
16294 }
@@ -16430,12 +16601,12 @@
16601 {
16602 Jim_Obj *objPtr, *listObjPtr;
16603 int i;
16604 int idx;
16605
16606 if (argc < 2) {
16607 Jim_WrongNumArgs(interp, 1, argv, "list ?index ...?");
16608 return JIM_ERR;
16609 }
16610 objPtr = argv[1];
16611 Jim_IncrRefCount(objPtr);
16612 for (i = 2; i < argc; i++) {
@@ -16547,14 +16718,13 @@
16718 Jim_IncrRefCount(commandObj);
16719 }
16720
16721 listlen = Jim_ListLength(interp, argv[0]);
16722 for (i = 0; i < listlen; i++) {
 
16723 int eq = 0;
16724 Jim_Obj *objPtr = Jim_ListGetIndex(interp, argv[0], i);
16725
 
16726 switch (opt_match) {
16727 case OPT_EXACT:
16728 eq = Jim_StringCompareObj(interp, argv[1], objPtr, opt_nocase) == 0;
16729 break;
16730
@@ -16744,29 +16914,27 @@
16914 if (argc < 3) {
16915 Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal");
16916 return JIM_ERR;
16917 }
16918 else if (argc == 3) {
16919
16920 if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
16921 return JIM_ERR;
16922 Jim_SetResult(interp, argv[2]);
16923 return JIM_OK;
16924 }
16925 return Jim_ListSetIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1]);
 
 
 
16926 }
16927
16928
16929 static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[])
16930 {
16931 static const char * const options[] = {
16932 "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-real", "-index", "-unique", NULL
16933 };
16934 enum
16935 { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE };
16936 Jim_Obj *resObj;
16937 int i;
16938 int retCode;
16939
16940 struct lsort_info info;
@@ -16777,17 +16945,18 @@
16945 }
16946
16947 info.type = JIM_LSORT_ASCII;
16948 info.order = 1;
16949 info.indexed = 0;
16950 info.unique = 0;
16951 info.command = NULL;
16952 info.interp = interp;
16953
16954 for (i = 1; i < (argc - 1); i++) {
16955 int option;
16956
16957 if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ENUM_ABBREV | JIM_ERRMSG)
16958 != JIM_OK)
16959 return JIM_ERR;
16960 switch (option) {
16961 case OPT_ASCII:
16962 info.type = JIM_LSORT_ASCII;
@@ -16796,16 +16965,22 @@
16965 info.type = JIM_LSORT_NOCASE;
16966 break;
16967 case OPT_INTEGER:
16968 info.type = JIM_LSORT_INTEGER;
16969 break;
16970 case OPT_REAL:
16971 info.type = JIM_LSORT_REAL;
16972 break;
16973 case OPT_INCREASING:
16974 info.order = 1;
16975 break;
16976 case OPT_DECREASING:
16977 info.order = -1;
16978 break;
16979 case OPT_UNIQUE:
16980 info.unique = 1;
16981 break;
16982 case OPT_COMMAND:
16983 if (i >= (argc - 2)) {
16984 Jim_SetResultString(interp, "\"-command\" option must be followed by comparison command", -1);
16985 return JIM_ERR;
16986 }
@@ -16915,20 +17090,20 @@
17090 static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17091 {
17092 if (argc >= 2) {
17093 int retcode;
17094 Jim_CallFrame *savedCallFrame, *targetCallFrame;
17095 int savedTailcall;
17096 const char *str;
17097
17098
17099 savedCallFrame = interp->framePtr;
17100
17101
17102 str = Jim_String(argv[1]);
17103 if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') {
17104 targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
17105 argc--;
17106 argv++;
17107 }
17108 else {
17109 targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL);
@@ -16935,25 +17110,25 @@
17110 }
17111 if (targetCallFrame == NULL) {
17112 return JIM_ERR;
17113 }
17114 if (argc < 2) {
17115 Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?");
 
17116 return JIM_ERR;
17117 }
17118
17119 interp->framePtr = targetCallFrame;
17120
17121 savedTailcall = interp->framePtr->tailcall;
17122 interp->framePtr->tailcall = 0;
17123 if (argc == 2) {
17124 retcode = Jim_EvalObj(interp, argv[1]);
17125 }
17126 else {
17127 retcode = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
 
 
 
17128 }
17129 interp->framePtr->tailcall = savedTailcall;
17130 interp->framePtr = savedCallFrame;
17131 return retcode;
17132 }
17133 else {
17134 Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
@@ -17064,12 +17239,39 @@
17239 }
17240
17241
17242 static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17243 {
17244 if (interp->framePtr->level == 0) {
17245 Jim_SetResultString(interp, "tailcall can only be called from a proc or lambda", -1);
17246 return JIM_ERR;
17247 }
17248 else if (argc >= 2) {
17249
17250 Jim_CallFrame *cf = interp->framePtr->parent;
17251
17252 Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
17253 if (cmdPtr == NULL) {
17254 return JIM_ERR;
17255 }
17256
17257 JimPanic((cf->tailcallCmd != NULL, "Already have a tailcallCmd"));
17258
17259
17260 JimIncrCmdRefCount(cmdPtr);
17261 cf->tailcallCmd = cmdPtr;
17262
17263
17264 JimPanic((cf->tailcallObj != NULL, "Already have a tailcallobj"));
17265
17266 cf->tailcallObj = Jim_NewListObj(interp, argv + 1, argc - 1);
17267 Jim_IncrRefCount(cf->tailcallObj);
17268
17269
17270 return JIM_EVAL;
17271 }
17272 return JIM_OK;
17273 }
17274
17275 static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17276 {
17277 Jim_Obj *cmdList;
@@ -17354,11 +17556,11 @@
17556 for (i = 0; i < numMaps; i += 2) {
17557 Jim_Obj *objPtr;
17558 const char *k;
17559 int kl;
17560
17561 objPtr = Jim_ListGetIndex(interp, mapListObjPtr, i);
17562 k = Jim_String(objPtr);
17563 kl = Jim_Utf8Length(interp, objPtr);
17564
17565 if (strLen >= kl && kl) {
17566 int rc;
@@ -17366,12 +17568,11 @@
17568 if (rc == 0) {
17569 if (noMatchStart) {
17570 Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart);
17571 noMatchStart = NULL;
17572 }
17573 Jim_AppendObj(interp, resultObjPtr, Jim_ListGetIndex(interp, mapListObjPtr, i + 1));
 
17574 str += utf8_index(str, kl);
17575 strLen -= kl;
17576 break;
17577 }
17578 }
@@ -17851,15 +18052,17 @@
18052
18053 exitCode = JIM_SIGNAL;
18054 }
18055 else {
18056 exitCode = Jim_EvalObj(interp, argv[0]);
18057
18058 interp->errorFlag = 0;
18059 }
18060 interp->signal_level -= sig;
18061
18062
18063 if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) {
18064
18065 return exitCode;
18066 }
18067
18068 if (sig && exitCode == JIM_SIGNAL) {
@@ -18009,11 +18212,11 @@
18212 listObjPtr = Jim_NewListObj(interp, NULL, 0);
18213
18214 JimInitHashTableIterator(&interp->references, &htiter);
18215 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18216 char buf[JIM_REFERENCE_SPACE + 1];
18217 Jim_Reference *refPtr = Jim_GetHashEntryVal(he);
18218 const unsigned long *refId = he->key;
18219
18220 JimFormatReference(buf, refPtr, *refId);
18221 Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1));
18222 }
@@ -18043,11 +18246,11 @@
18246
18247 static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type)
18248 {
18249 Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
18250 if (type & JIM_DICTMATCH_VALUES) {
18251 Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he));
18252 }
18253 }
18254
18255 static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
18256 JimDictMatchCallbackType *callback, int type)
@@ -18092,21 +18295,65 @@
18295 return -1;
18296 }
18297 return ((Jim_HashTable *)objPtr->internalRep.ptr)->used;
18298 }
18299
18300 int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr)
18301 {
18302 Jim_HashTable *ht;
18303 unsigned int i;
18304
18305 if (SetDictFromAny(interp, objPtr) != JIM_OK) {
18306 return JIM_ERR;
18307 }
18308
18309 ht = (Jim_HashTable *)objPtr->internalRep.ptr;
18310
18311
18312 printf("%d entries in table, %d buckets\n", ht->used, ht->size);
18313
18314 for (i = 0; i < ht->size; i++) {
18315 Jim_HashEntry *he = ht->table[i];
18316
18317 if (he) {
18318 printf("%d: ", i);
18319
18320 while (he) {
18321 printf(" %s", Jim_String(he->key));
18322 he = he->next;
18323 }
18324 printf("\n");
18325 }
18326 }
18327 return JIM_OK;
18328 }
18329
18330 static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv)
18331 {
18332 Jim_Obj *prefixObj = Jim_NewStringObj(interp, basecmd, -1);
18333
18334 Jim_AppendString(interp, prefixObj, " ", 1);
18335 Jim_AppendString(interp, prefixObj, subcmd, -1);
18336
18337 return Jim_EvalObjPrefix(interp, prefixObj, argc, argv);
18338 }
18339
18340
18341 static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18342 {
18343 Jim_Obj *objPtr;
18344 int option;
18345 static const char * const options[] = {
18346 "create", "get", "set", "unset", "exists", "keys", "size", "info",
18347 "merge", "with", "append", "lappend", "incr", "remove", "values", "for",
18348 "replace", "update", NULL
18349 };
18350 enum
18351 {
18352 OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXISTS, OPT_KEYS, OPT_SIZE, OPT_INFO,
18353 OPT_MERGE, OPT_WITH, OPT_APPEND, OPT_LAPPEND, OPT_INCR, OPT_REMOVE, OPT_VALUES, OPT_FOR,
18354 OPT_REPLACE, OPT_UPDATE,
18355 };
18356
18357 if (argc < 2) {
18358 Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?");
18359 return JIM_ERR;
@@ -18117,11 +18364,11 @@
18364 }
18365
18366 switch (option) {
18367 case OPT_GET:
18368 if (argc < 3) {
18369 Jim_WrongNumArgs(interp, 2, argv, "dictionary ?key ...?");
18370 return JIM_ERR;
18371 }
18372 if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr,
18373 JIM_ERRMSG) != JIM_OK) {
18374 return JIM_ERR;
@@ -18134,82 +18381,87 @@
18381 Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...? value");
18382 return JIM_ERR;
18383 }
18384 return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG);
18385
18386 case OPT_EXISTS:
18387 if (argc < 4) {
18388 Jim_WrongNumArgs(interp, 2, argv, "dictionary key ?key ...?");
18389 return JIM_ERR;
18390 }
18391 else {
18392 int rc = Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, JIM_ERRMSG);
18393 if (rc < 0) {
18394 return JIM_ERR;
18395 }
18396 Jim_SetResultBool(interp, rc == JIM_OK);
18397 return JIM_OK;
18398 }
18399
18400 case OPT_UNSET:
18401 if (argc < 4) {
18402 Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?");
18403 return JIM_ERR;
18404 }
18405 if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) {
18406 return JIM_ERR;
18407 }
18408 return JIM_OK;
18409
18410 case OPT_KEYS:
18411 if (argc != 3 && argc != 4) {
18412 Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?");
18413 return JIM_ERR;
18414 }
18415 return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL);
18416
18417 case OPT_SIZE:
 
 
18418 if (argc != 3) {
18419 Jim_WrongNumArgs(interp, 2, argv, "dictionary");
18420 return JIM_ERR;
18421 }
18422 else if (Jim_DictSize(interp, argv[2]) < 0) {
 
 
18423 return JIM_ERR;
18424 }
18425 Jim_SetResultInt(interp, Jim_DictSize(interp, argv[2]));
18426 return JIM_OK;
 
18427
18428 case OPT_MERGE:
18429 if (argc == 2) {
18430 return JIM_OK;
18431 }
18432 if (Jim_DictSize(interp, argv[2]) < 0) {
18433 return JIM_ERR;
18434 }
18435
18436 break;
18437
18438 case OPT_UPDATE:
18439 if (argc < 6 || argc % 2) {
18440
18441 argc = 2;
18442 }
18443 break;
 
 
 
 
 
 
18444
18445 case OPT_CREATE:
18446 if (argc % 2) {
18447 Jim_WrongNumArgs(interp, 2, argv, "?key value ...?");
18448 return JIM_ERR;
18449 }
18450 objPtr = Jim_NewDictObj(interp, argv + 2, argc - 2);
18451 Jim_SetResult(interp, objPtr);
18452 return JIM_OK;
18453
18454 case OPT_INFO:
18455 if (argc != 3) {
18456 Jim_WrongNumArgs(interp, 2, argv, "dictionary");
18457 return JIM_ERR;
18458 }
18459 return Jim_DictInfo(interp, argv[2]);
18460 }
18461
18462 return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2);
18463 }
18464
18465
18466 static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18467 {
@@ -18267,11 +18519,11 @@
18519 };
18520 enum
18521 { INFO_BODY, INFO_STATICS, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL,
18522 INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS,
18523 INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE,
18524 INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS,
18525 };
18526
18527 #ifdef jim_ext_namespace
18528 int nons = 0;
18529
@@ -19047,11 +19299,11 @@
19299 }
19300 }
19301
19302 static const struct {
19303 const char *name;
19304 Jim_CmdProc *cmdProc;
19305 } Jim_CoreCommandsTable[] = {
19306 {"alias", Jim_AliasCoreCommand},
19307 {"set", Jim_SetCoreCommand},
19308 {"unset", Jim_UnsetCoreCommand},
19309 {"puts", Jim_PutsCoreCommand},
@@ -19279,10 +19531,12 @@
19531 }
19532
19533 len += extra;
19534 buf = Jim_Alloc(len + 1);
19535 len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]);
19536
19537 va_end(args);
19538
19539 Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len));
19540 }
19541
19542
@@ -19530,23 +19784,22 @@
19784
19785 #include <ctype.h>
19786 #include <string.h>
19787
19788
 
19789 #define JIM_INTEGER_SPACE 24
19790 #define MAX_FLOAT_WIDTH 320
19791
19792 Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv)
19793 {
19794 const char *span, *format, *formatEnd, *msg;
19795 int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0;
19796 static const char * const mixedXPG =
19797 "cannot mix \"%\" and \"%n$\" conversion specifiers";
19798 static const char * const badIndex[2] = {
19799 "not enough arguments for all format specifiers",
19800 "\"%n$\" argument index out of range"
19801 };
19802 int formatLen;
19803 Jim_Obj *resultPtr;
19804
19805 char *num_buffer = NULL;
@@ -19555,319 +19808,349 @@
19808 span = format = Jim_GetString(fmtObjPtr, &formatLen);
19809 formatEnd = format + formatLen;
19810 resultPtr = Jim_NewEmptyStringObj(interp);
19811
19812 while (format != formatEnd) {
19813 char *end;
19814 int gotMinus, sawFlag;
19815 int gotPrecision, useShort;
19816 long width, precision;
19817 int newXpg;
19818 int ch;
19819 int step;
19820 int doubleType;
19821 char pad = ' ';
19822 char spec[2*JIM_INTEGER_SPACE + 12];
19823 char *p;
19824
19825 int formatted_chars;
19826 int formatted_bytes;
19827 const char *formatted_buf;
19828
19829 step = utf8_tounicode(format, &ch);
19830 format += step;
19831 if (ch != '%') {
19832 numBytes += step;
19833 continue;
19834 }
19835 if (numBytes) {
19836 Jim_AppendString(interp, resultPtr, span, numBytes);
19837 numBytes = 0;
19838 }
19839
19840
19841 step = utf8_tounicode(format, &ch);
19842 if (ch == '%') {
19843 span = format;
19844 numBytes = step;
19845 format += step;
19846 continue;
19847 }
19848
19849
19850 newXpg = 0;
19851 if (isdigit(ch)) {
19852 int position = strtoul(format, &end, 10);
19853 if (*end == '$') {
19854 newXpg = 1;
19855 objIndex = position - 1;
19856 format = end + 1;
19857 step = utf8_tounicode(format, &ch);
19858 }
19859 }
19860 if (newXpg) {
19861 if (gotSequential) {
19862 msg = mixedXPG;
19863 goto errorMsg;
19864 }
19865 gotXpg = 1;
19866 } else {
19867 if (gotXpg) {
19868 msg = mixedXPG;
19869 goto errorMsg;
19870 }
19871 gotSequential = 1;
19872 }
19873 if ((objIndex < 0) || (objIndex >= objc)) {
19874 msg = badIndex[gotXpg];
19875 goto errorMsg;
19876 }
19877
19878 p = spec;
19879 *p++ = '%';
19880
19881 gotMinus = 0;
19882 sawFlag = 1;
19883 do {
19884 switch (ch) {
19885 case '-':
19886 gotMinus = 1;
19887 break;
19888 case '0':
19889 pad = ch;
19890 break;
19891 case ' ':
19892 case '+':
19893 case '#':
19894 break;
19895 default:
19896 sawFlag = 0;
19897 continue;
19898 }
19899 *p++ = ch;
19900 format += step;
19901 step = utf8_tounicode(format, &ch);
19902 } while (sawFlag);
19903
19904
19905 width = 0;
19906 if (isdigit(ch)) {
19907 width = strtoul(format, &end, 10);
19908 format = end;
19909 step = utf8_tounicode(format, &ch);
19910 } else if (ch == '*') {
19911 if (objIndex >= objc - 1) {
19912 msg = badIndex[gotXpg];
19913 goto errorMsg;
19914 }
19915 if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) {
19916 goto error;
19917 }
19918 if (width < 0) {
19919 width = -width;
19920 if (!gotMinus) {
19921 *p++ = '-';
19922 gotMinus = 1;
19923 }
19924 }
19925 objIndex++;
19926 format += step;
19927 step = utf8_tounicode(format, &ch);
19928 }
19929
19930
19931 gotPrecision = precision = 0;
19932 if (ch == '.') {
19933 gotPrecision = 1;
19934 format += step;
19935 step = utf8_tounicode(format, &ch);
19936 }
19937 if (isdigit(ch)) {
19938 precision = strtoul(format, &end, 10);
19939 format = end;
19940 step = utf8_tounicode(format, &ch);
19941 } else if (ch == '*') {
19942 if (objIndex >= objc - 1) {
19943 msg = badIndex[gotXpg];
19944 goto errorMsg;
19945 }
19946 if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) {
19947 goto error;
19948 }
19949
19950
19951 if (precision < 0) {
19952 precision = 0;
19953 }
19954 objIndex++;
19955 format += step;
19956 step = utf8_tounicode(format, &ch);
19957 }
19958
19959
19960 useShort = 0;
19961 if (ch == 'h') {
19962 useShort = 1;
19963 format += step;
19964 step = utf8_tounicode(format, &ch);
19965 } else if (ch == 'l') {
19966
19967 format += step;
19968 step = utf8_tounicode(format, &ch);
19969 if (ch == 'l') {
19970 format += step;
19971 step = utf8_tounicode(format, &ch);
19972 }
19973 }
19974
19975 format += step;
19976 span = format;
19977
19978
19979 if (ch == 'i') {
19980 ch = 'd';
19981 }
19982
19983 doubleType = 0;
19984
19985 switch (ch) {
19986 case '\0':
19987 msg = "format string ended in middle of field specifier";
19988 goto errorMsg;
19989 case 's': {
19990 formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
19991 formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
19992 if (gotPrecision && (precision < formatted_chars)) {
19993
19994 formatted_chars = precision;
19995 formatted_bytes = utf8_index(formatted_buf, precision);
19996 }
19997 break;
19998 }
19999 case 'c': {
20000 jim_wide code;
20001
20002 if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
20003 goto error;
20004 }
20005
20006 formatted_bytes = utf8_getchars(spec, code);
20007 formatted_buf = spec;
20008 formatted_chars = 1;
20009 break;
20010 }
20011 case 'b': {
20012 unsigned jim_wide w;
20013 int length;
20014 int i;
20015 int j;
20016
20017 if (Jim_GetWide(interp, objv[objIndex], (jim_wide *)&w) != JIM_OK) {
20018 goto error;
20019 }
20020 length = sizeof(w) * 8;
20021
20022
20023
20024 if (num_buffer_size < length + 1) {
20025 num_buffer_size = length + 1;
20026 num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
20027 }
20028
20029 j = 0;
20030 for (i = length; i > 0; ) {
20031 i--;
20032 if (w & ((unsigned jim_wide)1 << i)) {
20033 num_buffer[j++] = '1';
20034 }
20035 else if (j || i == 0) {
20036 num_buffer[j++] = '0';
20037 }
20038 }
20039 num_buffer[j] = 0;
20040 formatted_chars = formatted_bytes = j;
20041 formatted_buf = num_buffer;
20042 break;
20043 }
20044
20045 case 'e':
20046 case 'E':
20047 case 'f':
20048 case 'g':
20049 case 'G':
20050 doubleType = 1;
20051
20052 case 'd':
20053 case 'u':
20054 case 'o':
20055 case 'x':
20056 case 'X': {
20057 jim_wide w;
20058 double d;
20059 int length;
20060
20061
20062 if (width) {
20063 p += sprintf(p, "%ld", width);
20064 }
20065 if (gotPrecision) {
20066 p += sprintf(p, ".%ld", precision);
20067 }
20068
20069
20070 if (doubleType) {
20071 if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
20072 goto error;
20073 }
20074 length = MAX_FLOAT_WIDTH;
20075 }
20076 else {
20077 if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) {
20078 goto error;
20079 }
20080 length = JIM_INTEGER_SPACE;
20081 if (useShort) {
20082 if (ch == 'd') {
20083 w = (short)w;
20084 }
20085 else {
20086 w = (unsigned short)w;
20087 }
20088 }
20089 *p++ = 'l';
20090 #ifdef HAVE_LONG_LONG
20091 if (sizeof(long long) == sizeof(jim_wide)) {
20092 *p++ = 'l';
20093 }
20094 #endif
20095 }
20096
20097 *p++ = (char) ch;
20098 *p = '\0';
20099
20100
20101 if (width > length) {
20102 length = width;
20103 }
20104 if (gotPrecision) {
20105 length += precision;
20106 }
20107
20108
20109 if (num_buffer_size < length + 1) {
20110 num_buffer_size = length + 1;
20111 num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
20112 }
20113
20114 if (doubleType) {
20115 snprintf(num_buffer, length + 1, spec, d);
20116 }
20117 else {
20118 formatted_bytes = snprintf(num_buffer, length + 1, spec, w);
20119 }
20120 formatted_chars = formatted_bytes = strlen(num_buffer);
20121 formatted_buf = num_buffer;
20122 break;
20123 }
20124
20125 default: {
20126
20127 spec[0] = ch;
20128 spec[1] = '\0';
20129 Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
20130 goto error;
20131 }
20132 }
20133
20134 if (!gotMinus) {
20135 while (formatted_chars < width) {
20136 Jim_AppendString(interp, resultPtr, &pad, 1);
20137 formatted_chars++;
20138 }
20139 }
20140
20141 Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes);
20142
20143 while (formatted_chars < width) {
20144 Jim_AppendString(interp, resultPtr, &pad, 1);
20145 formatted_chars++;
20146 }
20147
20148 objIndex += gotSequential;
20149 }
20150 if (numBytes) {
20151 Jim_AppendString(interp, resultPtr, span, numBytes);
20152 }
20153
20154 Jim_Free(num_buffer);
20155 return resultPtr;
20156
@@ -19876,21 +20159,22 @@
20159 error:
20160 Jim_FreeNewObj(interp, resultPtr);
20161 Jim_Free(num_buffer);
20162 return NULL;
20163 }
20164
20165
20166 #if defined(JIM_REGEXP)
20167 #include <stdio.h>
20168 #include <ctype.h>
20169 #include <stdlib.h>
20170 #include <string.h>
20171
 
 
 
20172
20173
20174 #define REG_MAX_PAREN 100
20175
20176
20177
20178 #define END 0
20179 #define BOL 1
20180 #define EOL 2
@@ -19899,23 +20183,27 @@
20183 #define ANYBUT 5
20184 #define BRANCH 6
20185 #define BACK 7
20186 #define EXACTLY 8
20187 #define NOTHING 9
20188 #define REP 10
20189 #define REPMIN 11
20190 #define REPX 12
20191 #define REPXMIN 13
20192
20193 #define WORDA 15
20194 #define WORDZ 16
20195
20196 #define OPENNC 1000
20197 #define OPEN 1001
20198
20199
20200
20201
20202 #define CLOSENC 2000
20203 #define CLOSE 2001
20204 #define CLOSE_END (CLOSE+REG_MAX_PAREN)
 
20205
20206 #define REG_MAGIC 0xFADED00D
20207
20208
20209 #define OP(preg, p) (preg->program[p])
@@ -19925,15 +20213,15 @@
20213
20214
20215
20216 #define FAIL(R,M) { (R)->err = (M); return (M); }
20217 #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{')
20218 #define META "^$.[()|?{+*"
20219
20220 #define HASWIDTH 1
20221 #define SIMPLE 2
20222 #define SPSTART 4
20223 #define WORST 0
20224
20225 #define MAX_REP_COUNT 1000000
20226
20227 static int reg(regex_t *preg, int paren , int *flagp );
@@ -19942,13 +20230,13 @@
20230 static int regatom(regex_t *preg, int *flagp );
20231 static int regnode(regex_t *preg, int op );
20232 static int regnext(regex_t *preg, int p );
20233 static void regc(regex_t *preg, int b );
20234 static int reginsert(regex_t *preg, int op, int size, int opnd );
20235 static void regtail(regex_t *preg, int p, int val);
20236 static void regoptail(regex_t *preg, int p, int val );
20237 static int regopsize(regex_t *preg, int p );
20238
20239 static int reg_range_find(const int *string, int c);
20240 static const char *str_find(const char *string, int c, int nocase);
20241 static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase);
20242
@@ -19985,13 +20273,10 @@
20273 FAIL(preg, REG_ERR_NULL_ARGUMENT);
20274
20275
20276 preg->cflags = cflags;
20277 preg->regparse = exp;
 
 
 
20278
20279
20280 preg->proglen = (strlen(exp) + 1) * 5;
20281 preg->program = malloc(preg->proglen * sizeof(int));
20282 if (preg->program == NULL)
@@ -20152,11 +20437,10 @@
20437 {
20438 int ret;
20439 char op;
20440 int next;
20441 int flags;
 
20442 int min;
20443 int max;
20444
20445 ret = regatom(preg, &flags);
20446 if (ret == 0)
@@ -20235,11 +20519,11 @@
20519 if (ISMULT(*preg->regparse)) {
20520 preg->err = REG_ERR_NESTED_COUNT;
20521 return 0;
20522 }
20523
20524 return ret;
20525 }
20526
20527 static void reg_addrange(regex_t *preg, int lower, int upper)
20528 {
20529 if (lower > upper) {
@@ -20329,10 +20613,11 @@
20613 break;
20614 case 'U':
20615 if ((n = parse_hex(s, 8, ch)) > 0) {
20616 s += n;
20617 }
20618 break;
20619 case 'x':
20620 if ((n = parse_hex(s, 2, ch)) > 0) {
20621 s += n;
20622 }
20623 break;
@@ -20577,10 +20862,11 @@
20862
20863 static int regnode(regex_t *preg, int op)
20864 {
20865 reg_grow(preg, 2);
20866
20867
20868 preg->program[preg->p++] = op;
20869 preg->program[preg->p++] = 0;
20870
20871
20872 return preg->p - 2;
@@ -20606,11 +20892,11 @@
20892 preg->p += size;
20893
20894 return opnd + size;
20895 }
20896
20897 static void regtail(regex_t *preg, int p, int val)
20898 {
20899 int scan;
20900 int temp;
20901 int offset;
20902
@@ -20669,36 +20955,16 @@
20955 preg->pmatch = pmatch;
20956 preg->nmatch = nmatch;
20957 preg->start = string;
20958
20959
20960 for (scan = OPERAND(1); scan != 0; scan += regopsize(preg, scan)) {
20961 int op = OP(preg, scan);
20962 if (op == END)
20963 break;
20964 if (op == REPX || op == REPXMIN)
20965 preg->program[scan + 4] = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20966 }
20967
20968
20969 if (preg->regmust != 0) {
20970 s = string;
@@ -20950,10 +21216,11 @@
21216
21217 static int regmatch(regex_t *preg, int prog)
21218 {
21219 int scan;
21220 int next;
21221 const char *save;
21222
21223 scan = prog;
21224
21225 #ifdef DEBUG
21226 if (scan != 0 && regnarrate)
@@ -21038,27 +21305,24 @@
21305 break;
21306 case NOTHING:
21307 break;
21308 case BACK:
21309 break;
21310 case BRANCH:
21311 if (OP(preg, next) != BRANCH)
21312 next = OPERAND(scan);
21313 else {
21314 do {
21315 save = preg->reginput;
21316 if (regmatch(preg, OPERAND(scan))) {
21317 return(1);
21318 }
21319 preg->reginput = save;
21320 scan = regnext(preg, scan);
21321 } while (scan != 0 && OP(preg, scan) == BRANCH);
21322 return(0);
21323
 
 
 
21324 }
21325 break;
21326 case REP:
21327 case REPMIN:
21328 return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN);
@@ -21066,43 +21330,35 @@
21330 case REPX:
21331 case REPXMIN:
21332 return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN);
21333
21334 case END:
21335 return 1;
 
21336
21337 case OPENNC:
21338 case CLOSENC:
21339 return regmatch(preg, next);
 
 
 
21340
21341 default:
21342 if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) {
 
 
21343 save = preg->reginput;
 
21344 if (regmatch(preg, next)) {
 
21345 if (OP(preg, scan) < CLOSE) {
21346 int no = OP(preg, scan) - OPEN;
21347 if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) {
21348 preg->pmatch[no].rm_so = save - preg->start;
21349 }
21350 }
21351 else {
21352 int no = OP(preg, scan) - CLOSE;
21353 if (no < preg->nmatch && preg->pmatch[no].rm_eo == -1) {
21354 preg->pmatch[no].rm_eo = save - preg->start;
21355 }
21356 }
21357 return(1);
21358 }
21359 return(0);
21360 }
21361 return REG_ERR_INTERNAL;
21362 }
21363
21364 scan = next;
@@ -21181,10 +21437,32 @@
21437 if (OP(preg, p) == BACK)
21438 return(p-offset);
21439 else
21440 return(p+offset);
21441 }
21442
21443 static int regopsize(regex_t *preg, int p )
21444 {
21445
21446 switch (OP(preg, p)) {
21447 case REP:
21448 case REPMIN:
21449 case REPX:
21450 case REPXMIN:
21451 return 5;
21452
21453 case ANYOF:
21454 case ANYBUT:
21455 case EXACTLY: {
21456 int s = p + 2;
21457 while (preg->program[s++]) {
21458 }
21459 return s - p;
21460 }
21461 }
21462 return 2;
21463 }
21464
21465
21466 size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
21467 {
21468 static const char *error_strings[] = {
@@ -21359,19 +21637,24 @@
21637 char *Jim_HistoryGetline(const char *prompt)
21638 {
21639 #ifdef USE_LINENOISE
21640 return linenoise(prompt);
21641 #else
21642 int len;
21643 char *line = malloc(MAX_LINE_LEN);
21644
21645 fputs(prompt, stdout);
21646 fflush(stdout);
21647
21648 if (fgets(line, MAX_LINE_LEN, stdin) == NULL) {
21649 free(line);
21650 return NULL;
21651 }
21652 len = strlen(line);
21653 if (len && line[len - 1] == '\n') {
21654 line[len - 1] = '\0';
21655 }
21656 return line;
21657 #endif
21658 }
21659
21660 void Jim_HistoryLoad(const char *filename)
@@ -21422,11 +21705,11 @@
21705 snprintf(history_file, history_len, "%s/.jim_history", home);
21706 Jim_HistoryLoad(history_file);
21707 }
21708 #endif
21709
21710 printf("Welcome to Jim version %d.%d\n",
21711 JIM_VERSION / 100, JIM_VERSION % 100);
21712 Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1");
21713
21714 while (1) {
21715 Jim_Obj *scriptObjPtr;
@@ -21534,10 +21817,16 @@
21817 }
21818
21819 Jim_SetVariableStr(interp, "argv", listObj);
21820 Jim_SetVariableStr(interp, "argc", Jim_NewIntObj(interp, argc));
21821 }
21822
21823 static void JimPrintErrorMessage(Jim_Interp *interp)
21824 {
21825 Jim_MakeErrorMessage(interp);
21826 fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
21827 }
21828
21829 int main(int argc, char *const argv[])
21830 {
21831 int retcode;
21832 Jim_Interp *interp;
@@ -21551,22 +21840,20 @@
21840 interp = Jim_CreateInterp();
21841 Jim_RegisterCoreCommands(interp);
21842
21843
21844 if (Jim_InitStaticExtensions(interp) != JIM_OK) {
21845 JimPrintErrorMessage(interp);
 
21846 }
21847
21848 Jim_SetVariableStrWithStr(interp, "jim_argv0", argv[0]);
21849 Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0");
21850 retcode = Jim_initjimshInit(interp);
21851
21852 if (argc == 1) {
21853 if (retcode == JIM_ERR) {
21854 JimPrintErrorMessage(interp);
 
21855 }
21856 if (retcode != JIM_EXIT) {
21857 JimSetArgv(interp, 0, NULL);
21858 retcode = Jim_InteractivePrompt(interp);
21859 }
@@ -21583,12 +21870,11 @@
21870 Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1));
21871 JimSetArgv(interp, argc - 2, argv + 2);
21872 retcode = Jim_EvalFile(interp, argv[1]);
21873 }
21874 if (retcode == JIM_ERR) {
21875 JimPrintErrorMessage(interp);
 
21876 }
21877 }
21878 if (retcode == JIM_EXIT) {
21879 retcode = Jim_GetExitCode(interp);
21880 }
21881
+33 -13
--- src/add.c
+++ src/add.c
@@ -44,11 +44,11 @@
4444
".fslckout",
4545
".fslckout-journal",
4646
".fslckout-wal",
4747
".fslckout-shm",
4848
49
- /* The use of ".fos" as the name of the checkout database is
49
+ /* The use of ".fos" as the name of the checkout database is
5050
** deprecated. Use ".fslckout" instead. At some point, the following
5151
** entries should be removed. 2012-02-04 */
5252
".fos",
5353
".fos-journal",
5454
".fos-wal",
@@ -123,10 +123,14 @@
123123
*/
124124
void test_reserved_names(void){
125125
int i;
126126
const char *z;
127127
int omitRepo = find_option("omitrepo",0,0)!=0;
128
+
129
+ /* We should be done with options.. */
130
+ verify_all_options();
131
+
128132
db_must_be_within_tree();
129133
for(i=0; (z = fossil_reserved_name(i, omitRepo))!=0; i++){
130134
fossil_print("%3d: %s\n", i, z);
131135
}
132136
fossil_print("ALL: (%s)\n", fossil_all_reserved_names(omitRepo));
@@ -177,11 +181,11 @@
177181
int i; /* Loop counter */
178182
const char *zReserved; /* Name of a reserved file */
179183
Blob repoName; /* Treename of the repository */
180184
Stmt loop; /* SQL to loop over all files to add */
181185
int (*xCmp)(const char*,const char*);
182
-
186
+
183187
if( !file_tree_name(g.zRepositoryName, &repoName, 0) ){
184188
blob_zero(&repoName);
185189
zRepo = "";
186190
}else{
187191
zRepo = blob_str(&repoName);
@@ -233,17 +237,17 @@
233237
** depends on the global setting, or the operating system default, if not set.
234238
**
235239
** Options:
236240
**
237241
** --case-sensitive <BOOL> override case-sensitive setting
238
-** --dotfiles include files beginning with a dot (".")
242
+** --dotfiles include files beginning with a dot (".")
239243
** -f|--force Add files without prompting
240
-** --ignore <CSG> ignore files matching patterns from the
244
+** --ignore <CSG> ignore files matching patterns from the
241245
** comma separated list of glob patterns.
242246
** --clean <CSG> also ignore files matching patterns from
243247
** the comma separated list of glob patterns.
244
-**
248
+**
245249
** See also: addremove, rm
246250
*/
247251
void add_cmd(void){
248252
int i; /* Loop counter */
249253
int vid; /* Currently checked out version */
@@ -257,10 +261,14 @@
257261
zCleanFlag = find_option("clean",0,1);
258262
zIgnoreFlag = find_option("ignore",0,1);
259263
forceFlag = find_option("force","f",0)!=0;
260264
if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;
261265
capture_case_sensitive_option();
266
+
267
+ /* We should be done with options.. */
268
+ verify_all_options();
269
+
262270
db_must_be_within_tree();
263271
if( zCleanFlag==0 ){
264272
zCleanFlag = db_get("clean-glob", 0);
265273
}
266274
if( zIgnoreFlag==0 ){
@@ -271,11 +279,11 @@
271279
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
272280
filename_collation());
273281
pClean = glob_create(zCleanFlag);
274282
pIgnore = glob_create(zIgnoreFlag);
275283
nRoot = strlen(g.zLocalRoot);
276
-
284
+
277285
/* Load the names of all files that are to be added into sfile temp table */
278286
for(i=2; i<g.argc; i++){
279287
char *zName;
280288
int isDir;
281289
Blob fullName;
@@ -346,10 +354,14 @@
346354
void delete_cmd(void){
347355
int i;
348356
Stmt loop;
349357
350358
capture_case_sensitive_option();
359
+
360
+ /* We should be done with options.. */
361
+ verify_all_options();
362
+
351363
db_must_be_within_tree();
352364
db_begin_transaction();
353365
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
354366
filename_collation());
355367
for(i=2; i<g.argc; i++){
@@ -367,11 +379,11 @@
367379
zTreeName, filename_collation(), zTreeName,
368380
filename_collation(), zTreeName, filename_collation()
369381
);
370382
blob_reset(&treeName);
371383
}
372
-
384
+
373385
db_prepare(&loop, "SELECT x FROM sfile");
374386
while( db_step(&loop)==SQLITE_ROW ){
375387
fossil_print("DELETED %s\n", db_column_text(&loop, 0));
376388
}
377389
db_finalize(&loop);
@@ -482,12 +494,12 @@
482494
** on the "settings" command for further information.
483495
**
484496
** The -n|--dry-run option shows what would happen without actually doing anything.
485497
**
486498
** This command can be used to track third party software.
487
-**
488
-** Options:
499
+**
500
+** Options:
489501
** --case-sensitive <BOOL> override case-sensitive setting
490502
** --dotfiles include files beginning with a dot (".")
491503
** --ignore <CSG> ignore files matching patterns from the
492504
** comma separated list of glob patterns.
493505
** --clean <CSG> also ignore files matching patterns from
@@ -511,10 +523,14 @@
511523
512524
if( !dryRunFlag ){
513525
dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
514526
}
515527
capture_case_sensitive_option();
528
+
529
+ /* We should be done with options.. */
530
+ verify_all_options();
531
+
516532
db_must_be_within_tree();
517533
if( zCleanFlag==0 ){
518534
zCleanFlag = db_get("clean-glob", 0);
519535
}
520536
if( zIgnoreFlag==0 ){
@@ -521,11 +537,11 @@
521537
zIgnoreFlag = db_get("ignore-glob", 0);
522538
}
523539
vid = db_lget_int("checkout",0);
524540
db_begin_transaction();
525541
526
- /* step 1:
542
+ /* step 1:
527543
** Populate the temp table "sfile" with the names of all unmanaged
528544
** files currently in the check-out, except for files that match the
529545
** --ignore or ignore-glob patterns and dot-files. Then add all of
530546
** the files in the sfile temp table to the set of managed files.
531547
*/
@@ -547,12 +563,12 @@
547563
" WHERE NOT deleted"
548564
" ORDER BY 1",
549565
g.zLocalRoot
550566
);
551567
while( db_step(&q)==SQLITE_ROW ){
552
- const char * zFile;
553
- const char * zPath;
568
+ const char *zFile;
569
+ const char *zPath;
554570
555571
zFile = db_column_text(&q, 0);
556572
zPath = db_column_text(&q, 1);
557573
if( !file_wd_isfile_or_link(zPath) ){
558574
if( !dryRunFlag ){
@@ -579,11 +595,11 @@
579595
int x = db_int(-1, "SELECT deleted FROM vfile WHERE pathname=%Q %s",
580596
zNew, filename_collation());
581597
if( x>=0 ){
582598
if( x==0 ){
583599
fossil_fatal("cannot rename '%s' to '%s' since another file named '%s'"
584
- " is currently under management", zOrig, zNew, zNew);
600
+ " is currently under management", zOrig, zNew, zNew);
585601
}else{
586602
fossil_fatal("cannot rename '%s' to '%s' since the delete of '%s' has "
587603
"not yet been committed", zOrig, zNew, zNew);
588604
}
589605
}
@@ -620,10 +636,14 @@
620636
Blob dest;
621637
Stmt q;
622638
623639
capture_case_sensitive_option();
624640
db_must_be_within_tree();
641
+
642
+ /* We should be done with options.. */
643
+ verify_all_options();
644
+
625645
vid = db_lget_int("checkout", 0);
626646
if( vid==0 ){
627647
fossil_fatal("no checkout rename files in");
628648
}
629649
if( g.argc<4 ){
630650
--- src/add.c
+++ src/add.c
@@ -44,11 +44,11 @@
44 ".fslckout",
45 ".fslckout-journal",
46 ".fslckout-wal",
47 ".fslckout-shm",
48
49 /* The use of ".fos" as the name of the checkout database is
50 ** deprecated. Use ".fslckout" instead. At some point, the following
51 ** entries should be removed. 2012-02-04 */
52 ".fos",
53 ".fos-journal",
54 ".fos-wal",
@@ -123,10 +123,14 @@
123 */
124 void test_reserved_names(void){
125 int i;
126 const char *z;
127 int omitRepo = find_option("omitrepo",0,0)!=0;
 
 
 
 
128 db_must_be_within_tree();
129 for(i=0; (z = fossil_reserved_name(i, omitRepo))!=0; i++){
130 fossil_print("%3d: %s\n", i, z);
131 }
132 fossil_print("ALL: (%s)\n", fossil_all_reserved_names(omitRepo));
@@ -177,11 +181,11 @@
177 int i; /* Loop counter */
178 const char *zReserved; /* Name of a reserved file */
179 Blob repoName; /* Treename of the repository */
180 Stmt loop; /* SQL to loop over all files to add */
181 int (*xCmp)(const char*,const char*);
182
183 if( !file_tree_name(g.zRepositoryName, &repoName, 0) ){
184 blob_zero(&repoName);
185 zRepo = "";
186 }else{
187 zRepo = blob_str(&repoName);
@@ -233,17 +237,17 @@
233 ** depends on the global setting, or the operating system default, if not set.
234 **
235 ** Options:
236 **
237 ** --case-sensitive <BOOL> override case-sensitive setting
238 ** --dotfiles include files beginning with a dot (".")
239 ** -f|--force Add files without prompting
240 ** --ignore <CSG> ignore files matching patterns from the
241 ** comma separated list of glob patterns.
242 ** --clean <CSG> also ignore files matching patterns from
243 ** the comma separated list of glob patterns.
244 **
245 ** See also: addremove, rm
246 */
247 void add_cmd(void){
248 int i; /* Loop counter */
249 int vid; /* Currently checked out version */
@@ -257,10 +261,14 @@
257 zCleanFlag = find_option("clean",0,1);
258 zIgnoreFlag = find_option("ignore",0,1);
259 forceFlag = find_option("force","f",0)!=0;
260 if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;
261 capture_case_sensitive_option();
 
 
 
 
262 db_must_be_within_tree();
263 if( zCleanFlag==0 ){
264 zCleanFlag = db_get("clean-glob", 0);
265 }
266 if( zIgnoreFlag==0 ){
@@ -271,11 +279,11 @@
271 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
272 filename_collation());
273 pClean = glob_create(zCleanFlag);
274 pIgnore = glob_create(zIgnoreFlag);
275 nRoot = strlen(g.zLocalRoot);
276
277 /* Load the names of all files that are to be added into sfile temp table */
278 for(i=2; i<g.argc; i++){
279 char *zName;
280 int isDir;
281 Blob fullName;
@@ -346,10 +354,14 @@
346 void delete_cmd(void){
347 int i;
348 Stmt loop;
349
350 capture_case_sensitive_option();
 
 
 
 
351 db_must_be_within_tree();
352 db_begin_transaction();
353 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
354 filename_collation());
355 for(i=2; i<g.argc; i++){
@@ -367,11 +379,11 @@
367 zTreeName, filename_collation(), zTreeName,
368 filename_collation(), zTreeName, filename_collation()
369 );
370 blob_reset(&treeName);
371 }
372
373 db_prepare(&loop, "SELECT x FROM sfile");
374 while( db_step(&loop)==SQLITE_ROW ){
375 fossil_print("DELETED %s\n", db_column_text(&loop, 0));
376 }
377 db_finalize(&loop);
@@ -482,12 +494,12 @@
482 ** on the "settings" command for further information.
483 **
484 ** The -n|--dry-run option shows what would happen without actually doing anything.
485 **
486 ** This command can be used to track third party software.
487 **
488 ** Options:
489 ** --case-sensitive <BOOL> override case-sensitive setting
490 ** --dotfiles include files beginning with a dot (".")
491 ** --ignore <CSG> ignore files matching patterns from the
492 ** comma separated list of glob patterns.
493 ** --clean <CSG> also ignore files matching patterns from
@@ -511,10 +523,14 @@
511
512 if( !dryRunFlag ){
513 dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
514 }
515 capture_case_sensitive_option();
 
 
 
 
516 db_must_be_within_tree();
517 if( zCleanFlag==0 ){
518 zCleanFlag = db_get("clean-glob", 0);
519 }
520 if( zIgnoreFlag==0 ){
@@ -521,11 +537,11 @@
521 zIgnoreFlag = db_get("ignore-glob", 0);
522 }
523 vid = db_lget_int("checkout",0);
524 db_begin_transaction();
525
526 /* step 1:
527 ** Populate the temp table "sfile" with the names of all unmanaged
528 ** files currently in the check-out, except for files that match the
529 ** --ignore or ignore-glob patterns and dot-files. Then add all of
530 ** the files in the sfile temp table to the set of managed files.
531 */
@@ -547,12 +563,12 @@
547 " WHERE NOT deleted"
548 " ORDER BY 1",
549 g.zLocalRoot
550 );
551 while( db_step(&q)==SQLITE_ROW ){
552 const char * zFile;
553 const char * zPath;
554
555 zFile = db_column_text(&q, 0);
556 zPath = db_column_text(&q, 1);
557 if( !file_wd_isfile_or_link(zPath) ){
558 if( !dryRunFlag ){
@@ -579,11 +595,11 @@
579 int x = db_int(-1, "SELECT deleted FROM vfile WHERE pathname=%Q %s",
580 zNew, filename_collation());
581 if( x>=0 ){
582 if( x==0 ){
583 fossil_fatal("cannot rename '%s' to '%s' since another file named '%s'"
584 " is currently under management", zOrig, zNew, zNew);
585 }else{
586 fossil_fatal("cannot rename '%s' to '%s' since the delete of '%s' has "
587 "not yet been committed", zOrig, zNew, zNew);
588 }
589 }
@@ -620,10 +636,14 @@
620 Blob dest;
621 Stmt q;
622
623 capture_case_sensitive_option();
624 db_must_be_within_tree();
 
 
 
 
625 vid = db_lget_int("checkout", 0);
626 if( vid==0 ){
627 fossil_fatal("no checkout rename files in");
628 }
629 if( g.argc<4 ){
630
--- src/add.c
+++ src/add.c
@@ -44,11 +44,11 @@
44 ".fslckout",
45 ".fslckout-journal",
46 ".fslckout-wal",
47 ".fslckout-shm",
48
49 /* The use of ".fos" as the name of the checkout database is
50 ** deprecated. Use ".fslckout" instead. At some point, the following
51 ** entries should be removed. 2012-02-04 */
52 ".fos",
53 ".fos-journal",
54 ".fos-wal",
@@ -123,10 +123,14 @@
123 */
124 void test_reserved_names(void){
125 int i;
126 const char *z;
127 int omitRepo = find_option("omitrepo",0,0)!=0;
128
129 /* We should be done with options.. */
130 verify_all_options();
131
132 db_must_be_within_tree();
133 for(i=0; (z = fossil_reserved_name(i, omitRepo))!=0; i++){
134 fossil_print("%3d: %s\n", i, z);
135 }
136 fossil_print("ALL: (%s)\n", fossil_all_reserved_names(omitRepo));
@@ -177,11 +181,11 @@
181 int i; /* Loop counter */
182 const char *zReserved; /* Name of a reserved file */
183 Blob repoName; /* Treename of the repository */
184 Stmt loop; /* SQL to loop over all files to add */
185 int (*xCmp)(const char*,const char*);
186
187 if( !file_tree_name(g.zRepositoryName, &repoName, 0) ){
188 blob_zero(&repoName);
189 zRepo = "";
190 }else{
191 zRepo = blob_str(&repoName);
@@ -233,17 +237,17 @@
237 ** depends on the global setting, or the operating system default, if not set.
238 **
239 ** Options:
240 **
241 ** --case-sensitive <BOOL> override case-sensitive setting
242 ** --dotfiles include files beginning with a dot (".")
243 ** -f|--force Add files without prompting
244 ** --ignore <CSG> ignore files matching patterns from the
245 ** comma separated list of glob patterns.
246 ** --clean <CSG> also ignore files matching patterns from
247 ** the comma separated list of glob patterns.
248 **
249 ** See also: addremove, rm
250 */
251 void add_cmd(void){
252 int i; /* Loop counter */
253 int vid; /* Currently checked out version */
@@ -257,10 +261,14 @@
261 zCleanFlag = find_option("clean",0,1);
262 zIgnoreFlag = find_option("ignore",0,1);
263 forceFlag = find_option("force","f",0)!=0;
264 if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;
265 capture_case_sensitive_option();
266
267 /* We should be done with options.. */
268 verify_all_options();
269
270 db_must_be_within_tree();
271 if( zCleanFlag==0 ){
272 zCleanFlag = db_get("clean-glob", 0);
273 }
274 if( zIgnoreFlag==0 ){
@@ -271,11 +279,11 @@
279 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
280 filename_collation());
281 pClean = glob_create(zCleanFlag);
282 pIgnore = glob_create(zIgnoreFlag);
283 nRoot = strlen(g.zLocalRoot);
284
285 /* Load the names of all files that are to be added into sfile temp table */
286 for(i=2; i<g.argc; i++){
287 char *zName;
288 int isDir;
289 Blob fullName;
@@ -346,10 +354,14 @@
354 void delete_cmd(void){
355 int i;
356 Stmt loop;
357
358 capture_case_sensitive_option();
359
360 /* We should be done with options.. */
361 verify_all_options();
362
363 db_must_be_within_tree();
364 db_begin_transaction();
365 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
366 filename_collation());
367 for(i=2; i<g.argc; i++){
@@ -367,11 +379,11 @@
379 zTreeName, filename_collation(), zTreeName,
380 filename_collation(), zTreeName, filename_collation()
381 );
382 blob_reset(&treeName);
383 }
384
385 db_prepare(&loop, "SELECT x FROM sfile");
386 while( db_step(&loop)==SQLITE_ROW ){
387 fossil_print("DELETED %s\n", db_column_text(&loop, 0));
388 }
389 db_finalize(&loop);
@@ -482,12 +494,12 @@
494 ** on the "settings" command for further information.
495 **
496 ** The -n|--dry-run option shows what would happen without actually doing anything.
497 **
498 ** This command can be used to track third party software.
499 **
500 ** Options:
501 ** --case-sensitive <BOOL> override case-sensitive setting
502 ** --dotfiles include files beginning with a dot (".")
503 ** --ignore <CSG> ignore files matching patterns from the
504 ** comma separated list of glob patterns.
505 ** --clean <CSG> also ignore files matching patterns from
@@ -511,10 +523,14 @@
523
524 if( !dryRunFlag ){
525 dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
526 }
527 capture_case_sensitive_option();
528
529 /* We should be done with options.. */
530 verify_all_options();
531
532 db_must_be_within_tree();
533 if( zCleanFlag==0 ){
534 zCleanFlag = db_get("clean-glob", 0);
535 }
536 if( zIgnoreFlag==0 ){
@@ -521,11 +537,11 @@
537 zIgnoreFlag = db_get("ignore-glob", 0);
538 }
539 vid = db_lget_int("checkout",0);
540 db_begin_transaction();
541
542 /* step 1:
543 ** Populate the temp table "sfile" with the names of all unmanaged
544 ** files currently in the check-out, except for files that match the
545 ** --ignore or ignore-glob patterns and dot-files. Then add all of
546 ** the files in the sfile temp table to the set of managed files.
547 */
@@ -547,12 +563,12 @@
563 " WHERE NOT deleted"
564 " ORDER BY 1",
565 g.zLocalRoot
566 );
567 while( db_step(&q)==SQLITE_ROW ){
568 const char *zFile;
569 const char *zPath;
570
571 zFile = db_column_text(&q, 0);
572 zPath = db_column_text(&q, 1);
573 if( !file_wd_isfile_or_link(zPath) ){
574 if( !dryRunFlag ){
@@ -579,11 +595,11 @@
595 int x = db_int(-1, "SELECT deleted FROM vfile WHERE pathname=%Q %s",
596 zNew, filename_collation());
597 if( x>=0 ){
598 if( x==0 ){
599 fossil_fatal("cannot rename '%s' to '%s' since another file named '%s'"
600 " is currently under management", zOrig, zNew, zNew);
601 }else{
602 fossil_fatal("cannot rename '%s' to '%s' since the delete of '%s' has "
603 "not yet been committed", zOrig, zNew, zNew);
604 }
605 }
@@ -620,10 +636,14 @@
636 Blob dest;
637 Stmt q;
638
639 capture_case_sensitive_option();
640 db_must_be_within_tree();
641
642 /* We should be done with options.. */
643 verify_all_options();
644
645 vid = db_lget_int("checkout", 0);
646 if( vid==0 ){
647 fossil_fatal("no checkout rename files in");
648 }
649 if( g.argc<4 ){
650
+2 -2
--- src/browse.c
+++ src/browse.c
@@ -495,11 +495,11 @@
495495
}
496496
if( linkTrunk ){
497497
style_submenu_element("Trunk", "Trunk", "%s",
498498
url_render(&sURI, "ci", "trunk", 0, 0));
499499
}
500
- if ( linkTip ){
500
+ if( linkTip ){
501501
style_submenu_element("Tip", "Tip", "%s",
502502
url_render(&sURI, "ci", "tip", 0, 0));
503503
}
504504
if( !showDirOnly ){
505505
style_submenu_element("Flat-View", "Flat-View", "%s",
@@ -718,11 +718,11 @@
718718
int isExt = zExt && zExt!=zFilename && zExt[1];
719719
int i;
720720
for( i=1; isExt && zExt[i]; i++ ) isExt &= fossil_isalnum(zExt[i]);
721721
if( isExt ){
722722
zClass = mprintf("file file-%s", zExt+1);
723
- for ( i=5; zClass[i]; i++ ) zClass[i] = fossil_tolower(zClass[i]);
723
+ for( i=5; zClass[i]; i++ ) zClass[i] = fossil_tolower(zClass[i]);
724724
}else{
725725
zClass = mprintf("file");
726726
}
727727
return zClass;
728728
}
729729
--- src/browse.c
+++ src/browse.c
@@ -495,11 +495,11 @@
495 }
496 if( linkTrunk ){
497 style_submenu_element("Trunk", "Trunk", "%s",
498 url_render(&sURI, "ci", "trunk", 0, 0));
499 }
500 if ( linkTip ){
501 style_submenu_element("Tip", "Tip", "%s",
502 url_render(&sURI, "ci", "tip", 0, 0));
503 }
504 if( !showDirOnly ){
505 style_submenu_element("Flat-View", "Flat-View", "%s",
@@ -718,11 +718,11 @@
718 int isExt = zExt && zExt!=zFilename && zExt[1];
719 int i;
720 for( i=1; isExt && zExt[i]; i++ ) isExt &= fossil_isalnum(zExt[i]);
721 if( isExt ){
722 zClass = mprintf("file file-%s", zExt+1);
723 for ( i=5; zClass[i]; i++ ) zClass[i] = fossil_tolower(zClass[i]);
724 }else{
725 zClass = mprintf("file");
726 }
727 return zClass;
728 }
729
--- src/browse.c
+++ src/browse.c
@@ -495,11 +495,11 @@
495 }
496 if( linkTrunk ){
497 style_submenu_element("Trunk", "Trunk", "%s",
498 url_render(&sURI, "ci", "trunk", 0, 0));
499 }
500 if( linkTip ){
501 style_submenu_element("Tip", "Tip", "%s",
502 url_render(&sURI, "ci", "tip", 0, 0));
503 }
504 if( !showDirOnly ){
505 style_submenu_element("Flat-View", "Flat-View", "%s",
@@ -718,11 +718,11 @@
718 int isExt = zExt && zExt!=zFilename && zExt[1];
719 int i;
720 for( i=1; isExt && zExt[i]; i++ ) isExt &= fossil_isalnum(zExt[i]);
721 if( isExt ){
722 zClass = mprintf("file file-%s", zExt+1);
723 for( i=5; zClass[i]; i++ ) zClass[i] = fossil_tolower(zClass[i]);
724 }else{
725 zClass = mprintf("file");
726 }
727 return zClass;
728 }
729
+29 -1
--- src/cache.c
+++ src/cache.c
@@ -62,10 +62,11 @@
6262
if( rc ){
6363
sqlite3_close(db);
6464
return 0;
6565
}
6666
rc = sqlite3_exec(db,
67
+ "PRAGMA page_size=8192;"
6768
"CREATE TABLE IF NOT EXISTS blob(id INTEGER PRIMARY KEY, data BLOB);"
6869
"CREATE TABLE IF NOT EXISTS cache("
6970
"key TEXT PRIMARY KEY," /* Key used to access the cache */
7071
"id INT REFERENCES blob," /* The cache content */
7172
"sz INT," /* Size of content in bytes */
@@ -345,11 +346,12 @@
345346
" ORDER BY tm DESC"
346347
);
347348
if( pStmt ){
348349
@ <ol>
349350
while( sqlite3_step(pStmt)==SQLITE_ROW ){
350
- @ <li><p>%h(sqlite3_column_text(pStmt,0))<br>
351
+ const char *zName = sqlite3_column_text(pStmt,0);
352
+ @ <li><p>%z(href("%R/cacheget?key=%T",zName))%h(zName)</a><br>
351353
@ size: %s(sqlite3_column_text(pStmt,1))
352354
@ hit-count: %d(sqlite3_column_int(pStmt,2))
353355
@ last-access: %s(sqlite3_column_text(pStmt,3))</p></li>
354356
}
355357
sqlite3_finalize(pStmt);
@@ -362,5 +364,31 @@
362364
fossil_free(zDbName);
363365
sqlite3_close(db);
364366
}
365367
style_footer();
366368
}
369
+
370
+/*
371
+** WEBPAGE: cacheget
372
+**
373
+** Usage: /cacheget?key=KEY
374
+**
375
+** Download a single entry for the cache, identified by KEY.
376
+** This page is normally a hyperlink from the /cachestat page.
377
+*/
378
+void cache_getpage(void){
379
+ const char *zKey;
380
+ Blob content;
381
+
382
+ login_check_credentials();
383
+ if( !g.perm.Setup ){ login_needed(); return; }
384
+ zKey = PD("key","");
385
+ blob_zero(&content);
386
+ if( cache_read(&content, zKey)==0 ){
387
+ style_header("Cache Download Error");
388
+ @ The cache does not contain any entry with this key: "%h(zKey)"
389
+ style_footer();
390
+ return;
391
+ }
392
+ cgi_set_content(&content);
393
+ cgi_set_content_type("application/x-compressed");
394
+}
367395
--- src/cache.c
+++ src/cache.c
@@ -62,10 +62,11 @@
62 if( rc ){
63 sqlite3_close(db);
64 return 0;
65 }
66 rc = sqlite3_exec(db,
 
67 "CREATE TABLE IF NOT EXISTS blob(id INTEGER PRIMARY KEY, data BLOB);"
68 "CREATE TABLE IF NOT EXISTS cache("
69 "key TEXT PRIMARY KEY," /* Key used to access the cache */
70 "id INT REFERENCES blob," /* The cache content */
71 "sz INT," /* Size of content in bytes */
@@ -345,11 +346,12 @@
345 " ORDER BY tm DESC"
346 );
347 if( pStmt ){
348 @ <ol>
349 while( sqlite3_step(pStmt)==SQLITE_ROW ){
350 @ <li><p>%h(sqlite3_column_text(pStmt,0))<br>
 
351 @ size: %s(sqlite3_column_text(pStmt,1))
352 @ hit-count: %d(sqlite3_column_int(pStmt,2))
353 @ last-access: %s(sqlite3_column_text(pStmt,3))</p></li>
354 }
355 sqlite3_finalize(pStmt);
@@ -362,5 +364,31 @@
362 fossil_free(zDbName);
363 sqlite3_close(db);
364 }
365 style_footer();
366 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
367
--- src/cache.c
+++ src/cache.c
@@ -62,10 +62,11 @@
62 if( rc ){
63 sqlite3_close(db);
64 return 0;
65 }
66 rc = sqlite3_exec(db,
67 "PRAGMA page_size=8192;"
68 "CREATE TABLE IF NOT EXISTS blob(id INTEGER PRIMARY KEY, data BLOB);"
69 "CREATE TABLE IF NOT EXISTS cache("
70 "key TEXT PRIMARY KEY," /* Key used to access the cache */
71 "id INT REFERENCES blob," /* The cache content */
72 "sz INT," /* Size of content in bytes */
@@ -345,11 +346,12 @@
346 " ORDER BY tm DESC"
347 );
348 if( pStmt ){
349 @ <ol>
350 while( sqlite3_step(pStmt)==SQLITE_ROW ){
351 const char *zName = sqlite3_column_text(pStmt,0);
352 @ <li><p>%z(href("%R/cacheget?key=%T",zName))%h(zName)</a><br>
353 @ size: %s(sqlite3_column_text(pStmt,1))
354 @ hit-count: %d(sqlite3_column_int(pStmt,2))
355 @ last-access: %s(sqlite3_column_text(pStmt,3))</p></li>
356 }
357 sqlite3_finalize(pStmt);
@@ -362,5 +364,31 @@
364 fossil_free(zDbName);
365 sqlite3_close(db);
366 }
367 style_footer();
368 }
369
370 /*
371 ** WEBPAGE: cacheget
372 **
373 ** Usage: /cacheget?key=KEY
374 **
375 ** Download a single entry for the cache, identified by KEY.
376 ** This page is normally a hyperlink from the /cachestat page.
377 */
378 void cache_getpage(void){
379 const char *zKey;
380 Blob content;
381
382 login_check_credentials();
383 if( !g.perm.Setup ){ login_needed(); return; }
384 zKey = PD("key","");
385 blob_zero(&content);
386 if( cache_read(&content, zKey)==0 ){
387 style_header("Cache Download Error");
388 @ The cache does not contain any entry with this key: "%h(zKey)"
389 style_footer();
390 return;
391 }
392 cgi_set_content(&content);
393 cgi_set_content_type("application/x-compressed");
394 }
395
+3 -2
--- src/cgi.c
+++ src/cgi.c
@@ -306,10 +306,11 @@
306306
307307
if( g.fullHttpReply ){
308308
fprintf(g.httpOut, "HTTP/1.0 %d %s\r\n", iReplyStatus, zReplyStatus);
309309
fprintf(g.httpOut, "Date: %s\r\n", cgi_rfc822_datestamp(time(0)));
310310
fprintf(g.httpOut, "Connection: close\r\n");
311
+ fprintf(g.httpOut, "X-UA-Compatible: IE=edge\r\n");
311312
}else{
312313
fprintf(g.httpOut, "Status: %d %s\r\n", iReplyStatus, zReplyStatus);
313314
}
314315
315316
if( blob_size(&extraHeader)>0 ){
@@ -750,11 +751,11 @@
750751
else {
751752
CgiPostReadState * st = (CgiPostReadState *)state;
752753
if( st->pos >= st->len ){
753754
*n = 0;
754755
return 0;
755
- } else if( !*n || ((st->pos + *n) > st->len) ){
756
+ }else if( !*n || ((st->pos + *n) > st->len) ){
756757
return cson_rc.RangeError;
757758
}else{
758759
unsigned int rsz = (unsigned int)fread( dest, 1, *n, st->fh );
759760
if( ! rsz ){
760761
*n = rsz;
@@ -1557,11 +1558,11 @@
15571558
cgi_trace(zLine);
15581559
zToken = extract_token(zLine, &z);
15591560
if( zToken && strlen(zToken)==0 ){
15601561
/* look for path to fossil */
15611562
if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1562
- if ( zCmd==0 ){
1563
+ if( zCmd==0 ){
15631564
malformed_request("missing fossil command");
15641565
}else{
15651566
/* no new command so exit */
15661567
fossil_exit(0);
15671568
}
15681569
--- src/cgi.c
+++ src/cgi.c
@@ -306,10 +306,11 @@
306
307 if( g.fullHttpReply ){
308 fprintf(g.httpOut, "HTTP/1.0 %d %s\r\n", iReplyStatus, zReplyStatus);
309 fprintf(g.httpOut, "Date: %s\r\n", cgi_rfc822_datestamp(time(0)));
310 fprintf(g.httpOut, "Connection: close\r\n");
 
311 }else{
312 fprintf(g.httpOut, "Status: %d %s\r\n", iReplyStatus, zReplyStatus);
313 }
314
315 if( blob_size(&extraHeader)>0 ){
@@ -750,11 +751,11 @@
750 else {
751 CgiPostReadState * st = (CgiPostReadState *)state;
752 if( st->pos >= st->len ){
753 *n = 0;
754 return 0;
755 } else if( !*n || ((st->pos + *n) > st->len) ){
756 return cson_rc.RangeError;
757 }else{
758 unsigned int rsz = (unsigned int)fread( dest, 1, *n, st->fh );
759 if( ! rsz ){
760 *n = rsz;
@@ -1557,11 +1558,11 @@
1557 cgi_trace(zLine);
1558 zToken = extract_token(zLine, &z);
1559 if( zToken && strlen(zToken)==0 ){
1560 /* look for path to fossil */
1561 if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1562 if ( zCmd==0 ){
1563 malformed_request("missing fossil command");
1564 }else{
1565 /* no new command so exit */
1566 fossil_exit(0);
1567 }
1568
--- src/cgi.c
+++ src/cgi.c
@@ -306,10 +306,11 @@
306
307 if( g.fullHttpReply ){
308 fprintf(g.httpOut, "HTTP/1.0 %d %s\r\n", iReplyStatus, zReplyStatus);
309 fprintf(g.httpOut, "Date: %s\r\n", cgi_rfc822_datestamp(time(0)));
310 fprintf(g.httpOut, "Connection: close\r\n");
311 fprintf(g.httpOut, "X-UA-Compatible: IE=edge\r\n");
312 }else{
313 fprintf(g.httpOut, "Status: %d %s\r\n", iReplyStatus, zReplyStatus);
314 }
315
316 if( blob_size(&extraHeader)>0 ){
@@ -750,11 +751,11 @@
751 else {
752 CgiPostReadState * st = (CgiPostReadState *)state;
753 if( st->pos >= st->len ){
754 *n = 0;
755 return 0;
756 }else if( !*n || ((st->pos + *n) > st->len) ){
757 return cson_rc.RangeError;
758 }else{
759 unsigned int rsz = (unsigned int)fread( dest, 1, *n, st->fh );
760 if( ! rsz ){
761 *n = rsz;
@@ -1557,11 +1558,11 @@
1558 cgi_trace(zLine);
1559 zToken = extract_token(zLine, &z);
1560 if( zToken && strlen(zToken)==0 ){
1561 /* look for path to fossil */
1562 if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1563 if( zCmd==0 ){
1564 malformed_request("missing fossil command");
1565 }else{
1566 /* no new command so exit */
1567 fossil_exit(0);
1568 }
1569
+45 -17
--- src/checkin.c
+++ src/checkin.c
@@ -159,10 +159,35 @@
159159
int relPathOption = find_option("rel-paths", 0, 0)!=0;
160160
if( absPathOption ){ relativePaths = 0; }
161161
if( relPathOption ){ relativePaths = 1; }
162162
return relativePaths;
163163
}
164
+
165
+void print_changes(
166
+ int useSha1sum, /* Verify file status using SHA1 hashing rather
167
+ than relying on file mtimes. */
168
+ int showHdr, /* Identify the repository if there are changes */
169
+ int verboseFlag, /* Say "(none)" if there are no changes */
170
+ int cwdRelative /* Report relative to the current working dir */
171
+){
172
+ Blob report;
173
+ int vid;
174
+ blob_zero(&report);
175
+
176
+ vid = db_lget_int("checkout", 0);
177
+ vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0);
178
+ status_report(&report, "", 0, cwdRelative);
179
+ if( verboseFlag && blob_size(&report)==0 ){
180
+ blob_append(&report, " (none)\n", -1);
181
+ }
182
+ if( showHdr && blob_size(&report)>0 ){
183
+ fossil_print("Changes for %s at %s:\n", db_get("project-name","???"),
184
+ g.zLocalRoot);
185
+ }
186
+ blob_write_to_file(&report, "-");
187
+ blob_reset(&report);
188
+}
164189
165190
/*
166191
** COMMAND: changes
167192
**
168193
** Usage: %fossil changes ?OPTIONS?
@@ -182,31 +207,21 @@
182207
** -v|--verbose Say "(none)" if there are no changes
183208
**
184209
** See also: extras, ls, status
185210
*/
186211
void changes_cmd(void){
187
- Blob report;
188
- int vid;
189212
int useSha1sum = find_option("sha1sum", 0, 0)!=0;
190213
int showHdr = find_option("header",0,0)!=0;
191214
int verboseFlag = find_option("verbose","v",0)!=0;
192215
int cwdRelative = 0;
193216
db_must_be_within_tree();
194217
cwdRelative = determine_cwd_relative_option();
195
- blob_zero(&report);
196
- vid = db_lget_int("checkout", 0);
197
- vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0);
198
- status_report(&report, "", 0, cwdRelative);
199
- if( verboseFlag && blob_size(&report)==0 ){
200
- blob_append(&report, " (none)\n", -1);
201
- }
202
- if( showHdr && blob_size(&report)>0 ){
203
- fossil_print("Changes for %s at %s:\n", db_get("project-name","???"),
204
- g.zLocalRoot);
205
- }
206
- blob_write_to_file(&report, "-");
207
- blob_reset(&report);
218
+
219
+ /* We should be done with options.. */
220
+ verify_all_options();
221
+
222
+ print_changes(useSha1sum, showHdr, verboseFlag, cwdRelative);
208223
}
209224
210225
/*
211226
** COMMAND: status
212227
**
@@ -227,23 +242,32 @@
227242
**
228243
** See also: changes, extras, ls
229244
*/
230245
void status_cmd(void){
231246
int vid;
247
+ int useSha1sum = find_option("sha1sum", 0, 0)!=0;
248
+ int showHdr = find_option("header",0,0)!=0;
249
+ int verboseFlag = find_option("verbose","v",0)!=0;
250
+ int cwdRelative = 0;
232251
db_must_be_within_tree();
233252
/* 012345678901234 */
253
+ cwdRelative = determine_cwd_relative_option();
254
+
255
+ /* We should be done with options.. */
256
+ verify_all_options();
257
+
234258
fossil_print("repository: %s\n", db_repository_filename());
235259
fossil_print("local-root: %s\n", g.zLocalRoot);
236260
if( g.zConfigDbName ){
237261
fossil_print("config-db: %s\n", g.zConfigDbName);
238262
}
239263
vid = db_lget_int("checkout", 0);
240264
if( vid ){
241265
show_common_info(vid, "checkout:", 1, 1);
242266
}
243
- db_record_repository_filename(0);
244
- changes_cmd();
267
+ db_record_repository_filename(0);
268
+ print_changes(useSha1sum, showHdr, verboseFlag, cwdRelative);
245269
}
246270
247271
/*
248272
** COMMAND: ls
249273
**
@@ -454,10 +478,14 @@
454478
455479
if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
456480
capture_case_sensitive_option();
457481
db_must_be_within_tree();
458482
cwdRelative = determine_cwd_relative_option();
483
+
484
+ /* We should be done with options.. */
485
+ verify_all_options();
486
+
459487
if( zIgnoreFlag==0 ){
460488
zIgnoreFlag = db_get("ignore-glob", 0);
461489
}
462490
pIgnore = glob_create(zIgnoreFlag);
463491
locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore, 0);
464492
--- src/checkin.c
+++ src/checkin.c
@@ -159,10 +159,35 @@
159 int relPathOption = find_option("rel-paths", 0, 0)!=0;
160 if( absPathOption ){ relativePaths = 0; }
161 if( relPathOption ){ relativePaths = 1; }
162 return relativePaths;
163 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
165 /*
166 ** COMMAND: changes
167 **
168 ** Usage: %fossil changes ?OPTIONS?
@@ -182,31 +207,21 @@
182 ** -v|--verbose Say "(none)" if there are no changes
183 **
184 ** See also: extras, ls, status
185 */
186 void changes_cmd(void){
187 Blob report;
188 int vid;
189 int useSha1sum = find_option("sha1sum", 0, 0)!=0;
190 int showHdr = find_option("header",0,0)!=0;
191 int verboseFlag = find_option("verbose","v",0)!=0;
192 int cwdRelative = 0;
193 db_must_be_within_tree();
194 cwdRelative = determine_cwd_relative_option();
195 blob_zero(&report);
196 vid = db_lget_int("checkout", 0);
197 vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0);
198 status_report(&report, "", 0, cwdRelative);
199 if( verboseFlag && blob_size(&report)==0 ){
200 blob_append(&report, " (none)\n", -1);
201 }
202 if( showHdr && blob_size(&report)>0 ){
203 fossil_print("Changes for %s at %s:\n", db_get("project-name","???"),
204 g.zLocalRoot);
205 }
206 blob_write_to_file(&report, "-");
207 blob_reset(&report);
208 }
209
210 /*
211 ** COMMAND: status
212 **
@@ -227,23 +242,32 @@
227 **
228 ** See also: changes, extras, ls
229 */
230 void status_cmd(void){
231 int vid;
 
 
 
 
232 db_must_be_within_tree();
233 /* 012345678901234 */
 
 
 
 
 
234 fossil_print("repository: %s\n", db_repository_filename());
235 fossil_print("local-root: %s\n", g.zLocalRoot);
236 if( g.zConfigDbName ){
237 fossil_print("config-db: %s\n", g.zConfigDbName);
238 }
239 vid = db_lget_int("checkout", 0);
240 if( vid ){
241 show_common_info(vid, "checkout:", 1, 1);
242 }
243 db_record_repository_filename(0);
244 changes_cmd();
245 }
246
247 /*
248 ** COMMAND: ls
249 **
@@ -454,10 +478,14 @@
454
455 if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
456 capture_case_sensitive_option();
457 db_must_be_within_tree();
458 cwdRelative = determine_cwd_relative_option();
 
 
 
 
459 if( zIgnoreFlag==0 ){
460 zIgnoreFlag = db_get("ignore-glob", 0);
461 }
462 pIgnore = glob_create(zIgnoreFlag);
463 locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore, 0);
464
--- src/checkin.c
+++ src/checkin.c
@@ -159,10 +159,35 @@
159 int relPathOption = find_option("rel-paths", 0, 0)!=0;
160 if( absPathOption ){ relativePaths = 0; }
161 if( relPathOption ){ relativePaths = 1; }
162 return relativePaths;
163 }
164
165 void print_changes(
166 int useSha1sum, /* Verify file status using SHA1 hashing rather
167 than relying on file mtimes. */
168 int showHdr, /* Identify the repository if there are changes */
169 int verboseFlag, /* Say "(none)" if there are no changes */
170 int cwdRelative /* Report relative to the current working dir */
171 ){
172 Blob report;
173 int vid;
174 blob_zero(&report);
175
176 vid = db_lget_int("checkout", 0);
177 vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0);
178 status_report(&report, "", 0, cwdRelative);
179 if( verboseFlag && blob_size(&report)==0 ){
180 blob_append(&report, " (none)\n", -1);
181 }
182 if( showHdr && blob_size(&report)>0 ){
183 fossil_print("Changes for %s at %s:\n", db_get("project-name","???"),
184 g.zLocalRoot);
185 }
186 blob_write_to_file(&report, "-");
187 blob_reset(&report);
188 }
189
190 /*
191 ** COMMAND: changes
192 **
193 ** Usage: %fossil changes ?OPTIONS?
@@ -182,31 +207,21 @@
207 ** -v|--verbose Say "(none)" if there are no changes
208 **
209 ** See also: extras, ls, status
210 */
211 void changes_cmd(void){
 
 
212 int useSha1sum = find_option("sha1sum", 0, 0)!=0;
213 int showHdr = find_option("header",0,0)!=0;
214 int verboseFlag = find_option("verbose","v",0)!=0;
215 int cwdRelative = 0;
216 db_must_be_within_tree();
217 cwdRelative = determine_cwd_relative_option();
218
219 /* We should be done with options.. */
220 verify_all_options();
221
222 print_changes(useSha1sum, showHdr, verboseFlag, cwdRelative);
 
 
 
 
 
 
 
 
223 }
224
225 /*
226 ** COMMAND: status
227 **
@@ -227,23 +242,32 @@
242 **
243 ** See also: changes, extras, ls
244 */
245 void status_cmd(void){
246 int vid;
247 int useSha1sum = find_option("sha1sum", 0, 0)!=0;
248 int showHdr = find_option("header",0,0)!=0;
249 int verboseFlag = find_option("verbose","v",0)!=0;
250 int cwdRelative = 0;
251 db_must_be_within_tree();
252 /* 012345678901234 */
253 cwdRelative = determine_cwd_relative_option();
254
255 /* We should be done with options.. */
256 verify_all_options();
257
258 fossil_print("repository: %s\n", db_repository_filename());
259 fossil_print("local-root: %s\n", g.zLocalRoot);
260 if( g.zConfigDbName ){
261 fossil_print("config-db: %s\n", g.zConfigDbName);
262 }
263 vid = db_lget_int("checkout", 0);
264 if( vid ){
265 show_common_info(vid, "checkout:", 1, 1);
266 }
267 db_record_repository_filename(0);
268 print_changes(useSha1sum, showHdr, verboseFlag, cwdRelative);
269 }
270
271 /*
272 ** COMMAND: ls
273 **
@@ -454,10 +478,14 @@
478
479 if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
480 capture_case_sensitive_option();
481 db_must_be_within_tree();
482 cwdRelative = determine_cwd_relative_option();
483
484 /* We should be done with options.. */
485 verify_all_options();
486
487 if( zIgnoreFlag==0 ){
488 zIgnoreFlag = db_get("ignore-glob", 0);
489 }
490 pIgnore = glob_create(zIgnoreFlag);
491 locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore, 0);
492
+9 -1
--- src/checkout.c
+++ src/checkout.c
@@ -201,10 +201,14 @@
201201
forceFlag = find_option("force","f",0)!=0;
202202
forceMissingFlag = find_option("force-missing",0,0)!=0;
203203
keepFlag = find_option("keep",0,0)!=0;
204204
latestFlag = find_option("latest",0,0)!=0;
205205
promptFlag = find_option("prompt",0,0)!=0 || forceFlag==0;
206
+
207
+ /* We should be done with options.. */
208
+ verify_all_options();
209
+
206210
if( (latestFlag!=0 && g.argc!=2) || (latestFlag==0 && g.argc!=3) ){
207211
usage("VERSION|--latest ?--force? ?--keep?");
208212
}
209213
if( !forceFlag && unsaved_changes(0) ){
210214
fossil_fatal("there are unsaved changes in the current checkout");
@@ -292,10 +296,14 @@
292296
** See also: open
293297
*/
294298
void close_cmd(void){
295299
int forceFlag = find_option("force","f",0)!=0;
296300
db_must_be_within_tree();
301
+
302
+ /* We should be done with options.. */
303
+ verify_all_options();
304
+
297305
if( !forceFlag && unsaved_changes(0) ){
298306
fossil_fatal("there are unsaved changes in the current checkout");
299307
}
300308
if( !forceFlag
301309
&& db_exists("SELECT 1 FROM %s.sqlite_master WHERE name='stash'",
@@ -303,13 +311,13 @@
303311
&& db_exists("SELECT 1 FROM %s.stash", db_name("localdb"))
304312
){
305313
fossil_fatal("closing the checkout will delete your stash");
306314
}
307315
if( db_is_writeable("repository") ){
308
- char * zUnset = mprintf("ckout:%q", g.zLocalRoot);
316
+ char *zUnset = mprintf("ckout:%q", g.zLocalRoot);
309317
db_unset(zUnset, 1);
310318
fossil_free(zUnset);
311319
}
312320
unlink_local_database(1);
313321
db_close(1);
314322
unlink_local_database(0);
315323
}
316324
--- src/checkout.c
+++ src/checkout.c
@@ -201,10 +201,14 @@
201 forceFlag = find_option("force","f",0)!=0;
202 forceMissingFlag = find_option("force-missing",0,0)!=0;
203 keepFlag = find_option("keep",0,0)!=0;
204 latestFlag = find_option("latest",0,0)!=0;
205 promptFlag = find_option("prompt",0,0)!=0 || forceFlag==0;
 
 
 
 
206 if( (latestFlag!=0 && g.argc!=2) || (latestFlag==0 && g.argc!=3) ){
207 usage("VERSION|--latest ?--force? ?--keep?");
208 }
209 if( !forceFlag && unsaved_changes(0) ){
210 fossil_fatal("there are unsaved changes in the current checkout");
@@ -292,10 +296,14 @@
292 ** See also: open
293 */
294 void close_cmd(void){
295 int forceFlag = find_option("force","f",0)!=0;
296 db_must_be_within_tree();
 
 
 
 
297 if( !forceFlag && unsaved_changes(0) ){
298 fossil_fatal("there are unsaved changes in the current checkout");
299 }
300 if( !forceFlag
301 && db_exists("SELECT 1 FROM %s.sqlite_master WHERE name='stash'",
@@ -303,13 +311,13 @@
303 && db_exists("SELECT 1 FROM %s.stash", db_name("localdb"))
304 ){
305 fossil_fatal("closing the checkout will delete your stash");
306 }
307 if( db_is_writeable("repository") ){
308 char * zUnset = mprintf("ckout:%q", g.zLocalRoot);
309 db_unset(zUnset, 1);
310 fossil_free(zUnset);
311 }
312 unlink_local_database(1);
313 db_close(1);
314 unlink_local_database(0);
315 }
316
--- src/checkout.c
+++ src/checkout.c
@@ -201,10 +201,14 @@
201 forceFlag = find_option("force","f",0)!=0;
202 forceMissingFlag = find_option("force-missing",0,0)!=0;
203 keepFlag = find_option("keep",0,0)!=0;
204 latestFlag = find_option("latest",0,0)!=0;
205 promptFlag = find_option("prompt",0,0)!=0 || forceFlag==0;
206
207 /* We should be done with options.. */
208 verify_all_options();
209
210 if( (latestFlag!=0 && g.argc!=2) || (latestFlag==0 && g.argc!=3) ){
211 usage("VERSION|--latest ?--force? ?--keep?");
212 }
213 if( !forceFlag && unsaved_changes(0) ){
214 fossil_fatal("there are unsaved changes in the current checkout");
@@ -292,10 +296,14 @@
296 ** See also: open
297 */
298 void close_cmd(void){
299 int forceFlag = find_option("force","f",0)!=0;
300 db_must_be_within_tree();
301
302 /* We should be done with options.. */
303 verify_all_options();
304
305 if( !forceFlag && unsaved_changes(0) ){
306 fossil_fatal("there are unsaved changes in the current checkout");
307 }
308 if( !forceFlag
309 && db_exists("SELECT 1 FROM %s.sqlite_master WHERE name='stash'",
@@ -303,13 +311,13 @@
311 && db_exists("SELECT 1 FROM %s.stash", db_name("localdb"))
312 ){
313 fossil_fatal("closing the checkout will delete your stash");
314 }
315 if( db_is_writeable("repository") ){
316 char *zUnset = mprintf("ckout:%q", g.zLocalRoot);
317 db_unset(zUnset, 1);
318 fossil_free(zUnset);
319 }
320 unlink_local_database(1);
321 db_close(1);
322 unlink_local_database(0);
323 }
324
--- src/clone.c
+++ src/clone.c
@@ -127,10 +127,14 @@
127127
if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER;
128128
zHttpAuth = find_option("httpauth","B",1);
129129
zDefaultUser = find_option("admin-user","A",1);
130130
clone_ssh_find_options();
131131
url_proxy_options();
132
+
133
+ /* We should be done with options.. */
134
+ verify_all_options();
135
+
132136
if( g.argc < 4 ){
133137
usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
134138
}
135139
db_open_config(0);
136140
if( file_size(g.argv[3])>0 ){
137141
--- src/clone.c
+++ src/clone.c
@@ -127,10 +127,14 @@
127 if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER;
128 zHttpAuth = find_option("httpauth","B",1);
129 zDefaultUser = find_option("admin-user","A",1);
130 clone_ssh_find_options();
131 url_proxy_options();
 
 
 
 
132 if( g.argc < 4 ){
133 usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
134 }
135 db_open_config(0);
136 if( file_size(g.argv[3])>0 ){
137
--- src/clone.c
+++ src/clone.c
@@ -127,10 +127,14 @@
127 if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER;
128 zHttpAuth = find_option("httpauth","B",1);
129 zDefaultUser = find_option("admin-user","A",1);
130 clone_ssh_find_options();
131 url_proxy_options();
132
133 /* We should be done with options.. */
134 verify_all_options();
135
136 if( g.argc < 4 ){
137 usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
138 }
139 db_open_config(0);
140 if( file_size(g.argv[3])>0 ){
141
+123 -84
--- src/comformat.c
+++ src/comformat.c
@@ -31,13 +31,14 @@
3131
#endif
3232
3333
#if INTERFACE
3434
#define COMMENT_PRINT_NONE ((u32)0x00000000) /* No flags. */
3535
#define COMMENT_PRINT_LEGACY ((u32)0x00000001) /* Use legacy algorithm. */
36
-#define COMMENT_PRINT_TRIM_SPACE ((u32)0x00000002) /* Trim leading/trailing. */
37
-#define COMMENT_PRINT_WORD_BREAK ((u32)0x00000004) /* Break lines on words. */
38
-#define COMMENT_PRINT_ORIG_BREAK ((u32)0x00000008) /* Break before original. */
36
+#define COMMENT_PRINT_TRIM_CRLF ((u32)0x00000002) /* Trim leading CR/LF. */
37
+#define COMMENT_PRINT_TRIM_SPACE ((u32)0x00000004) /* Trim leading/trailing. */
38
+#define COMMENT_PRINT_WORD_BREAK ((u32)0x00000008) /* Break lines on words. */
39
+#define COMMENT_PRINT_ORIG_BREAK ((u32)0x00000010) /* Break before original. */
3940
#define COMMENT_PRINT_DEFAULT (COMMENT_PRINT_LEGACY) /* Defaults. */
4041
#endif
4142
4243
/*
4344
** This is the previous value used by most external callers when they
@@ -52,10 +53,51 @@
5253
** This is the number of spaces to print when a tab character is seen.
5354
*/
5455
#ifndef COMMENT_TAB_WIDTH
5556
# define COMMENT_TAB_WIDTH (8)
5657
#endif
58
+
59
+/*
60
+** This function sets the maximum number of characters to print per line
61
+** based on the detected terminal line width, if available; otherwise, it
62
+** uses the legacy default terminal line width minus the amount to indent.
63
+**
64
+** Zero is returned to indicate any failure. One is returned to indicate
65
+** the successful detection of the terminal line width. Negative one is
66
+** returned to indicate the terminal line width is using the hard-coded
67
+** legacy default value.
68
+*/
69
+static int comment_set_maxchars(
70
+ int indent,
71
+ int *pMaxChars
72
+){
73
+#if defined(_WIN32)
74
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
75
+ memset(&csbi, 0, sizeof(CONSOLE_SCREEN_BUFFER_INFO));
76
+ if( GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi) ){
77
+ *pMaxChars = csbi.srWindow.Right - csbi.srWindow.Left - indent;
78
+ return 1;
79
+ }
80
+ return 0;
81
+#elif defined(TIOCGWINSZ)
82
+ struct winsize w;
83
+ memset(&w, 0, sizeof(struct winsize));
84
+ if( ioctl(0, TIOCGWINSZ, &w)!=-1 ){
85
+ *pMaxChars = w.ws_col - indent;
86
+ return 1;
87
+ }
88
+ return 0;
89
+#else
90
+ /*
91
+ ** Fallback to using more-or-less the "legacy semantics" of hard-coding
92
+ ** the maximum line length to a value reasonable for the vast majority
93
+ ** of supported systems.
94
+ */
95
+ *pMaxChars = COMMENT_LEGACY_LINE_LENGTH - indent;
96
+ return -1;
97
+#endif
98
+}
5799
58100
/*
59101
** This function checks the current line being printed against the original
60102
** comment text. Upon matching, it emits a new line and updates the provided
61103
** character and line counts, if applicable.
@@ -101,20 +143,26 @@
101143
** the necessary indenting.
102144
*/
103145
static void comment_print_indent(
104146
const char *zLine, /* [in] The comment line being printed. */
105147
int indent, /* [in] Number of spaces to indent, zero for none. */
148
+ int trimCrLf, /* [in] Non-zero to trim leading/trailing CR/LF. */
106149
int trimSpace, /* [in] Non-zero to trim leading/trailing spaces. */
107150
int *piIndex /* [in/out] Pointer to first non-space character. */
108151
){
109152
if( indent>0 ){
110153
fossil_print("%*s", indent, "");
111
- if( trimSpace && zLine && piIndex ){
112
- int index = *piIndex;
154
+ }
155
+ if( zLine && piIndex ){
156
+ int index = *piIndex;
157
+ if( trimCrLf ){
158
+ while( zLine[index]=='\r' || zLine[index]=='\n' ){ index++; }
159
+ }
160
+ if( trimSpace ){
113161
while( fossil_isspace(zLine[index]) ){ index++; }
114
- *piIndex = index;
115162
}
163
+ *piIndex = index;
116164
}
117165
}
118166
119167
/*
120168
** This function prints one logical line of a comment, stopping when it hits
@@ -121,62 +169,72 @@
121169
** a new line -OR- runs out of space on the logical line.
122170
*/
123171
static void comment_print_line(
124172
const char *zOrigText, /* [in] Original comment text ONLY, may be NULL. */
125173
const char *zLine, /* [in] The comment line to print. */
126
- int indent, /* [in] Number of spaces to indent, zero for none. */
174
+ int origIndent, /* [in] Number of spaces to indent before the original
175
+ ** comment. */
176
+ int indent, /* [in] Number of spaces to indent, before the line
177
+ ** to print. */
127178
int lineChars, /* [in] Maximum number of characters to print. */
179
+ int trimCrLf, /* [in] Non-zero to trim leading/trailing CR/LF. */
128180
int trimSpace, /* [in] Non-zero to trim leading/trailing spaces. */
129181
int wordBreak, /* [in] Non-zero to try breaking on word boundaries. */
130182
int origBreak, /* [in] Non-zero to break before original comment. */
131183
int *pLineCnt, /* [in/out] Pointer to the total line count. */
132184
const char **pzLine /* [out] Pointer to the end of the logical line. */
133185
){
134186
int index = 0, charCnt = 0, lineCnt = 0, maxChars;
135187
if( !zLine ) return;
136188
if( lineChars<=0 ) return;
137
- comment_print_indent(zLine, indent, trimSpace, &index);
189
+ comment_print_indent(zLine, indent, trimCrLf, trimSpace, &index);
138190
maxChars = lineChars;
139191
for(;;){
192
+ int useChars = 1;
140193
char c = zLine[index];
141194
if( c==0 ){
142195
break;
143196
}else{
144197
if( origBreak && index>0 ){
145
- if( comment_check_orig(zOrigText, &zLine[index], &charCnt, &lineCnt) ){
198
+ const char *zCurrent = &zLine[index];
199
+ if( comment_check_orig(zOrigText, zCurrent, &charCnt, &lineCnt) ){
200
+ comment_print_indent(zCurrent, origIndent, trimCrLf, trimSpace,
201
+ &index);
146202
maxChars = lineChars;
147203
}
148204
}
149205
index++;
150206
}
151207
if( c=='\n' ){
152
- charCnt = 0;
153208
lineCnt++;
209
+ charCnt = 0;
210
+ useChars = 0;
154211
}else if( c=='\t' ){
155212
int nextIndex = comment_next_space(zLine, index);
156213
if( nextIndex<=0 || (nextIndex-index)>maxChars ){
157214
break;
158215
}
159216
charCnt++;
160
- if( maxChars<COMMENT_TAB_WIDTH ){
217
+ useChars = COMMENT_TAB_WIDTH;
218
+ if( maxChars<useChars ){
161219
fossil_print(" ");
162220
break;
163221
}
164
- maxChars -= COMMENT_TAB_WIDTH;
165222
}else if( wordBreak && fossil_isspace(c) ){
166223
int nextIndex = comment_next_space(zLine, index);
167224
if( nextIndex<=0 || (nextIndex-index)>maxChars ){
168225
break;
169226
}
170227
charCnt++;
171
- maxChars--;
172228
}else{
173229
charCnt++;
174
- maxChars--;
175230
}
231
+ assert( c!='\n' || charCnt==0 );
176232
fossil_print("%c", c);
233
+ maxChars -= useChars;
177234
if( maxChars==0 ) break;
235
+ assert( maxChars>0 );
178236
if( c=='\n' ) break;
179237
}
180238
if( charCnt>0 ){
181239
fossil_print("\n");
182240
lineCnt++;
@@ -203,49 +261,26 @@
203261
static int comment_print_legacy(
204262
const char *zText, /* The comment text to be printed. */
205263
int indent, /* Number of spaces to indent each non-initial line. */
206264
int width /* Maximum number of characters per line. */
207265
){
208
- int tlen = width - indent;
266
+ int maxChars = width - indent;
209267
int si, sk, i, k;
210268
int doIndent = 0;
211269
char *zBuf;
212270
char zBuffer[400];
213271
int lineCnt = 0;
214272
215
-#if defined(_WIN32)
216
- if( width<0 ){
217
- CONSOLE_SCREEN_BUFFER_INFO csbi;
218
- memset(&csbi, 0, sizeof(CONSOLE_SCREEN_BUFFER_INFO));
219
- if( GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi) ){
220
- tlen = csbi.srWindow.Right - csbi.srWindow.Left - indent;
221
- }
222
- }
223
-#elif defined(TIOCGWINSZ)
224
- if( width<0 ){
225
- struct winsize w;
226
- memset(&w, 0, sizeof(struct winsize));
227
- if( ioctl(0, TIOCGWINSZ, &w)!=-1 ){
228
- tlen = w.ws_col - indent;
229
- }
230
- }
231
-#else
232
- if( width<0 ){
233
- /*
234
- ** Fallback to using more-or-less the "legacy semantics" of hard-coding
235
- ** the maximum line length to a value reasonable for the vast majority
236
- ** of supported systems.
237
- */
238
- tlen = COMMENT_LEGACY_LINE_LENGTH - indent;
239
- }
240
-#endif
241
- if( zText==0 ) zText = "(NULL)";
242
- if( tlen<=0 ){
243
- tlen = strlen(zText);
244
- }
245
- if( tlen >= (sizeof(zBuffer)) ){
246
- zBuf = fossil_malloc(tlen+1);
273
+ if( width<0 ){
274
+ comment_set_maxchars(indent, &maxChars);
275
+ }
276
+ if( zText==0 ) zText = "(NULL)";
277
+ if( maxChars<=0 ){
278
+ maxChars = strlen(zText);
279
+ }
280
+ if( maxChars >= (sizeof(zBuffer)) ){
281
+ zBuf = fossil_malloc(maxChars+1);
247282
}else{
248283
zBuf = zBuffer;
249284
}
250285
for(;;){
251286
while( fossil_isspace(zText[0]) ){ zText++; }
@@ -255,11 +290,11 @@
255290
lineCnt = 1;
256291
}
257292
if( zBuf!=zBuffer) fossil_free(zBuf);
258293
return lineCnt;
259294
}
260
- for(sk=si=i=k=0; zText[i] && k<tlen; i++){
295
+ for(sk=si=i=k=0; zText[i] && k<maxChars; i++){
261296
char c = zText[i];
262297
if( fossil_isspace(c) ){
263298
si = i;
264299
sk = k;
265300
if( k==0 || zBuf[k-1]!=' ' ){
@@ -298,16 +333,26 @@
298333
**
299334
** COMMENT_PRINT_LEGACY: Forces use of the legacy comment printing
300335
** algorithm. For backward compatibility,
301336
** this is the default.
302337
**
303
-** COMMENT_PRINT_TRIM_SPACE: Trims leading and trailing spaces where
304
-** they do not materially impact formatting
305
-** (i.e. at the start of the comment string
306
-** -AND- right before each line indentation).
338
+** COMMENT_PRINT_TRIM_CRLF: Trims leading and trailing carriage-returns
339
+** and line-feeds where they do not materially
340
+** impact pre-existing formatting (i.e. at the
341
+** start of the comment string -AND- right
342
+** before line indentation). This flag does
343
+** not apply to the legacy comment printing
344
+** algorithm. This flag may be combined with
345
+** COMMENT_PRINT_TRIM_SPACE.
346
+**
347
+** COMMENT_PRINT_TRIM_SPACE: Trims leading and trailing spaces where they
348
+** do not materially impact the pre-existing
349
+** formatting (i.e. at the start of the comment
350
+** string -AND- right before line indentation).
307351
** This flag does not apply to the legacy
308
-** comment printing algorithm.
352
+** comment printing algorithm. This flag may
353
+** be combined with COMMENT_PRINT_TRIM_CRLF.
309354
**
310355
** COMMENT_PRINT_WORD_BREAK: Attempts to break lines on word boundaries
311356
** while honoring the logical line length.
312357
** If this flag is not specified, honoring the
313358
** logical line length may result in breaking
@@ -316,11 +361,11 @@
316361
** printing algorithm.
317362
**
318363
** COMMENT_PRINT_ORIG_BREAK: Looks for the original comment text within
319364
** the text being printed. Upon matching, a
320365
** new line will be emitted, thus preserving
321
-** more of the existing formatting.
366
+** more of the pre-existing formatting.
322367
**
323368
** Given a comment string, format that string for printing on a TTY.
324369
** Assume that the output cursors is indent spaces from the left margin
325370
** and that a single line can contain no more than 'width' characters.
326371
** Indent all subsequent lines by 'indent'.
@@ -334,45 +379,23 @@
334379
int width, /* Maximum number of characters per line. */
335380
int flags /* Zero or more "COMMENT_PRINT_*" flags. */
336381
){
337382
int maxChars = width - indent;
338383
int legacy = flags & COMMENT_PRINT_LEGACY;
384
+ int trimCrLf = flags & COMMENT_PRINT_TRIM_CRLF;
339385
int trimSpace = flags & COMMENT_PRINT_TRIM_SPACE;
340386
int wordBreak = flags & COMMENT_PRINT_WORD_BREAK;
341387
int origBreak = flags & COMMENT_PRINT_ORIG_BREAK;
342388
int lineCnt = 0;
343389
const char *zLine;
344390
345391
if( legacy ){
346392
return comment_print_legacy(zText, indent, width);
347393
}
348
-#if defined(_WIN32)
349
- if( width<0 ){
350
- CONSOLE_SCREEN_BUFFER_INFO csbi;
351
- memset(&csbi, 0, sizeof(CONSOLE_SCREEN_BUFFER_INFO));
352
- if( GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi) ){
353
- maxChars = csbi.srWindow.Right - csbi.srWindow.Left - indent;
354
- }
355
- }
356
-#elif defined(TIOCGWINSZ)
357
- if( width<0 ){
358
- struct winsize w;
359
- memset(&w, 0, sizeof(struct winsize));
360
- if( ioctl(0, TIOCGWINSZ, &w)!=-1 ){
361
- maxChars = w.ws_col - indent;
362
- }
363
- }
364
-#else
365
- if( width<0 ){
366
- /*
367
- ** Fallback to using more-or-less the "legacy semantics" of hard-coding
368
- ** the maximum line length to a value reasonable for the vast majority
369
- ** of supported systems.
370
- */
371
- maxChars = COMMENT_LEGACY_LINE_LENGTH - indent;
372
- }
373
-#endif
394
+ if( width<0 ){
395
+ comment_set_maxchars(indent, &maxChars);
396
+ }
374397
if( zText==0 ) zText = "(NULL)";
375398
if( maxChars<=0 ){
376399
maxChars = strlen(zText);
377400
}
378401
if( trimSpace ){
@@ -383,12 +406,13 @@
383406
lineCnt++;
384407
return lineCnt;
385408
}
386409
zLine = zText;
387410
for(;;){
388
- comment_print_line(zOrigText, zLine, zLine>zText ? indent : 0, maxChars,
389
- trimSpace, wordBreak, origBreak, &lineCnt, &zLine);
411
+ comment_print_line(zOrigText, zLine, indent, zLine>zText ? indent : 0,
412
+ maxChars, trimCrLf, trimSpace, wordBreak, origBreak,
413
+ &lineCnt, &zLine);
390414
if( !zLine || !zLine[0] ) break;
391415
}
392416
return lineCnt;
393417
}
394418
@@ -404,28 +428,35 @@
404428
** --file The comment text is really just a file name to
405429
** read it from.
406430
** --decode Decode the text using the same method used when
407431
** handling the value of a C-card from a manifest.
408432
** --legacy Use the legacy comment printing algorithm.
433
+** --trimcrlf Enable trimming of leading/trailing CR/LF.
409434
** --trimspace Enable trimming of leading/trailing spaces.
410435
** --wordbreak Attempt to break lines on word boundaries.
411436
** --origbreak Attempt to break when the original comment text
412437
** is detected.
438
+** --indent Number of spaces to indent (default (-1) is to
439
+** auto-detect). Zero means no indent.
413440
** -W|--width <num> Width of lines (default (-1) is to auto-detect).
414441
** Zero means no limit.
415442
*/
416443
void test_comment_format(void){
417444
const char *zWidth;
445
+ const char *zIndent;
418446
const char *zPrefix;
419447
char *zText;
420448
char *zOrigText;
421449
int indent, width;
422450
int fromFile = find_option("file", 0, 0)!=0;
423451
int decode = find_option("decode", 0, 0)!=0;
424452
int flags = COMMENT_PRINT_NONE;
425453
if( find_option("legacy", 0, 0) ){
426454
flags |= COMMENT_PRINT_LEGACY;
455
+ }
456
+ if( find_option("trimcrlf", 0, 0) ){
457
+ flags |= COMMENT_PRINT_TRIM_CRLF;
427458
}
428459
if( find_option("trimspace", 0, 0) ){
429460
flags |= COMMENT_PRINT_TRIM_SPACE;
430461
}
431462
if( find_option("wordbreak", 0, 0) ){
@@ -437,10 +468,16 @@
437468
zWidth = find_option("width","W",1);
438469
if( zWidth ){
439470
width = atoi(zWidth);
440471
}else{
441472
width = -1; /* automatic */
473
+ }
474
+ zIndent = find_option("indent",0,1);
475
+ if( zIndent ){
476
+ indent = atoi(zIndent);
477
+ }else{
478
+ indent = -1; /* automatic */
442479
}
443480
if( g.argc!=4 && g.argc!=5 ){
444481
usage("?OPTIONS? PREFIX TEXT ?ORIGTEXT?");
445482
}
446483
zPrefix = g.argv[2];
@@ -467,14 +504,16 @@
467504
if( zOrigText ){
468505
zOrigText = mprintf(fromFile ? "%z" : "%s", zOrigText);
469506
defossilize(zOrigText);
470507
}
471508
}
472
- indent = strlen(zPrefix);
473
- if( indent>0 ){
509
+ if( indent<0 ){
510
+ indent = strlen(zPrefix);
511
+ }
512
+ if( zPrefix && *zPrefix ){
474513
fossil_print("%s", zPrefix);
475514
}
476515
fossil_print("(%d lines output)\n",
477516
comment_print(zText, zOrigText, indent, width, flags));
478517
if( zOrigText && zOrigText!=g.argv[4] ) fossil_free(zOrigText);
479518
if( zText && zText!=g.argv[3] ) fossil_free(zText);
480519
}
481520
--- src/comformat.c
+++ src/comformat.c
@@ -31,13 +31,14 @@
31 #endif
32
33 #if INTERFACE
34 #define COMMENT_PRINT_NONE ((u32)0x00000000) /* No flags. */
35 #define COMMENT_PRINT_LEGACY ((u32)0x00000001) /* Use legacy algorithm. */
36 #define COMMENT_PRINT_TRIM_SPACE ((u32)0x00000002) /* Trim leading/trailing. */
37 #define COMMENT_PRINT_WORD_BREAK ((u32)0x00000004) /* Break lines on words. */
38 #define COMMENT_PRINT_ORIG_BREAK ((u32)0x00000008) /* Break before original. */
 
39 #define COMMENT_PRINT_DEFAULT (COMMENT_PRINT_LEGACY) /* Defaults. */
40 #endif
41
42 /*
43 ** This is the previous value used by most external callers when they
@@ -52,10 +53,51 @@
52 ** This is the number of spaces to print when a tab character is seen.
53 */
54 #ifndef COMMENT_TAB_WIDTH
55 # define COMMENT_TAB_WIDTH (8)
56 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
58 /*
59 ** This function checks the current line being printed against the original
60 ** comment text. Upon matching, it emits a new line and updates the provided
61 ** character and line counts, if applicable.
@@ -101,20 +143,26 @@
101 ** the necessary indenting.
102 */
103 static void comment_print_indent(
104 const char *zLine, /* [in] The comment line being printed. */
105 int indent, /* [in] Number of spaces to indent, zero for none. */
 
106 int trimSpace, /* [in] Non-zero to trim leading/trailing spaces. */
107 int *piIndex /* [in/out] Pointer to first non-space character. */
108 ){
109 if( indent>0 ){
110 fossil_print("%*s", indent, "");
111 if( trimSpace && zLine && piIndex ){
112 int index = *piIndex;
 
 
 
 
 
113 while( fossil_isspace(zLine[index]) ){ index++; }
114 *piIndex = index;
115 }
 
116 }
117 }
118
119 /*
120 ** This function prints one logical line of a comment, stopping when it hits
@@ -121,62 +169,72 @@
121 ** a new line -OR- runs out of space on the logical line.
122 */
123 static void comment_print_line(
124 const char *zOrigText, /* [in] Original comment text ONLY, may be NULL. */
125 const char *zLine, /* [in] The comment line to print. */
126 int indent, /* [in] Number of spaces to indent, zero for none. */
 
 
 
127 int lineChars, /* [in] Maximum number of characters to print. */
 
128 int trimSpace, /* [in] Non-zero to trim leading/trailing spaces. */
129 int wordBreak, /* [in] Non-zero to try breaking on word boundaries. */
130 int origBreak, /* [in] Non-zero to break before original comment. */
131 int *pLineCnt, /* [in/out] Pointer to the total line count. */
132 const char **pzLine /* [out] Pointer to the end of the logical line. */
133 ){
134 int index = 0, charCnt = 0, lineCnt = 0, maxChars;
135 if( !zLine ) return;
136 if( lineChars<=0 ) return;
137 comment_print_indent(zLine, indent, trimSpace, &index);
138 maxChars = lineChars;
139 for(;;){
 
140 char c = zLine[index];
141 if( c==0 ){
142 break;
143 }else{
144 if( origBreak && index>0 ){
145 if( comment_check_orig(zOrigText, &zLine[index], &charCnt, &lineCnt) ){
 
 
 
146 maxChars = lineChars;
147 }
148 }
149 index++;
150 }
151 if( c=='\n' ){
152 charCnt = 0;
153 lineCnt++;
 
 
154 }else if( c=='\t' ){
155 int nextIndex = comment_next_space(zLine, index);
156 if( nextIndex<=0 || (nextIndex-index)>maxChars ){
157 break;
158 }
159 charCnt++;
160 if( maxChars<COMMENT_TAB_WIDTH ){
 
161 fossil_print(" ");
162 break;
163 }
164 maxChars -= COMMENT_TAB_WIDTH;
165 }else if( wordBreak && fossil_isspace(c) ){
166 int nextIndex = comment_next_space(zLine, index);
167 if( nextIndex<=0 || (nextIndex-index)>maxChars ){
168 break;
169 }
170 charCnt++;
171 maxChars--;
172 }else{
173 charCnt++;
174 maxChars--;
175 }
 
176 fossil_print("%c", c);
 
177 if( maxChars==0 ) break;
 
178 if( c=='\n' ) break;
179 }
180 if( charCnt>0 ){
181 fossil_print("\n");
182 lineCnt++;
@@ -203,49 +261,26 @@
203 static int comment_print_legacy(
204 const char *zText, /* The comment text to be printed. */
205 int indent, /* Number of spaces to indent each non-initial line. */
206 int width /* Maximum number of characters per line. */
207 ){
208 int tlen = width - indent;
209 int si, sk, i, k;
210 int doIndent = 0;
211 char *zBuf;
212 char zBuffer[400];
213 int lineCnt = 0;
214
215 #if defined(_WIN32)
216 if( width<0 ){
217 CONSOLE_SCREEN_BUFFER_INFO csbi;
218 memset(&csbi, 0, sizeof(CONSOLE_SCREEN_BUFFER_INFO));
219 if( GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi) ){
220 tlen = csbi.srWindow.Right - csbi.srWindow.Left - indent;
221 }
222 }
223 #elif defined(TIOCGWINSZ)
224 if( width<0 ){
225 struct winsize w;
226 memset(&w, 0, sizeof(struct winsize));
227 if( ioctl(0, TIOCGWINSZ, &w)!=-1 ){
228 tlen = w.ws_col - indent;
229 }
230 }
231 #else
232 if( width<0 ){
233 /*
234 ** Fallback to using more-or-less the "legacy semantics" of hard-coding
235 ** the maximum line length to a value reasonable for the vast majority
236 ** of supported systems.
237 */
238 tlen = COMMENT_LEGACY_LINE_LENGTH - indent;
239 }
240 #endif
241 if( zText==0 ) zText = "(NULL)";
242 if( tlen<=0 ){
243 tlen = strlen(zText);
244 }
245 if( tlen >= (sizeof(zBuffer)) ){
246 zBuf = fossil_malloc(tlen+1);
247 }else{
248 zBuf = zBuffer;
249 }
250 for(;;){
251 while( fossil_isspace(zText[0]) ){ zText++; }
@@ -255,11 +290,11 @@
255 lineCnt = 1;
256 }
257 if( zBuf!=zBuffer) fossil_free(zBuf);
258 return lineCnt;
259 }
260 for(sk=si=i=k=0; zText[i] && k<tlen; i++){
261 char c = zText[i];
262 if( fossil_isspace(c) ){
263 si = i;
264 sk = k;
265 if( k==0 || zBuf[k-1]!=' ' ){
@@ -298,16 +333,26 @@
298 **
299 ** COMMENT_PRINT_LEGACY: Forces use of the legacy comment printing
300 ** algorithm. For backward compatibility,
301 ** this is the default.
302 **
303 ** COMMENT_PRINT_TRIM_SPACE: Trims leading and trailing spaces where
304 ** they do not materially impact formatting
305 ** (i.e. at the start of the comment string
306 ** -AND- right before each line indentation).
 
 
 
 
 
 
 
 
 
307 ** This flag does not apply to the legacy
308 ** comment printing algorithm.
 
309 **
310 ** COMMENT_PRINT_WORD_BREAK: Attempts to break lines on word boundaries
311 ** while honoring the logical line length.
312 ** If this flag is not specified, honoring the
313 ** logical line length may result in breaking
@@ -316,11 +361,11 @@
316 ** printing algorithm.
317 **
318 ** COMMENT_PRINT_ORIG_BREAK: Looks for the original comment text within
319 ** the text being printed. Upon matching, a
320 ** new line will be emitted, thus preserving
321 ** more of the existing formatting.
322 **
323 ** Given a comment string, format that string for printing on a TTY.
324 ** Assume that the output cursors is indent spaces from the left margin
325 ** and that a single line can contain no more than 'width' characters.
326 ** Indent all subsequent lines by 'indent'.
@@ -334,45 +379,23 @@
334 int width, /* Maximum number of characters per line. */
335 int flags /* Zero or more "COMMENT_PRINT_*" flags. */
336 ){
337 int maxChars = width - indent;
338 int legacy = flags & COMMENT_PRINT_LEGACY;
 
339 int trimSpace = flags & COMMENT_PRINT_TRIM_SPACE;
340 int wordBreak = flags & COMMENT_PRINT_WORD_BREAK;
341 int origBreak = flags & COMMENT_PRINT_ORIG_BREAK;
342 int lineCnt = 0;
343 const char *zLine;
344
345 if( legacy ){
346 return comment_print_legacy(zText, indent, width);
347 }
348 #if defined(_WIN32)
349 if( width<0 ){
350 CONSOLE_SCREEN_BUFFER_INFO csbi;
351 memset(&csbi, 0, sizeof(CONSOLE_SCREEN_BUFFER_INFO));
352 if( GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi) ){
353 maxChars = csbi.srWindow.Right - csbi.srWindow.Left - indent;
354 }
355 }
356 #elif defined(TIOCGWINSZ)
357 if( width<0 ){
358 struct winsize w;
359 memset(&w, 0, sizeof(struct winsize));
360 if( ioctl(0, TIOCGWINSZ, &w)!=-1 ){
361 maxChars = w.ws_col - indent;
362 }
363 }
364 #else
365 if( width<0 ){
366 /*
367 ** Fallback to using more-or-less the "legacy semantics" of hard-coding
368 ** the maximum line length to a value reasonable for the vast majority
369 ** of supported systems.
370 */
371 maxChars = COMMENT_LEGACY_LINE_LENGTH - indent;
372 }
373 #endif
374 if( zText==0 ) zText = "(NULL)";
375 if( maxChars<=0 ){
376 maxChars = strlen(zText);
377 }
378 if( trimSpace ){
@@ -383,12 +406,13 @@
383 lineCnt++;
384 return lineCnt;
385 }
386 zLine = zText;
387 for(;;){
388 comment_print_line(zOrigText, zLine, zLine>zText ? indent : 0, maxChars,
389 trimSpace, wordBreak, origBreak, &lineCnt, &zLine);
 
390 if( !zLine || !zLine[0] ) break;
391 }
392 return lineCnt;
393 }
394
@@ -404,28 +428,35 @@
404 ** --file The comment text is really just a file name to
405 ** read it from.
406 ** --decode Decode the text using the same method used when
407 ** handling the value of a C-card from a manifest.
408 ** --legacy Use the legacy comment printing algorithm.
 
409 ** --trimspace Enable trimming of leading/trailing spaces.
410 ** --wordbreak Attempt to break lines on word boundaries.
411 ** --origbreak Attempt to break when the original comment text
412 ** is detected.
 
 
413 ** -W|--width <num> Width of lines (default (-1) is to auto-detect).
414 ** Zero means no limit.
415 */
416 void test_comment_format(void){
417 const char *zWidth;
 
418 const char *zPrefix;
419 char *zText;
420 char *zOrigText;
421 int indent, width;
422 int fromFile = find_option("file", 0, 0)!=0;
423 int decode = find_option("decode", 0, 0)!=0;
424 int flags = COMMENT_PRINT_NONE;
425 if( find_option("legacy", 0, 0) ){
426 flags |= COMMENT_PRINT_LEGACY;
 
 
 
427 }
428 if( find_option("trimspace", 0, 0) ){
429 flags |= COMMENT_PRINT_TRIM_SPACE;
430 }
431 if( find_option("wordbreak", 0, 0) ){
@@ -437,10 +468,16 @@
437 zWidth = find_option("width","W",1);
438 if( zWidth ){
439 width = atoi(zWidth);
440 }else{
441 width = -1; /* automatic */
 
 
 
 
 
 
442 }
443 if( g.argc!=4 && g.argc!=5 ){
444 usage("?OPTIONS? PREFIX TEXT ?ORIGTEXT?");
445 }
446 zPrefix = g.argv[2];
@@ -467,14 +504,16 @@
467 if( zOrigText ){
468 zOrigText = mprintf(fromFile ? "%z" : "%s", zOrigText);
469 defossilize(zOrigText);
470 }
471 }
472 indent = strlen(zPrefix);
473 if( indent>0 ){
 
 
474 fossil_print("%s", zPrefix);
475 }
476 fossil_print("(%d lines output)\n",
477 comment_print(zText, zOrigText, indent, width, flags));
478 if( zOrigText && zOrigText!=g.argv[4] ) fossil_free(zOrigText);
479 if( zText && zText!=g.argv[3] ) fossil_free(zText);
480 }
481
--- src/comformat.c
+++ src/comformat.c
@@ -31,13 +31,14 @@
31 #endif
32
33 #if INTERFACE
34 #define COMMENT_PRINT_NONE ((u32)0x00000000) /* No flags. */
35 #define COMMENT_PRINT_LEGACY ((u32)0x00000001) /* Use legacy algorithm. */
36 #define COMMENT_PRINT_TRIM_CRLF ((u32)0x00000002) /* Trim leading CR/LF. */
37 #define COMMENT_PRINT_TRIM_SPACE ((u32)0x00000004) /* Trim leading/trailing. */
38 #define COMMENT_PRINT_WORD_BREAK ((u32)0x00000008) /* Break lines on words. */
39 #define COMMENT_PRINT_ORIG_BREAK ((u32)0x00000010) /* Break before original. */
40 #define COMMENT_PRINT_DEFAULT (COMMENT_PRINT_LEGACY) /* Defaults. */
41 #endif
42
43 /*
44 ** This is the previous value used by most external callers when they
@@ -52,10 +53,51 @@
53 ** This is the number of spaces to print when a tab character is seen.
54 */
55 #ifndef COMMENT_TAB_WIDTH
56 # define COMMENT_TAB_WIDTH (8)
57 #endif
58
59 /*
60 ** This function sets the maximum number of characters to print per line
61 ** based on the detected terminal line width, if available; otherwise, it
62 ** uses the legacy default terminal line width minus the amount to indent.
63 **
64 ** Zero is returned to indicate any failure. One is returned to indicate
65 ** the successful detection of the terminal line width. Negative one is
66 ** returned to indicate the terminal line width is using the hard-coded
67 ** legacy default value.
68 */
69 static int comment_set_maxchars(
70 int indent,
71 int *pMaxChars
72 ){
73 #if defined(_WIN32)
74 CONSOLE_SCREEN_BUFFER_INFO csbi;
75 memset(&csbi, 0, sizeof(CONSOLE_SCREEN_BUFFER_INFO));
76 if( GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi) ){
77 *pMaxChars = csbi.srWindow.Right - csbi.srWindow.Left - indent;
78 return 1;
79 }
80 return 0;
81 #elif defined(TIOCGWINSZ)
82 struct winsize w;
83 memset(&w, 0, sizeof(struct winsize));
84 if( ioctl(0, TIOCGWINSZ, &w)!=-1 ){
85 *pMaxChars = w.ws_col - indent;
86 return 1;
87 }
88 return 0;
89 #else
90 /*
91 ** Fallback to using more-or-less the "legacy semantics" of hard-coding
92 ** the maximum line length to a value reasonable for the vast majority
93 ** of supported systems.
94 */
95 *pMaxChars = COMMENT_LEGACY_LINE_LENGTH - indent;
96 return -1;
97 #endif
98 }
99
100 /*
101 ** This function checks the current line being printed against the original
102 ** comment text. Upon matching, it emits a new line and updates the provided
103 ** character and line counts, if applicable.
@@ -101,20 +143,26 @@
143 ** the necessary indenting.
144 */
145 static void comment_print_indent(
146 const char *zLine, /* [in] The comment line being printed. */
147 int indent, /* [in] Number of spaces to indent, zero for none. */
148 int trimCrLf, /* [in] Non-zero to trim leading/trailing CR/LF. */
149 int trimSpace, /* [in] Non-zero to trim leading/trailing spaces. */
150 int *piIndex /* [in/out] Pointer to first non-space character. */
151 ){
152 if( indent>0 ){
153 fossil_print("%*s", indent, "");
154 }
155 if( zLine && piIndex ){
156 int index = *piIndex;
157 if( trimCrLf ){
158 while( zLine[index]=='\r' || zLine[index]=='\n' ){ index++; }
159 }
160 if( trimSpace ){
161 while( fossil_isspace(zLine[index]) ){ index++; }
 
162 }
163 *piIndex = index;
164 }
165 }
166
167 /*
168 ** This function prints one logical line of a comment, stopping when it hits
@@ -121,62 +169,72 @@
169 ** a new line -OR- runs out of space on the logical line.
170 */
171 static void comment_print_line(
172 const char *zOrigText, /* [in] Original comment text ONLY, may be NULL. */
173 const char *zLine, /* [in] The comment line to print. */
174 int origIndent, /* [in] Number of spaces to indent before the original
175 ** comment. */
176 int indent, /* [in] Number of spaces to indent, before the line
177 ** to print. */
178 int lineChars, /* [in] Maximum number of characters to print. */
179 int trimCrLf, /* [in] Non-zero to trim leading/trailing CR/LF. */
180 int trimSpace, /* [in] Non-zero to trim leading/trailing spaces. */
181 int wordBreak, /* [in] Non-zero to try breaking on word boundaries. */
182 int origBreak, /* [in] Non-zero to break before original comment. */
183 int *pLineCnt, /* [in/out] Pointer to the total line count. */
184 const char **pzLine /* [out] Pointer to the end of the logical line. */
185 ){
186 int index = 0, charCnt = 0, lineCnt = 0, maxChars;
187 if( !zLine ) return;
188 if( lineChars<=0 ) return;
189 comment_print_indent(zLine, indent, trimCrLf, trimSpace, &index);
190 maxChars = lineChars;
191 for(;;){
192 int useChars = 1;
193 char c = zLine[index];
194 if( c==0 ){
195 break;
196 }else{
197 if( origBreak && index>0 ){
198 const char *zCurrent = &zLine[index];
199 if( comment_check_orig(zOrigText, zCurrent, &charCnt, &lineCnt) ){
200 comment_print_indent(zCurrent, origIndent, trimCrLf, trimSpace,
201 &index);
202 maxChars = lineChars;
203 }
204 }
205 index++;
206 }
207 if( c=='\n' ){
 
208 lineCnt++;
209 charCnt = 0;
210 useChars = 0;
211 }else if( c=='\t' ){
212 int nextIndex = comment_next_space(zLine, index);
213 if( nextIndex<=0 || (nextIndex-index)>maxChars ){
214 break;
215 }
216 charCnt++;
217 useChars = COMMENT_TAB_WIDTH;
218 if( maxChars<useChars ){
219 fossil_print(" ");
220 break;
221 }
 
222 }else if( wordBreak && fossil_isspace(c) ){
223 int nextIndex = comment_next_space(zLine, index);
224 if( nextIndex<=0 || (nextIndex-index)>maxChars ){
225 break;
226 }
227 charCnt++;
 
228 }else{
229 charCnt++;
 
230 }
231 assert( c!='\n' || charCnt==0 );
232 fossil_print("%c", c);
233 maxChars -= useChars;
234 if( maxChars==0 ) break;
235 assert( maxChars>0 );
236 if( c=='\n' ) break;
237 }
238 if( charCnt>0 ){
239 fossil_print("\n");
240 lineCnt++;
@@ -203,49 +261,26 @@
261 static int comment_print_legacy(
262 const char *zText, /* The comment text to be printed. */
263 int indent, /* Number of spaces to indent each non-initial line. */
264 int width /* Maximum number of characters per line. */
265 ){
266 int maxChars = width - indent;
267 int si, sk, i, k;
268 int doIndent = 0;
269 char *zBuf;
270 char zBuffer[400];
271 int lineCnt = 0;
272
273 if( width<0 ){
274 comment_set_maxchars(indent, &maxChars);
275 }
276 if( zText==0 ) zText = "(NULL)";
277 if( maxChars<=0 ){
278 maxChars = strlen(zText);
279 }
280 if( maxChars >= (sizeof(zBuffer)) ){
281 zBuf = fossil_malloc(maxChars+1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
282 }else{
283 zBuf = zBuffer;
284 }
285 for(;;){
286 while( fossil_isspace(zText[0]) ){ zText++; }
@@ -255,11 +290,11 @@
290 lineCnt = 1;
291 }
292 if( zBuf!=zBuffer) fossil_free(zBuf);
293 return lineCnt;
294 }
295 for(sk=si=i=k=0; zText[i] && k<maxChars; i++){
296 char c = zText[i];
297 if( fossil_isspace(c) ){
298 si = i;
299 sk = k;
300 if( k==0 || zBuf[k-1]!=' ' ){
@@ -298,16 +333,26 @@
333 **
334 ** COMMENT_PRINT_LEGACY: Forces use of the legacy comment printing
335 ** algorithm. For backward compatibility,
336 ** this is the default.
337 **
338 ** COMMENT_PRINT_TRIM_CRLF: Trims leading and trailing carriage-returns
339 ** and line-feeds where they do not materially
340 ** impact pre-existing formatting (i.e. at the
341 ** start of the comment string -AND- right
342 ** before line indentation). This flag does
343 ** not apply to the legacy comment printing
344 ** algorithm. This flag may be combined with
345 ** COMMENT_PRINT_TRIM_SPACE.
346 **
347 ** COMMENT_PRINT_TRIM_SPACE: Trims leading and trailing spaces where they
348 ** do not materially impact the pre-existing
349 ** formatting (i.e. at the start of the comment
350 ** string -AND- right before line indentation).
351 ** This flag does not apply to the legacy
352 ** comment printing algorithm. This flag may
353 ** be combined with COMMENT_PRINT_TRIM_CRLF.
354 **
355 ** COMMENT_PRINT_WORD_BREAK: Attempts to break lines on word boundaries
356 ** while honoring the logical line length.
357 ** If this flag is not specified, honoring the
358 ** logical line length may result in breaking
@@ -316,11 +361,11 @@
361 ** printing algorithm.
362 **
363 ** COMMENT_PRINT_ORIG_BREAK: Looks for the original comment text within
364 ** the text being printed. Upon matching, a
365 ** new line will be emitted, thus preserving
366 ** more of the pre-existing formatting.
367 **
368 ** Given a comment string, format that string for printing on a TTY.
369 ** Assume that the output cursors is indent spaces from the left margin
370 ** and that a single line can contain no more than 'width' characters.
371 ** Indent all subsequent lines by 'indent'.
@@ -334,45 +379,23 @@
379 int width, /* Maximum number of characters per line. */
380 int flags /* Zero or more "COMMENT_PRINT_*" flags. */
381 ){
382 int maxChars = width - indent;
383 int legacy = flags & COMMENT_PRINT_LEGACY;
384 int trimCrLf = flags & COMMENT_PRINT_TRIM_CRLF;
385 int trimSpace = flags & COMMENT_PRINT_TRIM_SPACE;
386 int wordBreak = flags & COMMENT_PRINT_WORD_BREAK;
387 int origBreak = flags & COMMENT_PRINT_ORIG_BREAK;
388 int lineCnt = 0;
389 const char *zLine;
390
391 if( legacy ){
392 return comment_print_legacy(zText, indent, width);
393 }
394 if( width<0 ){
395 comment_set_maxchars(indent, &maxChars);
396 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
397 if( zText==0 ) zText = "(NULL)";
398 if( maxChars<=0 ){
399 maxChars = strlen(zText);
400 }
401 if( trimSpace ){
@@ -383,12 +406,13 @@
406 lineCnt++;
407 return lineCnt;
408 }
409 zLine = zText;
410 for(;;){
411 comment_print_line(zOrigText, zLine, indent, zLine>zText ? indent : 0,
412 maxChars, trimCrLf, trimSpace, wordBreak, origBreak,
413 &lineCnt, &zLine);
414 if( !zLine || !zLine[0] ) break;
415 }
416 return lineCnt;
417 }
418
@@ -404,28 +428,35 @@
428 ** --file The comment text is really just a file name to
429 ** read it from.
430 ** --decode Decode the text using the same method used when
431 ** handling the value of a C-card from a manifest.
432 ** --legacy Use the legacy comment printing algorithm.
433 ** --trimcrlf Enable trimming of leading/trailing CR/LF.
434 ** --trimspace Enable trimming of leading/trailing spaces.
435 ** --wordbreak Attempt to break lines on word boundaries.
436 ** --origbreak Attempt to break when the original comment text
437 ** is detected.
438 ** --indent Number of spaces to indent (default (-1) is to
439 ** auto-detect). Zero means no indent.
440 ** -W|--width <num> Width of lines (default (-1) is to auto-detect).
441 ** Zero means no limit.
442 */
443 void test_comment_format(void){
444 const char *zWidth;
445 const char *zIndent;
446 const char *zPrefix;
447 char *zText;
448 char *zOrigText;
449 int indent, width;
450 int fromFile = find_option("file", 0, 0)!=0;
451 int decode = find_option("decode", 0, 0)!=0;
452 int flags = COMMENT_PRINT_NONE;
453 if( find_option("legacy", 0, 0) ){
454 flags |= COMMENT_PRINT_LEGACY;
455 }
456 if( find_option("trimcrlf", 0, 0) ){
457 flags |= COMMENT_PRINT_TRIM_CRLF;
458 }
459 if( find_option("trimspace", 0, 0) ){
460 flags |= COMMENT_PRINT_TRIM_SPACE;
461 }
462 if( find_option("wordbreak", 0, 0) ){
@@ -437,10 +468,16 @@
468 zWidth = find_option("width","W",1);
469 if( zWidth ){
470 width = atoi(zWidth);
471 }else{
472 width = -1; /* automatic */
473 }
474 zIndent = find_option("indent",0,1);
475 if( zIndent ){
476 indent = atoi(zIndent);
477 }else{
478 indent = -1; /* automatic */
479 }
480 if( g.argc!=4 && g.argc!=5 ){
481 usage("?OPTIONS? PREFIX TEXT ?ORIGTEXT?");
482 }
483 zPrefix = g.argv[2];
@@ -467,14 +504,16 @@
504 if( zOrigText ){
505 zOrigText = mprintf(fromFile ? "%z" : "%s", zOrigText);
506 defossilize(zOrigText);
507 }
508 }
509 if( indent<0 ){
510 indent = strlen(zPrefix);
511 }
512 if( zPrefix && *zPrefix ){
513 fossil_print("%s", zPrefix);
514 }
515 fossil_print("(%d lines output)\n",
516 comment_print(zText, zOrigText, indent, width, flags));
517 if( zOrigText && zOrigText!=g.argv[4] ) fossil_free(zOrigText);
518 if( zText && zText!=g.argv[3] ) fossil_free(zText);
519 }
520
+17 -6
--- src/db.c
+++ src/db.c
@@ -628,11 +628,11 @@
628628
** Execute a query. Return the first column of the first row
629629
** of the result set as a string. Space to hold the string is
630630
** obtained from malloc(). If the result set is empty, return
631631
** zDefault instead.
632632
*/
633
-char *db_text(char const *zDefault, const char *zSql, ...){
633
+char *db_text(const char *zDefault, const char *zSql, ...){
634634
va_list ap;
635635
Stmt s;
636636
char *z;
637637
va_start(ap, zSql);
638638
db_vprepare(&s, 0, zSql, ap);
@@ -1069,10 +1069,13 @@
10691069
**
10701070
** Error out if the repository cannot be opened.
10711071
*/
10721072
void db_find_and_open_repository(int bFlags, int nArgUsed){
10731073
const char *zRep = find_repository_option();
1074
+ if( zRep && file_isdir(zRep)==1 ){
1075
+ goto rep_not_found;
1076
+ }
10741077
if( zRep==0 && nArgUsed && g.argc==nArgUsed+1 ){
10751078
zRep = g.argv[nArgUsed];
10761079
}
10771080
if( zRep==0 ){
10781081
if( db_open_local(0)==0 ){
@@ -1479,10 +1482,14 @@
14791482
14801483
zTemplate = find_option("template",0,1);
14811484
zDate = find_option("date-override",0,1);
14821485
zDefaultUser = find_option("admin-user","A",1);
14831486
find_option("empty", 0, 0); /* deprecated */
1487
+
1488
+ /* We should be done with options.. */
1489
+ verify_all_options();
1490
+
14841491
if( g.argc!=3 ){
14851492
usage("REPOSITORY-NAME");
14861493
}
14871494
db_create_repository(g.argv[2]);
14881495
db_open_repository(g.argv[2]);
@@ -1932,17 +1939,17 @@
19321939
/*
19331940
** Returns non-0 if the database (which must be open) table identified
19341941
** by zTableName has a column named zColName (case-sensitive), else
19351942
** returns 0.
19361943
*/
1937
-int db_table_has_column( char const *zTableName, char const *zColName ){
1944
+int db_table_has_column(const char *zTableName, const char *zColName){
19381945
Stmt q = empty_Stmt;
19391946
int rc = 0;
19401947
db_prepare( &q, "PRAGMA table_info(%Q)", zTableName );
19411948
while(SQLITE_ROW == db_step(&q)){
19421949
/* Columns: (cid, name, type, notnull, dflt_value, pk) */
1943
- char const * zCol = db_column_text(&q, 1);
1950
+ const char *zCol = db_column_text(&q, 1);
19441951
if( 0==fossil_strcmp(zColName, zCol) ){
19451952
rc = 1;
19461953
break;
19471954
}
19481955
}
@@ -2033,10 +2040,14 @@
20332040
url_proxy_options();
20342041
emptyFlag = find_option("empty",0,0)!=0;
20352042
keepFlag = find_option("keep",0,0)!=0;
20362043
forceMissingFlag = find_option("force-missing",0,0)!=0;
20372044
allowNested = find_option("nested",0,0)!=0;
2045
+
2046
+ /* We should be done with options.. */
2047
+ verify_all_options();
2048
+
20382049
if( g.argc!=3 && g.argc!=4 ){
20392050
usage("REPOSITORY-FILENAME ?VERSION?");
20402051
}
20412052
if( !allowNested && db_open_local(0) ){
20422053
fossil_fatal("already within an open tree rooted at %s", g.zLocalRoot);
@@ -2133,16 +2144,16 @@
21332144
** The behaviour page doesn't use a special layout. It lists all
21342145
** set-commands and displays the 'set'-help as info.
21352146
*/
21362147
#if INTERFACE
21372148
struct stControlSettings {
2138
- char const *name; /* Name of the setting */
2139
- char const *var; /* Internal variable name used by db_set() */
2149
+ const char *name; /* Name of the setting */
2150
+ const char *var; /* Internal variable name used by db_set() */
21402151
int width; /* Width of display. 0 for boolean values. */
21412152
int versionable; /* Is this setting versionable? */
21422153
int forceTextArea; /* Force using a text area for display? */
2143
- char const *def; /* Default value */
2154
+ const char *def; /* Default value */
21442155
};
21452156
#endif /* INTERFACE */
21462157
struct stControlSettings const ctrlSettings[] = {
21472158
{ "access-log", 0, 0, 0, 0, "off" },
21482159
{ "allow-symlinks", 0, 0, 1, 0, "off" },
21492160
--- src/db.c
+++ src/db.c
@@ -628,11 +628,11 @@
628 ** Execute a query. Return the first column of the first row
629 ** of the result set as a string. Space to hold the string is
630 ** obtained from malloc(). If the result set is empty, return
631 ** zDefault instead.
632 */
633 char *db_text(char const *zDefault, const char *zSql, ...){
634 va_list ap;
635 Stmt s;
636 char *z;
637 va_start(ap, zSql);
638 db_vprepare(&s, 0, zSql, ap);
@@ -1069,10 +1069,13 @@
1069 **
1070 ** Error out if the repository cannot be opened.
1071 */
1072 void db_find_and_open_repository(int bFlags, int nArgUsed){
1073 const char *zRep = find_repository_option();
 
 
 
1074 if( zRep==0 && nArgUsed && g.argc==nArgUsed+1 ){
1075 zRep = g.argv[nArgUsed];
1076 }
1077 if( zRep==0 ){
1078 if( db_open_local(0)==0 ){
@@ -1479,10 +1482,14 @@
1479
1480 zTemplate = find_option("template",0,1);
1481 zDate = find_option("date-override",0,1);
1482 zDefaultUser = find_option("admin-user","A",1);
1483 find_option("empty", 0, 0); /* deprecated */
 
 
 
 
1484 if( g.argc!=3 ){
1485 usage("REPOSITORY-NAME");
1486 }
1487 db_create_repository(g.argv[2]);
1488 db_open_repository(g.argv[2]);
@@ -1932,17 +1939,17 @@
1932 /*
1933 ** Returns non-0 if the database (which must be open) table identified
1934 ** by zTableName has a column named zColName (case-sensitive), else
1935 ** returns 0.
1936 */
1937 int db_table_has_column( char const *zTableName, char const *zColName ){
1938 Stmt q = empty_Stmt;
1939 int rc = 0;
1940 db_prepare( &q, "PRAGMA table_info(%Q)", zTableName );
1941 while(SQLITE_ROW == db_step(&q)){
1942 /* Columns: (cid, name, type, notnull, dflt_value, pk) */
1943 char const * zCol = db_column_text(&q, 1);
1944 if( 0==fossil_strcmp(zColName, zCol) ){
1945 rc = 1;
1946 break;
1947 }
1948 }
@@ -2033,10 +2040,14 @@
2033 url_proxy_options();
2034 emptyFlag = find_option("empty",0,0)!=0;
2035 keepFlag = find_option("keep",0,0)!=0;
2036 forceMissingFlag = find_option("force-missing",0,0)!=0;
2037 allowNested = find_option("nested",0,0)!=0;
 
 
 
 
2038 if( g.argc!=3 && g.argc!=4 ){
2039 usage("REPOSITORY-FILENAME ?VERSION?");
2040 }
2041 if( !allowNested && db_open_local(0) ){
2042 fossil_fatal("already within an open tree rooted at %s", g.zLocalRoot);
@@ -2133,16 +2144,16 @@
2133 ** The behaviour page doesn't use a special layout. It lists all
2134 ** set-commands and displays the 'set'-help as info.
2135 */
2136 #if INTERFACE
2137 struct stControlSettings {
2138 char const *name; /* Name of the setting */
2139 char const *var; /* Internal variable name used by db_set() */
2140 int width; /* Width of display. 0 for boolean values. */
2141 int versionable; /* Is this setting versionable? */
2142 int forceTextArea; /* Force using a text area for display? */
2143 char const *def; /* Default value */
2144 };
2145 #endif /* INTERFACE */
2146 struct stControlSettings const ctrlSettings[] = {
2147 { "access-log", 0, 0, 0, 0, "off" },
2148 { "allow-symlinks", 0, 0, 1, 0, "off" },
2149
--- src/db.c
+++ src/db.c
@@ -628,11 +628,11 @@
628 ** Execute a query. Return the first column of the first row
629 ** of the result set as a string. Space to hold the string is
630 ** obtained from malloc(). If the result set is empty, return
631 ** zDefault instead.
632 */
633 char *db_text(const char *zDefault, const char *zSql, ...){
634 va_list ap;
635 Stmt s;
636 char *z;
637 va_start(ap, zSql);
638 db_vprepare(&s, 0, zSql, ap);
@@ -1069,10 +1069,13 @@
1069 **
1070 ** Error out if the repository cannot be opened.
1071 */
1072 void db_find_and_open_repository(int bFlags, int nArgUsed){
1073 const char *zRep = find_repository_option();
1074 if( zRep && file_isdir(zRep)==1 ){
1075 goto rep_not_found;
1076 }
1077 if( zRep==0 && nArgUsed && g.argc==nArgUsed+1 ){
1078 zRep = g.argv[nArgUsed];
1079 }
1080 if( zRep==0 ){
1081 if( db_open_local(0)==0 ){
@@ -1479,10 +1482,14 @@
1482
1483 zTemplate = find_option("template",0,1);
1484 zDate = find_option("date-override",0,1);
1485 zDefaultUser = find_option("admin-user","A",1);
1486 find_option("empty", 0, 0); /* deprecated */
1487
1488 /* We should be done with options.. */
1489 verify_all_options();
1490
1491 if( g.argc!=3 ){
1492 usage("REPOSITORY-NAME");
1493 }
1494 db_create_repository(g.argv[2]);
1495 db_open_repository(g.argv[2]);
@@ -1932,17 +1939,17 @@
1939 /*
1940 ** Returns non-0 if the database (which must be open) table identified
1941 ** by zTableName has a column named zColName (case-sensitive), else
1942 ** returns 0.
1943 */
1944 int db_table_has_column(const char *zTableName, const char *zColName){
1945 Stmt q = empty_Stmt;
1946 int rc = 0;
1947 db_prepare( &q, "PRAGMA table_info(%Q)", zTableName );
1948 while(SQLITE_ROW == db_step(&q)){
1949 /* Columns: (cid, name, type, notnull, dflt_value, pk) */
1950 const char *zCol = db_column_text(&q, 1);
1951 if( 0==fossil_strcmp(zColName, zCol) ){
1952 rc = 1;
1953 break;
1954 }
1955 }
@@ -2033,10 +2040,14 @@
2040 url_proxy_options();
2041 emptyFlag = find_option("empty",0,0)!=0;
2042 keepFlag = find_option("keep",0,0)!=0;
2043 forceMissingFlag = find_option("force-missing",0,0)!=0;
2044 allowNested = find_option("nested",0,0)!=0;
2045
2046 /* We should be done with options.. */
2047 verify_all_options();
2048
2049 if( g.argc!=3 && g.argc!=4 ){
2050 usage("REPOSITORY-FILENAME ?VERSION?");
2051 }
2052 if( !allowNested && db_open_local(0) ){
2053 fossil_fatal("already within an open tree rooted at %s", g.zLocalRoot);
@@ -2133,16 +2144,16 @@
2144 ** The behaviour page doesn't use a special layout. It lists all
2145 ** set-commands and displays the 'set'-help as info.
2146 */
2147 #if INTERFACE
2148 struct stControlSettings {
2149 const char *name; /* Name of the setting */
2150 const char *var; /* Internal variable name used by db_set() */
2151 int width; /* Width of display. 0 for boolean values. */
2152 int versionable; /* Is this setting versionable? */
2153 int forceTextArea; /* Force using a text area for display? */
2154 const char *def; /* Default value */
2155 };
2156 #endif /* INTERFACE */
2157 struct stControlSettings const ctrlSettings[] = {
2158 { "access-log", 0, 0, 0, 0, "off" },
2159 { "allow-symlinks", 0, 0, 1, 0, "off" },
2160
--- src/descendants.c
+++ src/descendants.c
@@ -130,10 +130,15 @@
130130
db_finalize(&ins);
131131
db_finalize(&isBr);
132132
db_finalize(&q1);
133133
bag_clear(&pending);
134134
bag_clear(&seen);
135
+ }else{
136
+ db_multi_exec(
137
+ "INSERT INTO leaves"
138
+ " SELECT leaf.rid FROM leaf"
139
+ );
135140
}
136141
if( closeMode==1 ){
137142
db_multi_exec(
138143
"DELETE FROM leaves WHERE rid IN"
139144
" (SELECT leaves.rid FROM leaves, tagxref"
@@ -312,10 +317,14 @@
312317
fossil_fatal("-W|--width value must be >20 or 0");
313318
}
314319
}else{
315320
width = -1;
316321
}
322
+
323
+ /* We should be done with options.. */
324
+ verify_all_options();
325
+
317326
if( g.argc==2 ){
318327
base = db_lget_int("checkout", 0);
319328
}else{
320329
base = name_to_typed_rid(g.argv[2], "ci");
321330
}
@@ -373,10 +382,14 @@
373382
}
374383
}else{
375384
width = -1;
376385
}
377386
db_find_and_open_repository(0,0);
387
+
388
+ /* We should be done with options.. */
389
+ verify_all_options();
390
+
378391
if( recomputeFlag ) leaf_rebuild();
379392
blob_zero(&sql);
380393
blob_append(&sql, timeline_query_for_tty(), -1);
381394
blob_appendf(&sql, " AND blob.rid IN leaf");
382395
if( showClosed ){
383396
--- src/descendants.c
+++ src/descendants.c
@@ -130,10 +130,15 @@
130 db_finalize(&ins);
131 db_finalize(&isBr);
132 db_finalize(&q1);
133 bag_clear(&pending);
134 bag_clear(&seen);
 
 
 
 
 
135 }
136 if( closeMode==1 ){
137 db_multi_exec(
138 "DELETE FROM leaves WHERE rid IN"
139 " (SELECT leaves.rid FROM leaves, tagxref"
@@ -312,10 +317,14 @@
312 fossil_fatal("-W|--width value must be >20 or 0");
313 }
314 }else{
315 width = -1;
316 }
 
 
 
 
317 if( g.argc==2 ){
318 base = db_lget_int("checkout", 0);
319 }else{
320 base = name_to_typed_rid(g.argv[2], "ci");
321 }
@@ -373,10 +382,14 @@
373 }
374 }else{
375 width = -1;
376 }
377 db_find_and_open_repository(0,0);
 
 
 
 
378 if( recomputeFlag ) leaf_rebuild();
379 blob_zero(&sql);
380 blob_append(&sql, timeline_query_for_tty(), -1);
381 blob_appendf(&sql, " AND blob.rid IN leaf");
382 if( showClosed ){
383
--- src/descendants.c
+++ src/descendants.c
@@ -130,10 +130,15 @@
130 db_finalize(&ins);
131 db_finalize(&isBr);
132 db_finalize(&q1);
133 bag_clear(&pending);
134 bag_clear(&seen);
135 }else{
136 db_multi_exec(
137 "INSERT INTO leaves"
138 " SELECT leaf.rid FROM leaf"
139 );
140 }
141 if( closeMode==1 ){
142 db_multi_exec(
143 "DELETE FROM leaves WHERE rid IN"
144 " (SELECT leaves.rid FROM leaves, tagxref"
@@ -312,10 +317,14 @@
317 fossil_fatal("-W|--width value must be >20 or 0");
318 }
319 }else{
320 width = -1;
321 }
322
323 /* We should be done with options.. */
324 verify_all_options();
325
326 if( g.argc==2 ){
327 base = db_lget_int("checkout", 0);
328 }else{
329 base = name_to_typed_rid(g.argv[2], "ci");
330 }
@@ -373,10 +382,14 @@
382 }
383 }else{
384 width = -1;
385 }
386 db_find_and_open_repository(0,0);
387
388 /* We should be done with options.. */
389 verify_all_options();
390
391 if( recomputeFlag ) leaf_rebuild();
392 blob_zero(&sql);
393 blob_append(&sql, timeline_query_for_tty(), -1);
394 blob_appendf(&sql, " AND blob.rid IN leaf");
395 if( showClosed ){
396
+4
--- src/diff.c
+++ src/diff.c
@@ -2434,10 +2434,14 @@
24342434
if( find_option("ignore-all-space","w",0)!=0 ){
24352435
annFlags = DIFF_IGNORE_ALLWS; /* stronger than DIFF_IGNORE_EOLWS */
24362436
}
24372437
fileVers = find_option("filevers",0,0)!=0;
24382438
db_must_be_within_tree();
2439
+
2440
+ /* We should be done with options.. */
2441
+ verify_all_options();
2442
+
24392443
if( g.argc<3 ) {
24402444
usage("FILENAME");
24412445
}
24422446
file_tree_name(g.argv[2], &treename, 1);
24432447
zFilename = blob_str(&treename);
24442448
--- src/diff.c
+++ src/diff.c
@@ -2434,10 +2434,14 @@
2434 if( find_option("ignore-all-space","w",0)!=0 ){
2435 annFlags = DIFF_IGNORE_ALLWS; /* stronger than DIFF_IGNORE_EOLWS */
2436 }
2437 fileVers = find_option("filevers",0,0)!=0;
2438 db_must_be_within_tree();
 
 
 
 
2439 if( g.argc<3 ) {
2440 usage("FILENAME");
2441 }
2442 file_tree_name(g.argv[2], &treename, 1);
2443 zFilename = blob_str(&treename);
2444
--- src/diff.c
+++ src/diff.c
@@ -2434,10 +2434,14 @@
2434 if( find_option("ignore-all-space","w",0)!=0 ){
2435 annFlags = DIFF_IGNORE_ALLWS; /* stronger than DIFF_IGNORE_EOLWS */
2436 }
2437 fileVers = find_option("filevers",0,0)!=0;
2438 db_must_be_within_tree();
2439
2440 /* We should be done with options.. */
2441 verify_all_options();
2442
2443 if( g.argc<3 ) {
2444 usage("FILENAME");
2445 }
2446 file_tree_name(g.argv[2], &treename, 1);
2447 zFilename = blob_str(&treename);
2448
+16 -2
--- src/finfo.c
+++ src/finfo.c
@@ -63,10 +63,13 @@
6363
if( find_option("status","s",0) ){
6464
Stmt q;
6565
Blob line;
6666
Blob fname;
6767
int vid;
68
+
69
+ /* We should be done with options.. */
70
+ verify_all_options();
6871
6972
if( g.argc!=3 ) usage("-s|--status FILENAME");
7073
vid = db_lget_int("checkout", 0);
7174
if( vid==0 ){
7275
fossil_fatal("no checkout to finfo files in");
@@ -115,10 +118,13 @@
115118
blob_reset(&line);
116119
}else if( find_option("print","p",0) ){
117120
Blob record;
118121
Blob fname;
119122
const char *zRevision = find_option("revision", "r", 1);
123
+
124
+ /* We should be done with options.. */
125
+ verify_all_options();
120126
121127
file_tree_name(g.argv[2], &fname, 1);
122128
if( zRevision ){
123129
historical_version_of_file(zRevision, blob_str(&fname), &record, 0,0,0,0);
124130
}else{
@@ -158,10 +164,14 @@
158164
fossil_fatal("-W|--width value must be >22 or 0");
159165
}
160166
}else{
161167
iWidth = -1;
162168
}
169
+
170
+ /* We should be done with options.. */
171
+ verify_all_options();
172
+
163173
if( g.argc!=3 ){
164174
usage("?-l|--log? ?-b|--brief? FILENAME");
165175
}
166176
file_tree_name(g.argv[2], &fname, 1);
167177
rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s",
@@ -199,15 +209,15 @@
199209
const char *zBr = db_column_text(&q, 5);
200210
char *zOut;
201211
if( zBr==0 ) zBr = "trunk";
202212
if( iBrief ){
203213
fossil_print("%s ", zDate);
204
- zOut = sqlite3_mprintf(
214
+ zOut = mprintf(
205215
"[%S] %s (user: %s, artifact: [%S], branch: %s)",
206216
zCiUuid, zCom, zUser, zFileUuid, zBr);
207217
comment_print(zOut, zCom, 11, iWidth, g.comFmtFlags);
208
- sqlite3_free(zOut);
218
+ fossil_free(zOut);
209219
}else{
210220
blob_reset(&line);
211221
blob_appendf(&line, "%.10s ", zCiUuid);
212222
blob_appendf(&line, "%.10s ", zDate);
213223
blob_appendf(&line, "%8.8s ", zUser);
@@ -241,10 +251,14 @@
241251
int rc;
242252
Blob content, fname;
243253
const char *zRev;
244254
db_find_and_open_repository(0, 0);
245255
zRev = find_option("r","r",1);
256
+
257
+ /* We should be done with options.. */
258
+ verify_all_options();
259
+
246260
for(i=2; i<g.argc; i++){
247261
file_tree_name(g.argv[i], &fname, 1);
248262
blob_zero(&content);
249263
rc = historical_version_of_file(zRev, blob_str(&fname), &content, 0,0,0,0);
250264
if( rc==0 ){
251265
--- src/finfo.c
+++ src/finfo.c
@@ -63,10 +63,13 @@
63 if( find_option("status","s",0) ){
64 Stmt q;
65 Blob line;
66 Blob fname;
67 int vid;
 
 
 
68
69 if( g.argc!=3 ) usage("-s|--status FILENAME");
70 vid = db_lget_int("checkout", 0);
71 if( vid==0 ){
72 fossil_fatal("no checkout to finfo files in");
@@ -115,10 +118,13 @@
115 blob_reset(&line);
116 }else if( find_option("print","p",0) ){
117 Blob record;
118 Blob fname;
119 const char *zRevision = find_option("revision", "r", 1);
 
 
 
120
121 file_tree_name(g.argv[2], &fname, 1);
122 if( zRevision ){
123 historical_version_of_file(zRevision, blob_str(&fname), &record, 0,0,0,0);
124 }else{
@@ -158,10 +164,14 @@
158 fossil_fatal("-W|--width value must be >22 or 0");
159 }
160 }else{
161 iWidth = -1;
162 }
 
 
 
 
163 if( g.argc!=3 ){
164 usage("?-l|--log? ?-b|--brief? FILENAME");
165 }
166 file_tree_name(g.argv[2], &fname, 1);
167 rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s",
@@ -199,15 +209,15 @@
199 const char *zBr = db_column_text(&q, 5);
200 char *zOut;
201 if( zBr==0 ) zBr = "trunk";
202 if( iBrief ){
203 fossil_print("%s ", zDate);
204 zOut = sqlite3_mprintf(
205 "[%S] %s (user: %s, artifact: [%S], branch: %s)",
206 zCiUuid, zCom, zUser, zFileUuid, zBr);
207 comment_print(zOut, zCom, 11, iWidth, g.comFmtFlags);
208 sqlite3_free(zOut);
209 }else{
210 blob_reset(&line);
211 blob_appendf(&line, "%.10s ", zCiUuid);
212 blob_appendf(&line, "%.10s ", zDate);
213 blob_appendf(&line, "%8.8s ", zUser);
@@ -241,10 +251,14 @@
241 int rc;
242 Blob content, fname;
243 const char *zRev;
244 db_find_and_open_repository(0, 0);
245 zRev = find_option("r","r",1);
 
 
 
 
246 for(i=2; i<g.argc; i++){
247 file_tree_name(g.argv[i], &fname, 1);
248 blob_zero(&content);
249 rc = historical_version_of_file(zRev, blob_str(&fname), &content, 0,0,0,0);
250 if( rc==0 ){
251
--- src/finfo.c
+++ src/finfo.c
@@ -63,10 +63,13 @@
63 if( find_option("status","s",0) ){
64 Stmt q;
65 Blob line;
66 Blob fname;
67 int vid;
68
69 /* We should be done with options.. */
70 verify_all_options();
71
72 if( g.argc!=3 ) usage("-s|--status FILENAME");
73 vid = db_lget_int("checkout", 0);
74 if( vid==0 ){
75 fossil_fatal("no checkout to finfo files in");
@@ -115,10 +118,13 @@
118 blob_reset(&line);
119 }else if( find_option("print","p",0) ){
120 Blob record;
121 Blob fname;
122 const char *zRevision = find_option("revision", "r", 1);
123
124 /* We should be done with options.. */
125 verify_all_options();
126
127 file_tree_name(g.argv[2], &fname, 1);
128 if( zRevision ){
129 historical_version_of_file(zRevision, blob_str(&fname), &record, 0,0,0,0);
130 }else{
@@ -158,10 +164,14 @@
164 fossil_fatal("-W|--width value must be >22 or 0");
165 }
166 }else{
167 iWidth = -1;
168 }
169
170 /* We should be done with options.. */
171 verify_all_options();
172
173 if( g.argc!=3 ){
174 usage("?-l|--log? ?-b|--brief? FILENAME");
175 }
176 file_tree_name(g.argv[2], &fname, 1);
177 rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s",
@@ -199,15 +209,15 @@
209 const char *zBr = db_column_text(&q, 5);
210 char *zOut;
211 if( zBr==0 ) zBr = "trunk";
212 if( iBrief ){
213 fossil_print("%s ", zDate);
214 zOut = mprintf(
215 "[%S] %s (user: %s, artifact: [%S], branch: %s)",
216 zCiUuid, zCom, zUser, zFileUuid, zBr);
217 comment_print(zOut, zCom, 11, iWidth, g.comFmtFlags);
218 fossil_free(zOut);
219 }else{
220 blob_reset(&line);
221 blob_appendf(&line, "%.10s ", zCiUuid);
222 blob_appendf(&line, "%.10s ", zDate);
223 blob_appendf(&line, "%8.8s ", zUser);
@@ -241,10 +251,14 @@
251 int rc;
252 Blob content, fname;
253 const char *zRev;
254 db_find_and_open_repository(0, 0);
255 zRev = find_option("r","r",1);
256
257 /* We should be done with options.. */
258 verify_all_options();
259
260 for(i=2; i<g.argc; i++){
261 file_tree_name(g.argv[i], &fname, 1);
262 blob_zero(&content);
263 rc = historical_version_of_file(zRev, blob_str(&fname), &content, 0,0,0,0);
264 if( rc==0 ){
265
+1 -1
--- src/graph.c
+++ src/graph.c
@@ -34,11 +34,11 @@
3434
int rid; /* The rid for the check-in */
3535
i8 nParent; /* Number of parents */
3636
int *aParent; /* Array of parents. 0 element is primary .*/
3737
char *zBranch; /* Branch name */
3838
char *zBgClr; /* Background Color */
39
- char zUuid[17]; /* Check-in for file ID */
39
+ char zUuid[41]; /* Check-in for file ID */
4040
4141
GraphRow *pNext; /* Next row down in the list of all rows */
4242
GraphRow *pPrev; /* Previous row */
4343
4444
int idx; /* Row index. First is 1. 0 used for "none" */
4545
--- src/graph.c
+++ src/graph.c
@@ -34,11 +34,11 @@
34 int rid; /* The rid for the check-in */
35 i8 nParent; /* Number of parents */
36 int *aParent; /* Array of parents. 0 element is primary .*/
37 char *zBranch; /* Branch name */
38 char *zBgClr; /* Background Color */
39 char zUuid[17]; /* Check-in for file ID */
40
41 GraphRow *pNext; /* Next row down in the list of all rows */
42 GraphRow *pPrev; /* Previous row */
43
44 int idx; /* Row index. First is 1. 0 used for "none" */
45
--- src/graph.c
+++ src/graph.c
@@ -34,11 +34,11 @@
34 int rid; /* The rid for the check-in */
35 i8 nParent; /* Number of parents */
36 int *aParent; /* Array of parents. 0 element is primary .*/
37 char *zBranch; /* Branch name */
38 char *zBgClr; /* Background Color */
39 char zUuid[41]; /* Check-in for file ID */
40
41 GraphRow *pNext; /* Next row down in the list of all rows */
42 GraphRow *pPrev; /* Previous row */
43
44 int idx; /* Row index. First is 1. 0 used for "none" */
45
+9 -1
--- src/info.c
+++ src/info.c
@@ -197,10 +197,14 @@
197197
i64 fsize;
198198
int verboseFlag = find_option("verbose","v",0)!=0;
199199
if( !verboseFlag ){
200200
verboseFlag = find_option("detail","l",0)!=0; /* deprecated */
201201
}
202
+
203
+ /* We should be done with options.. */
204
+ verify_all_options();
205
+
202206
if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
203207
db_open_config(0);
204208
db_record_repository_filename(g.argv[2]);
205209
db_open_repository(g.argv[2]);
206210
fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
@@ -987,10 +991,12 @@
987991
if(zGlob && !*zGlob){
988992
zGlob = NULL;
989993
}
990994
diffFlags = construct_diff_flags(verboseFlag, sideBySide);
991995
zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
996
+ style_submenu_element("Path","path",
997
+ "%R/timeline?me=%T&you=%T", zFrom, zTo);
992998
if( sideBySide || verboseFlag ){
993999
style_submenu_element("Hide Diff", "hidediff",
9941000
"%R/vdiff?from=%T&to=%T&sbs=0%s%T%s",
9951001
zFrom, zTo,
9961002
zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
@@ -2100,11 +2106,13 @@
21002106
}
21012107
@ %h(aColor[i].zCName)</label>&nbsp;
21022108
@ <input type="text" name="%s(zIdCustom)"
21032109
@ id="%s(zIdCustom)" class="checkinUserColor"
21042110
@ value="%h(stdClrFound?"":zDefaultColor)"
2105
- @ onfocus="this.form.elements['%s(zId)'][%d(nColor)].checked = true;" />
2111
+ @ onfocus="this.form.elements['%s(zId)'][%d(nColor)].checked = true;"
2112
+ @ onload="this.blur();"
2113
+ @ onblur="this.parentElement.style.backgroundColor = this.value ? ('#'+this.value.replace('#','')) : '';" />
21062114
@ </td>
21072115
@ </tr>
21082116
@ </table>
21092117
}
21102118
21112119
--- src/info.c
+++ src/info.c
@@ -197,10 +197,14 @@
197 i64 fsize;
198 int verboseFlag = find_option("verbose","v",0)!=0;
199 if( !verboseFlag ){
200 verboseFlag = find_option("detail","l",0)!=0; /* deprecated */
201 }
 
 
 
 
202 if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
203 db_open_config(0);
204 db_record_repository_filename(g.argv[2]);
205 db_open_repository(g.argv[2]);
206 fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
@@ -987,10 +991,12 @@
987 if(zGlob && !*zGlob){
988 zGlob = NULL;
989 }
990 diffFlags = construct_diff_flags(verboseFlag, sideBySide);
991 zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
 
 
992 if( sideBySide || verboseFlag ){
993 style_submenu_element("Hide Diff", "hidediff",
994 "%R/vdiff?from=%T&to=%T&sbs=0%s%T%s",
995 zFrom, zTo,
996 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
@@ -2100,11 +2106,13 @@
2100 }
2101 @ %h(aColor[i].zCName)</label>&nbsp;
2102 @ <input type="text" name="%s(zIdCustom)"
2103 @ id="%s(zIdCustom)" class="checkinUserColor"
2104 @ value="%h(stdClrFound?"":zDefaultColor)"
2105 @ onfocus="this.form.elements['%s(zId)'][%d(nColor)].checked = true;" />
 
 
2106 @ </td>
2107 @ </tr>
2108 @ </table>
2109 }
2110
2111
--- src/info.c
+++ src/info.c
@@ -197,10 +197,14 @@
197 i64 fsize;
198 int verboseFlag = find_option("verbose","v",0)!=0;
199 if( !verboseFlag ){
200 verboseFlag = find_option("detail","l",0)!=0; /* deprecated */
201 }
202
203 /* We should be done with options.. */
204 verify_all_options();
205
206 if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
207 db_open_config(0);
208 db_record_repository_filename(g.argv[2]);
209 db_open_repository(g.argv[2]);
210 fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
@@ -987,10 +991,12 @@
991 if(zGlob && !*zGlob){
992 zGlob = NULL;
993 }
994 diffFlags = construct_diff_flags(verboseFlag, sideBySide);
995 zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
996 style_submenu_element("Path","path",
997 "%R/timeline?me=%T&you=%T", zFrom, zTo);
998 if( sideBySide || verboseFlag ){
999 style_submenu_element("Hide Diff", "hidediff",
1000 "%R/vdiff?from=%T&to=%T&sbs=0%s%T%s",
1001 zFrom, zTo,
1002 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
@@ -2100,11 +2106,13 @@
2106 }
2107 @ %h(aColor[i].zCName)</label>&nbsp;
2108 @ <input type="text" name="%s(zIdCustom)"
2109 @ id="%s(zIdCustom)" class="checkinUserColor"
2110 @ value="%h(stdClrFound?"":zDefaultColor)"
2111 @ onfocus="this.form.elements['%s(zId)'][%d(nColor)].checked = true;"
2112 @ onload="this.blur();"
2113 @ onblur="this.parentElement.style.backgroundColor = this.value ? ('#'+this.value.replace('#','')) : '';" />
2114 @ </td>
2115 @ </tr>
2116 @ </table>
2117 }
2118
2119
+14 -14
--- src/login.c
+++ src/login.c
@@ -208,12 +208,12 @@
208208
** On serious (DB-level) error it will probably exit.
209209
**
210210
** zPassword may be either the plain-text form or the encrypted
211211
** form of the user's password.
212212
*/
213
-int login_search_uid(char const *zUsername, char const *zPasswd){
214
- char * zSha1Pw = sha1_shared_secret(zPasswd, zUsername, 0);
213
+int login_search_uid(const char *zUsername, const char *zPasswd){
214
+ char *zSha1Pw = sha1_shared_secret(zPasswd, zUsername, 0);
215215
int const uid =
216216
db_int(0,
217217
"SELECT uid FROM user"
218218
" WHERE login=%Q"
219219
" AND length(cap)>0 AND length(pw)>0"
@@ -231,12 +231,12 @@
231231
** The zHash parameter must be a random value which must be
232232
** subsequently stored in user.cookie for later validation.
233233
**
234234
** The returned memory should be free()d after use.
235235
*/
236
-char * login_gen_user_cookie_value(char const *zUsername, char const * zHash){
237
- char * zProjCode = db_get("project-code",NULL);
236
+char *login_gen_user_cookie_value(const char *zUsername, const char *zHash){
237
+ char *zProjCode = db_get("project-code",NULL);
238238
char *zCode = abbreviated_project_code(zProjCode);
239239
free(zProjCode);
240240
assert((zUsername && *zUsername) && "Invalid user data.");
241241
return mprintf("%s/%z/%s", zHash, zCode, zUsername);
242242
}
@@ -252,20 +252,20 @@
252252
** If zDest is not NULL then the generated cookie is copied to
253253
** *zDdest and ownership is transfered to the caller (who should
254254
** eventually pass it to free()).
255255
*/
256256
void login_set_user_cookie(
257
- char const * zUsername, /* User's name */
257
+ const char *zUsername, /* User's name */
258258
int uid, /* User's ID */
259
- char ** zDest /* Optional: store generated cookie value. */
259
+ char **zDest /* Optional: store generated cookie value. */
260260
){
261261
const char *zCookieName = login_cookie_name();
262262
const char *zExpire = db_get("cookie-expire","8766");
263263
int expires = atoi(zExpire)*3600;
264264
char *zHash;
265265
char *zCookie;
266
- char const *zIpAddr = PD("REMOTE_ADDR","nil"); /* IP address of user */
266
+ const char *zIpAddr = PD("REMOTE_ADDR","nil"); /* IP address of user */
267267
char *zRemoteAddr = ipPrefix(zIpAddr); /* Abbreviated IP address */
268268
269269
assert((zUsername && *zUsername) && (uid > 0) && "Invalid user data.");
270270
zHash = db_text(0,
271271
"SELECT cookie FROM user"
@@ -303,16 +303,16 @@
303303
** is used.
304304
**
305305
** If zCookieDest is not NULL then the generated cookie is assigned to
306306
** *zCookieDest and the caller must eventually free() it.
307307
*/
308
-void login_set_anon_cookie(char const * zIpAddr, char ** zCookieDest ){
309
- char const *zNow; /* Current time (julian day number) */
308
+void login_set_anon_cookie(const char *zIpAddr, char **zCookieDest ){
309
+ const char *zNow; /* Current time (julian day number) */
310310
char *zCookie; /* The login cookie */
311
- char const *zCookieName; /* Name of the login cookie */
311
+ const char *zCookieName; /* Name of the login cookie */
312312
Blob b; /* Blob used during cookie construction */
313
- char * zRemoteAddr; /* Abbreviated IP address */
313
+ char *zRemoteAddr; /* Abbreviated IP address */
314314
if(!zIpAddr){
315315
zIpAddr = PD("REMOTE_ADDR","nil");
316316
}
317317
zRemoteAddr = ipPrefix(zIpAddr);
318318
zCookieName = login_cookie_name();
@@ -344,11 +344,11 @@
344344
*/
345345
void login_clear_login_data(){
346346
if(!g.userUid){
347347
return;
348348
}else{
349
- char const * cookie = login_cookie_name();
349
+ const char *cookie = login_cookie_name();
350350
/* To logout, change the cookie value to an empty string */
351351
cgi_set_cookie(cookie, "",
352352
login_cookie_path(), -86400);
353353
db_multi_exec("UPDATE user SET cookie=NULL, ipaddr=NULL, "
354354
" cexpire=0 WHERE uid=%d"
@@ -629,11 +629,11 @@
629629
@ <p>If you do not have an account, you can
630630
@ <a href="%s(g.zTop)/register?g=%T(P("G"))">create one</a>.
631631
}
632632
if( zAnonPw ){
633633
unsigned int uSeed = captcha_seed();
634
- char const *zDecoded = captcha_decode(uSeed);
634
+ const char *zDecoded = captcha_decode(uSeed);
635635
int bAutoCaptcha = db_get_boolean("auto-captcha", 0);
636636
char *zCaptcha = captcha_render(zDecoded);
637637
638638
@ <p><input type="hidden" name="cs" value="%u(uSeed)" />
639639
@ Visitors may enter <b>anonymous</b> as the user-ID with
@@ -1236,11 +1236,11 @@
12361236
**
12371237
*/
12381238
void register_page(void){
12391239
const char *zUsername, *zPasswd, *zConfirm, *zContact, *zCS, *zPw, *zCap;
12401240
unsigned int uSeed;
1241
- char const *zDecoded;
1241
+ const char *zDecoded;
12421242
char *zCaptcha;
12431243
if( !db_get_boolean("self-register", 0) ){
12441244
style_header("Registration not possible");
12451245
@ <p>This project does not allow user self-registration. Please contact the
12461246
@ project administrator to obtain an account.</p>
12471247
--- src/login.c
+++ src/login.c
@@ -208,12 +208,12 @@
208 ** On serious (DB-level) error it will probably exit.
209 **
210 ** zPassword may be either the plain-text form or the encrypted
211 ** form of the user's password.
212 */
213 int login_search_uid(char const *zUsername, char const *zPasswd){
214 char * zSha1Pw = sha1_shared_secret(zPasswd, zUsername, 0);
215 int const uid =
216 db_int(0,
217 "SELECT uid FROM user"
218 " WHERE login=%Q"
219 " AND length(cap)>0 AND length(pw)>0"
@@ -231,12 +231,12 @@
231 ** The zHash parameter must be a random value which must be
232 ** subsequently stored in user.cookie for later validation.
233 **
234 ** The returned memory should be free()d after use.
235 */
236 char * login_gen_user_cookie_value(char const *zUsername, char const * zHash){
237 char * zProjCode = db_get("project-code",NULL);
238 char *zCode = abbreviated_project_code(zProjCode);
239 free(zProjCode);
240 assert((zUsername && *zUsername) && "Invalid user data.");
241 return mprintf("%s/%z/%s", zHash, zCode, zUsername);
242 }
@@ -252,20 +252,20 @@
252 ** If zDest is not NULL then the generated cookie is copied to
253 ** *zDdest and ownership is transfered to the caller (who should
254 ** eventually pass it to free()).
255 */
256 void login_set_user_cookie(
257 char const * zUsername, /* User's name */
258 int uid, /* User's ID */
259 char ** zDest /* Optional: store generated cookie value. */
260 ){
261 const char *zCookieName = login_cookie_name();
262 const char *zExpire = db_get("cookie-expire","8766");
263 int expires = atoi(zExpire)*3600;
264 char *zHash;
265 char *zCookie;
266 char const *zIpAddr = PD("REMOTE_ADDR","nil"); /* IP address of user */
267 char *zRemoteAddr = ipPrefix(zIpAddr); /* Abbreviated IP address */
268
269 assert((zUsername && *zUsername) && (uid > 0) && "Invalid user data.");
270 zHash = db_text(0,
271 "SELECT cookie FROM user"
@@ -303,16 +303,16 @@
303 ** is used.
304 **
305 ** If zCookieDest is not NULL then the generated cookie is assigned to
306 ** *zCookieDest and the caller must eventually free() it.
307 */
308 void login_set_anon_cookie(char const * zIpAddr, char ** zCookieDest ){
309 char const *zNow; /* Current time (julian day number) */
310 char *zCookie; /* The login cookie */
311 char const *zCookieName; /* Name of the login cookie */
312 Blob b; /* Blob used during cookie construction */
313 char * zRemoteAddr; /* Abbreviated IP address */
314 if(!zIpAddr){
315 zIpAddr = PD("REMOTE_ADDR","nil");
316 }
317 zRemoteAddr = ipPrefix(zIpAddr);
318 zCookieName = login_cookie_name();
@@ -344,11 +344,11 @@
344 */
345 void login_clear_login_data(){
346 if(!g.userUid){
347 return;
348 }else{
349 char const * cookie = login_cookie_name();
350 /* To logout, change the cookie value to an empty string */
351 cgi_set_cookie(cookie, "",
352 login_cookie_path(), -86400);
353 db_multi_exec("UPDATE user SET cookie=NULL, ipaddr=NULL, "
354 " cexpire=0 WHERE uid=%d"
@@ -629,11 +629,11 @@
629 @ <p>If you do not have an account, you can
630 @ <a href="%s(g.zTop)/register?g=%T(P("G"))">create one</a>.
631 }
632 if( zAnonPw ){
633 unsigned int uSeed = captcha_seed();
634 char const *zDecoded = captcha_decode(uSeed);
635 int bAutoCaptcha = db_get_boolean("auto-captcha", 0);
636 char *zCaptcha = captcha_render(zDecoded);
637
638 @ <p><input type="hidden" name="cs" value="%u(uSeed)" />
639 @ Visitors may enter <b>anonymous</b> as the user-ID with
@@ -1236,11 +1236,11 @@
1236 **
1237 */
1238 void register_page(void){
1239 const char *zUsername, *zPasswd, *zConfirm, *zContact, *zCS, *zPw, *zCap;
1240 unsigned int uSeed;
1241 char const *zDecoded;
1242 char *zCaptcha;
1243 if( !db_get_boolean("self-register", 0) ){
1244 style_header("Registration not possible");
1245 @ <p>This project does not allow user self-registration. Please contact the
1246 @ project administrator to obtain an account.</p>
1247
--- src/login.c
+++ src/login.c
@@ -208,12 +208,12 @@
208 ** On serious (DB-level) error it will probably exit.
209 **
210 ** zPassword may be either the plain-text form or the encrypted
211 ** form of the user's password.
212 */
213 int login_search_uid(const char *zUsername, const char *zPasswd){
214 char *zSha1Pw = sha1_shared_secret(zPasswd, zUsername, 0);
215 int const uid =
216 db_int(0,
217 "SELECT uid FROM user"
218 " WHERE login=%Q"
219 " AND length(cap)>0 AND length(pw)>0"
@@ -231,12 +231,12 @@
231 ** The zHash parameter must be a random value which must be
232 ** subsequently stored in user.cookie for later validation.
233 **
234 ** The returned memory should be free()d after use.
235 */
236 char *login_gen_user_cookie_value(const char *zUsername, const char *zHash){
237 char *zProjCode = db_get("project-code",NULL);
238 char *zCode = abbreviated_project_code(zProjCode);
239 free(zProjCode);
240 assert((zUsername && *zUsername) && "Invalid user data.");
241 return mprintf("%s/%z/%s", zHash, zCode, zUsername);
242 }
@@ -252,20 +252,20 @@
252 ** If zDest is not NULL then the generated cookie is copied to
253 ** *zDdest and ownership is transfered to the caller (who should
254 ** eventually pass it to free()).
255 */
256 void login_set_user_cookie(
257 const char *zUsername, /* User's name */
258 int uid, /* User's ID */
259 char **zDest /* Optional: store generated cookie value. */
260 ){
261 const char *zCookieName = login_cookie_name();
262 const char *zExpire = db_get("cookie-expire","8766");
263 int expires = atoi(zExpire)*3600;
264 char *zHash;
265 char *zCookie;
266 const char *zIpAddr = PD("REMOTE_ADDR","nil"); /* IP address of user */
267 char *zRemoteAddr = ipPrefix(zIpAddr); /* Abbreviated IP address */
268
269 assert((zUsername && *zUsername) && (uid > 0) && "Invalid user data.");
270 zHash = db_text(0,
271 "SELECT cookie FROM user"
@@ -303,16 +303,16 @@
303 ** is used.
304 **
305 ** If zCookieDest is not NULL then the generated cookie is assigned to
306 ** *zCookieDest and the caller must eventually free() it.
307 */
308 void login_set_anon_cookie(const char *zIpAddr, char **zCookieDest ){
309 const char *zNow; /* Current time (julian day number) */
310 char *zCookie; /* The login cookie */
311 const char *zCookieName; /* Name of the login cookie */
312 Blob b; /* Blob used during cookie construction */
313 char *zRemoteAddr; /* Abbreviated IP address */
314 if(!zIpAddr){
315 zIpAddr = PD("REMOTE_ADDR","nil");
316 }
317 zRemoteAddr = ipPrefix(zIpAddr);
318 zCookieName = login_cookie_name();
@@ -344,11 +344,11 @@
344 */
345 void login_clear_login_data(){
346 if(!g.userUid){
347 return;
348 }else{
349 const char *cookie = login_cookie_name();
350 /* To logout, change the cookie value to an empty string */
351 cgi_set_cookie(cookie, "",
352 login_cookie_path(), -86400);
353 db_multi_exec("UPDATE user SET cookie=NULL, ipaddr=NULL, "
354 " cexpire=0 WHERE uid=%d"
@@ -629,11 +629,11 @@
629 @ <p>If you do not have an account, you can
630 @ <a href="%s(g.zTop)/register?g=%T(P("G"))">create one</a>.
631 }
632 if( zAnonPw ){
633 unsigned int uSeed = captcha_seed();
634 const char *zDecoded = captcha_decode(uSeed);
635 int bAutoCaptcha = db_get_boolean("auto-captcha", 0);
636 char *zCaptcha = captcha_render(zDecoded);
637
638 @ <p><input type="hidden" name="cs" value="%u(uSeed)" />
639 @ Visitors may enter <b>anonymous</b> as the user-ID with
@@ -1236,11 +1236,11 @@
1236 **
1237 */
1238 void register_page(void){
1239 const char *zUsername, *zPasswd, *zConfirm, *zContact, *zCS, *zPw, *zCap;
1240 unsigned int uSeed;
1241 const char *zDecoded;
1242 char *zCaptcha;
1243 if( !db_get_boolean("self-register", 0) ){
1244 style_header("Registration not possible");
1245 @ <p>This project does not allow user self-registration. Please contact the
1246 @ project administrator to obtain an account.</p>
1247
+45 -23
--- src/main.c
+++ src/main.c
@@ -229,45 +229,45 @@
229229
*/
230230
int resultCode; /* used for passing back specific codes
231231
** from /json callbacks. */
232232
int errorDetailParanoia; /* 0=full error codes, 1=%10, 2=%100, 3=%1000 */
233233
cson_output_opt outOpt; /* formatting options for JSON mode. */
234
- cson_value * authToken; /* authentication token */
235
- char const * jsonp; /* Name of JSONP function wrapper. */
234
+ cson_value *authToken; /* authentication token */
235
+ const char *jsonp; /* Name of JSONP function wrapper. */
236236
unsigned char dispatchDepth /* Tells JSON command dispatching
237237
which argument we are currently
238238
working on. For this purpose, arg#0
239239
is the "json" path/CLI arg.
240240
*/;
241241
struct { /* "garbage collector" */
242
- cson_value * v;
243
- cson_array * a;
242
+ cson_value *v;
243
+ cson_array *a;
244244
} gc;
245245
struct { /* JSON POST data. */
246
- cson_value * v;
247
- cson_array * a;
246
+ cson_value *v;
247
+ cson_array *a;
248248
int offset; /* Tells us which PATH_INFO/CLI args
249249
part holds the "json" command, so
250250
that we can account for sub-repos
251251
and path prefixes. This is handled
252252
differently for CLI and CGI modes.
253253
*/
254
- char const * commandStr /*"command" request param.*/;
254
+ const char *commandStr /*"command" request param.*/;
255255
} cmd;
256256
struct { /* JSON POST data. */
257
- cson_value * v;
258
- cson_object * o;
257
+ cson_value *v;
258
+ cson_object *o;
259259
} post;
260260
struct { /* GET/COOKIE params in JSON mode. */
261
- cson_value * v;
262
- cson_object * o;
261
+ cson_value *v;
262
+ cson_object *o;
263263
} param;
264264
struct {
265
- cson_value * v;
266
- cson_object * o;
265
+ cson_value *v;
266
+ cson_object *o;
267267
} reqPayload; /* request payload object (if any) */
268
- cson_array * warnings; /* response warnings */
268
+ cson_array *warnings; /* response warnings */
269269
int timerId; /* fetched from fossil_timer_start() */
270270
} json;
271271
#endif /* FOSSIL_ENABLE_JSON */
272272
};
273273
@@ -391,11 +391,11 @@
391391
unsigned int nLine; /* Number of lines in the file*/
392392
unsigned int i, j, k; /* Loop counters */
393393
int n; /* Number of bytes in one line */
394394
char *z; /* General use string pointer */
395395
char **newArgv; /* New expanded g.argv under construction */
396
- char const * zFileName; /* input file name */
396
+ const char *zFileName; /* input file name */
397397
FILE *inFile; /* input FILE */
398398
#if defined(_WIN32)
399399
wchar_t buf[MAX_PATH];
400400
#endif
401401
@@ -936,12 +936,19 @@
936936
** If the verbose option is specified, additional details will
937937
** be output about what optional features this binary was compiled
938938
** with
939939
*/
940940
void version_cmd(void){
941
+ int verboseFlag = 0;
942
+
941943
fossil_print("This is fossil version %s\n", get_version());
942
- if(!find_option("verbose","v",0)){
944
+ verboseFlag = find_option("verbose","v",0)!=0;
945
+
946
+ /* We should be done with options.. */
947
+ verify_all_options();
948
+
949
+ if(!verboseFlag){
943950
return;
944951
}else{
945952
#if defined(FOSSIL_ENABLE_TCL)
946953
int rc;
947954
const char *zRc;
@@ -997,12 +1004,12 @@
9971004
** %fossil help --w|-www Show list of WWW pages
9981005
*/
9991006
void help_cmd(void){
10001007
int rc, idx, isPage = 0;
10011008
const char *z;
1002
- char const * zCmdOrPage;
1003
- char const * zCmdOrPagePlural;
1009
+ const char *zCmdOrPage;
1010
+ const char *zCmdOrPagePlural;
10041011
if( g.argc<3 ){
10051012
z = g.argv[0];
10061013
fossil_print(
10071014
"Usage: %s help COMMAND\n"
10081015
"Common COMMANDs: (use \"%s help -a|--all\" for a complete list)\n",
@@ -1067,18 +1074,18 @@
10671074
/*
10681075
** WEBPAGE: help
10691076
** URL: /help/CMD
10701077
*/
10711078
void help_page(void){
1072
- const char * zCmd = P("cmd");
1079
+ const char *zCmd = P("cmd");
10731080
10741081
if( zCmd==0 ) zCmd = P("name");
10751082
style_header("Command-line Help");
10761083
if( zCmd ){
10771084
int rc, idx;
10781085
char *z, *s, *d;
1079
- char const * zCmdOrPage = ('/'==*zCmd) ? "page" : "command";
1086
+ const char *zCmdOrPage = ('/'==*zCmd) ? "page" : "command";
10801087
style_submenu_element("Command-List", "Command-List", "%s/help", g.zTop);
10811088
@ <h1>The "%s(zCmd)" %s(zCmdOrPage):</h1>
10821089
rc = name_search(zCmd, aCommand, count(aCommand), 0, &idx);
10831090
if( rc==1 ){
10841091
@ unknown command: %s(zCmd)
@@ -1410,11 +1417,11 @@
14101417
}
14111418
if( szFile==0 ){
14121419
if( zRepo[0]=='/' && zRepo[1]=='/' ){ zRepo++; j--; }
14131420
szFile = file_size(zRepo);
14141421
}
1415
- if( szFile<0 ){
1422
+ if( szFile<0 && i>0 ){
14161423
const char *zMimetype;
14171424
assert( fossil_strcmp(&zRepo[j], ".fossil")==0 );
14181425
zRepo[j] = 0;
14191426
if( zPathInfo[i]=='/' && file_isdir(zRepo)==1 ){
14201427
fossil_free(zToFree);
@@ -1928,10 +1935,14 @@
19281935
if( zAltBase ) set_base_url(zAltBase);
19291936
if( find_option("https",0,0)!=0 ) cgi_replace_parameter("HTTPS","on");
19301937
zHost = find_option("host", 0, 1);
19311938
if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);
19321939
g.cgiOutput = 1;
1940
+
1941
+ /* We should be done with options.. */
1942
+ verify_all_options();
1943
+
19331944
if( g.argc!=2 && g.argc!=3 && g.argc!=6 ){
19341945
fossil_fatal("no repository specified");
19351946
}
19361947
g.fullHttpReply = 1;
19371948
if( g.argc==6 ){
@@ -2094,23 +2105,34 @@
20942105
#if defined(_WIN32)
20952106
const char *zStopperFile; /* Name of file used to terminate server */
20962107
zStopperFile = find_option("stopper", 0, 1);
20972108
#endif
20982109
2099
- zFileGlob = find_option("files", 0, 1);
2110
+ zFileGlob = find_option("files-urlenc",0,1);
2111
+ if( zFileGlob ){
2112
+ char *z = mprintf("%s", zFileGlob);
2113
+ dehttpize(z);
2114
+ zFileGlob = z;
2115
+ }else{
2116
+ zFileGlob = find_option("files",0,1);
2117
+ }
21002118
g.useLocalauth = find_option("localauth", 0, 0)!=0;
21012119
Th_InitTraceLog();
21022120
zPort = find_option("port", "P", 1);
21032121
zNotFound = find_option("notfound", 0, 1);
21042122
zAltBase = find_option("baseurl", 0, 1);
21052123
if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
21062124
if( zAltBase ){
21072125
set_base_url(zAltBase);
21082126
}
2109
- if ( find_option("localhost", 0, 0)!=0 ){
2127
+ if( find_option("localhost", 0, 0)!=0 ){
21102128
flags |= HTTP_SERVER_LOCALHOST;
21112129
}
2130
+
2131
+ /* We should be done with options.. */
2132
+ verify_all_options();
2133
+
21122134
if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
21132135
isUiCmd = g.argv[1][0]=='u';
21142136
if( isUiCmd ){
21152137
flags |= HTTP_SERVER_LOCALHOST;
21162138
g.useLocalauth = 1;
21172139
--- src/main.c
+++ src/main.c
@@ -229,45 +229,45 @@
229 */
230 int resultCode; /* used for passing back specific codes
231 ** from /json callbacks. */
232 int errorDetailParanoia; /* 0=full error codes, 1=%10, 2=%100, 3=%1000 */
233 cson_output_opt outOpt; /* formatting options for JSON mode. */
234 cson_value * authToken; /* authentication token */
235 char const * jsonp; /* Name of JSONP function wrapper. */
236 unsigned char dispatchDepth /* Tells JSON command dispatching
237 which argument we are currently
238 working on. For this purpose, arg#0
239 is the "json" path/CLI arg.
240 */;
241 struct { /* "garbage collector" */
242 cson_value * v;
243 cson_array * a;
244 } gc;
245 struct { /* JSON POST data. */
246 cson_value * v;
247 cson_array * a;
248 int offset; /* Tells us which PATH_INFO/CLI args
249 part holds the "json" command, so
250 that we can account for sub-repos
251 and path prefixes. This is handled
252 differently for CLI and CGI modes.
253 */
254 char const * commandStr /*"command" request param.*/;
255 } cmd;
256 struct { /* JSON POST data. */
257 cson_value * v;
258 cson_object * o;
259 } post;
260 struct { /* GET/COOKIE params in JSON mode. */
261 cson_value * v;
262 cson_object * o;
263 } param;
264 struct {
265 cson_value * v;
266 cson_object * o;
267 } reqPayload; /* request payload object (if any) */
268 cson_array * warnings; /* response warnings */
269 int timerId; /* fetched from fossil_timer_start() */
270 } json;
271 #endif /* FOSSIL_ENABLE_JSON */
272 };
273
@@ -391,11 +391,11 @@
391 unsigned int nLine; /* Number of lines in the file*/
392 unsigned int i, j, k; /* Loop counters */
393 int n; /* Number of bytes in one line */
394 char *z; /* General use string pointer */
395 char **newArgv; /* New expanded g.argv under construction */
396 char const * zFileName; /* input file name */
397 FILE *inFile; /* input FILE */
398 #if defined(_WIN32)
399 wchar_t buf[MAX_PATH];
400 #endif
401
@@ -936,12 +936,19 @@
936 ** If the verbose option is specified, additional details will
937 ** be output about what optional features this binary was compiled
938 ** with
939 */
940 void version_cmd(void){
 
 
941 fossil_print("This is fossil version %s\n", get_version());
942 if(!find_option("verbose","v",0)){
 
 
 
 
 
943 return;
944 }else{
945 #if defined(FOSSIL_ENABLE_TCL)
946 int rc;
947 const char *zRc;
@@ -997,12 +1004,12 @@
997 ** %fossil help --w|-www Show list of WWW pages
998 */
999 void help_cmd(void){
1000 int rc, idx, isPage = 0;
1001 const char *z;
1002 char const * zCmdOrPage;
1003 char const * zCmdOrPagePlural;
1004 if( g.argc<3 ){
1005 z = g.argv[0];
1006 fossil_print(
1007 "Usage: %s help COMMAND\n"
1008 "Common COMMANDs: (use \"%s help -a|--all\" for a complete list)\n",
@@ -1067,18 +1074,18 @@
1067 /*
1068 ** WEBPAGE: help
1069 ** URL: /help/CMD
1070 */
1071 void help_page(void){
1072 const char * zCmd = P("cmd");
1073
1074 if( zCmd==0 ) zCmd = P("name");
1075 style_header("Command-line Help");
1076 if( zCmd ){
1077 int rc, idx;
1078 char *z, *s, *d;
1079 char const * zCmdOrPage = ('/'==*zCmd) ? "page" : "command";
1080 style_submenu_element("Command-List", "Command-List", "%s/help", g.zTop);
1081 @ <h1>The "%s(zCmd)" %s(zCmdOrPage):</h1>
1082 rc = name_search(zCmd, aCommand, count(aCommand), 0, &idx);
1083 if( rc==1 ){
1084 @ unknown command: %s(zCmd)
@@ -1410,11 +1417,11 @@
1410 }
1411 if( szFile==0 ){
1412 if( zRepo[0]=='/' && zRepo[1]=='/' ){ zRepo++; j--; }
1413 szFile = file_size(zRepo);
1414 }
1415 if( szFile<0 ){
1416 const char *zMimetype;
1417 assert( fossil_strcmp(&zRepo[j], ".fossil")==0 );
1418 zRepo[j] = 0;
1419 if( zPathInfo[i]=='/' && file_isdir(zRepo)==1 ){
1420 fossil_free(zToFree);
@@ -1928,10 +1935,14 @@
1928 if( zAltBase ) set_base_url(zAltBase);
1929 if( find_option("https",0,0)!=0 ) cgi_replace_parameter("HTTPS","on");
1930 zHost = find_option("host", 0, 1);
1931 if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);
1932 g.cgiOutput = 1;
 
 
 
 
1933 if( g.argc!=2 && g.argc!=3 && g.argc!=6 ){
1934 fossil_fatal("no repository specified");
1935 }
1936 g.fullHttpReply = 1;
1937 if( g.argc==6 ){
@@ -2094,23 +2105,34 @@
2094 #if defined(_WIN32)
2095 const char *zStopperFile; /* Name of file used to terminate server */
2096 zStopperFile = find_option("stopper", 0, 1);
2097 #endif
2098
2099 zFileGlob = find_option("files", 0, 1);
 
 
 
 
 
 
 
2100 g.useLocalauth = find_option("localauth", 0, 0)!=0;
2101 Th_InitTraceLog();
2102 zPort = find_option("port", "P", 1);
2103 zNotFound = find_option("notfound", 0, 1);
2104 zAltBase = find_option("baseurl", 0, 1);
2105 if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
2106 if( zAltBase ){
2107 set_base_url(zAltBase);
2108 }
2109 if ( find_option("localhost", 0, 0)!=0 ){
2110 flags |= HTTP_SERVER_LOCALHOST;
2111 }
 
 
 
 
2112 if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
2113 isUiCmd = g.argv[1][0]=='u';
2114 if( isUiCmd ){
2115 flags |= HTTP_SERVER_LOCALHOST;
2116 g.useLocalauth = 1;
2117
--- src/main.c
+++ src/main.c
@@ -229,45 +229,45 @@
229 */
230 int resultCode; /* used for passing back specific codes
231 ** from /json callbacks. */
232 int errorDetailParanoia; /* 0=full error codes, 1=%10, 2=%100, 3=%1000 */
233 cson_output_opt outOpt; /* formatting options for JSON mode. */
234 cson_value *authToken; /* authentication token */
235 const char *jsonp; /* Name of JSONP function wrapper. */
236 unsigned char dispatchDepth /* Tells JSON command dispatching
237 which argument we are currently
238 working on. For this purpose, arg#0
239 is the "json" path/CLI arg.
240 */;
241 struct { /* "garbage collector" */
242 cson_value *v;
243 cson_array *a;
244 } gc;
245 struct { /* JSON POST data. */
246 cson_value *v;
247 cson_array *a;
248 int offset; /* Tells us which PATH_INFO/CLI args
249 part holds the "json" command, so
250 that we can account for sub-repos
251 and path prefixes. This is handled
252 differently for CLI and CGI modes.
253 */
254 const char *commandStr /*"command" request param.*/;
255 } cmd;
256 struct { /* JSON POST data. */
257 cson_value *v;
258 cson_object *o;
259 } post;
260 struct { /* GET/COOKIE params in JSON mode. */
261 cson_value *v;
262 cson_object *o;
263 } param;
264 struct {
265 cson_value *v;
266 cson_object *o;
267 } reqPayload; /* request payload object (if any) */
268 cson_array *warnings; /* response warnings */
269 int timerId; /* fetched from fossil_timer_start() */
270 } json;
271 #endif /* FOSSIL_ENABLE_JSON */
272 };
273
@@ -391,11 +391,11 @@
391 unsigned int nLine; /* Number of lines in the file*/
392 unsigned int i, j, k; /* Loop counters */
393 int n; /* Number of bytes in one line */
394 char *z; /* General use string pointer */
395 char **newArgv; /* New expanded g.argv under construction */
396 const char *zFileName; /* input file name */
397 FILE *inFile; /* input FILE */
398 #if defined(_WIN32)
399 wchar_t buf[MAX_PATH];
400 #endif
401
@@ -936,12 +936,19 @@
936 ** If the verbose option is specified, additional details will
937 ** be output about what optional features this binary was compiled
938 ** with
939 */
940 void version_cmd(void){
941 int verboseFlag = 0;
942
943 fossil_print("This is fossil version %s\n", get_version());
944 verboseFlag = find_option("verbose","v",0)!=0;
945
946 /* We should be done with options.. */
947 verify_all_options();
948
949 if(!verboseFlag){
950 return;
951 }else{
952 #if defined(FOSSIL_ENABLE_TCL)
953 int rc;
954 const char *zRc;
@@ -997,12 +1004,12 @@
1004 ** %fossil help --w|-www Show list of WWW pages
1005 */
1006 void help_cmd(void){
1007 int rc, idx, isPage = 0;
1008 const char *z;
1009 const char *zCmdOrPage;
1010 const char *zCmdOrPagePlural;
1011 if( g.argc<3 ){
1012 z = g.argv[0];
1013 fossil_print(
1014 "Usage: %s help COMMAND\n"
1015 "Common COMMANDs: (use \"%s help -a|--all\" for a complete list)\n",
@@ -1067,18 +1074,18 @@
1074 /*
1075 ** WEBPAGE: help
1076 ** URL: /help/CMD
1077 */
1078 void help_page(void){
1079 const char *zCmd = P("cmd");
1080
1081 if( zCmd==0 ) zCmd = P("name");
1082 style_header("Command-line Help");
1083 if( zCmd ){
1084 int rc, idx;
1085 char *z, *s, *d;
1086 const char *zCmdOrPage = ('/'==*zCmd) ? "page" : "command";
1087 style_submenu_element("Command-List", "Command-List", "%s/help", g.zTop);
1088 @ <h1>The "%s(zCmd)" %s(zCmdOrPage):</h1>
1089 rc = name_search(zCmd, aCommand, count(aCommand), 0, &idx);
1090 if( rc==1 ){
1091 @ unknown command: %s(zCmd)
@@ -1410,11 +1417,11 @@
1417 }
1418 if( szFile==0 ){
1419 if( zRepo[0]=='/' && zRepo[1]=='/' ){ zRepo++; j--; }
1420 szFile = file_size(zRepo);
1421 }
1422 if( szFile<0 && i>0 ){
1423 const char *zMimetype;
1424 assert( fossil_strcmp(&zRepo[j], ".fossil")==0 );
1425 zRepo[j] = 0;
1426 if( zPathInfo[i]=='/' && file_isdir(zRepo)==1 ){
1427 fossil_free(zToFree);
@@ -1928,10 +1935,14 @@
1935 if( zAltBase ) set_base_url(zAltBase);
1936 if( find_option("https",0,0)!=0 ) cgi_replace_parameter("HTTPS","on");
1937 zHost = find_option("host", 0, 1);
1938 if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);
1939 g.cgiOutput = 1;
1940
1941 /* We should be done with options.. */
1942 verify_all_options();
1943
1944 if( g.argc!=2 && g.argc!=3 && g.argc!=6 ){
1945 fossil_fatal("no repository specified");
1946 }
1947 g.fullHttpReply = 1;
1948 if( g.argc==6 ){
@@ -2094,23 +2105,34 @@
2105 #if defined(_WIN32)
2106 const char *zStopperFile; /* Name of file used to terminate server */
2107 zStopperFile = find_option("stopper", 0, 1);
2108 #endif
2109
2110 zFileGlob = find_option("files-urlenc",0,1);
2111 if( zFileGlob ){
2112 char *z = mprintf("%s", zFileGlob);
2113 dehttpize(z);
2114 zFileGlob = z;
2115 }else{
2116 zFileGlob = find_option("files",0,1);
2117 }
2118 g.useLocalauth = find_option("localauth", 0, 0)!=0;
2119 Th_InitTraceLog();
2120 zPort = find_option("port", "P", 1);
2121 zNotFound = find_option("notfound", 0, 1);
2122 zAltBase = find_option("baseurl", 0, 1);
2123 if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
2124 if( zAltBase ){
2125 set_base_url(zAltBase);
2126 }
2127 if( find_option("localhost", 0, 0)!=0 ){
2128 flags |= HTTP_SERVER_LOCALHOST;
2129 }
2130
2131 /* We should be done with options.. */
2132 verify_all_options();
2133
2134 if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
2135 isUiCmd = g.argv[1][0]=='u';
2136 if( isUiCmd ){
2137 flags |= HTTP_SERVER_LOCALHOST;
2138 g.useLocalauth = 1;
2139
+2 -1
--- src/main.mk
+++ src/main.mk
@@ -385,11 +385,12 @@
385385
386386
$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
387387
$(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
388388
389389
# Setup the options used to compile the included SQLite library.
390
-SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 \
390
+SQLITE_OPTIONS = -DNDEBUG=1 \
391
+ -DSQLITE_OMIT_LOAD_EXTENSION=1 \
391392
-DSQLITE_ENABLE_LOCKING_STYLE=0 \
392393
-DSQLITE_THREADSAFE=0 \
393394
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
394395
-DSQLITE_OMIT_DEPRECATED \
395396
-DSQLITE_ENABLE_EXPLAIN_COMMENTS
396397
--- src/main.mk
+++ src/main.mk
@@ -385,11 +385,12 @@
385
386 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
387 $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
388
389 # Setup the options used to compile the included SQLite library.
390 SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 \
 
391 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
392 -DSQLITE_THREADSAFE=0 \
393 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
394 -DSQLITE_OMIT_DEPRECATED \
395 -DSQLITE_ENABLE_EXPLAIN_COMMENTS
396
--- src/main.mk
+++ src/main.mk
@@ -385,11 +385,12 @@
385
386 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
387 $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
388
389 # Setup the options used to compile the included SQLite library.
390 SQLITE_OPTIONS = -DNDEBUG=1 \
391 -DSQLITE_OMIT_LOAD_EXTENSION=1 \
392 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
393 -DSQLITE_THREADSAFE=0 \
394 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
395 -DSQLITE_OMIT_DEPRECATED \
396 -DSQLITE_ENABLE_EXPLAIN_COMMENTS
397
+11 -7
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -132,10 +132,11 @@
132132
}
133133
134134
# Options used to compile the included SQLite library.
135135
#
136136
set SQLITE_OPTIONS {
137
+ -DNDEBUG=1
137138
-DSQLITE_OMIT_LOAD_EXTENSION=1
138139
-DSQLITE_ENABLE_LOCKING_STYLE=0
139140
-DSQLITE_THREADSAFE=0
140141
-DSQLITE_DEFAULT_FILE_FORMAT=4
141142
-DSQLITE_OMIT_DEPRECATED
@@ -455,12 +456,12 @@
455456
#### The directories where the OpenSSL include and library files are located.
456457
# The recommended usage here is to use the Sysinternals junction tool
457458
# to create a hard link between an "openssl-1.x" sub-directory of the
458459
# Fossil source code directory and the target OpenSSL source directory.
459460
#
460
-OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1h/include
461
-OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1h
461
+OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1i/include
462
+OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1i
462463
463464
#### Either the directory where the Tcl library is installed or the Tcl
464465
# source code directory resides (depending on the value of the macro
465466
# FOSSIL_TCL_SOURCE). If this points to the Tcl install directory,
466467
# this directory must have "include" and "lib" sub-directories. If
@@ -826,11 +827,14 @@
826827
writeln "\$(OBJDIR)/$s.o:\t\$(OBJDIR)/${s}_.c \$(OBJDIR)/$s.h $extra_h($s) \$(SRCDIR)/config.h"
827828
writeln "\t\$(XTCC) -o \$(OBJDIR)/$s.o -c \$(OBJDIR)/${s}_.c\n"
828829
writeln "\$(OBJDIR)/${s}.h:\t\$(OBJDIR)/headers\n"
829830
}
830831
831
-set MINGW_SQLITE_OPTIONS $SQLITE_OPTIONS
832
+set SQLITE_WIN32_OPTIONS $SQLITE_OPTIONS
833
+lappend SQLITE_WIN32_OPTIONS -DSQLITE_WIN32_NO_ANSI
834
+
835
+set MINGW_SQLITE_OPTIONS $SQLITE_WIN32_OPTIONS
832836
lappend MINGW_SQLITE_OPTIONS -D_HAVE__MINGW_H
833837
lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MALLOC_H
834838
lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MSIZE
835839
836840
set j " \\\n "
@@ -1053,12 +1057,12 @@
10531057
10541058
# Uncomment to enable Tcl support
10551059
# FOSSIL_ENABLE_TCL = 1
10561060
10571061
!ifdef FOSSIL_ENABLE_SSL
1058
-SSLINCDIR = $(B)\compat\openssl-1.0.1h\include
1059
-SSLLIBDIR = $(B)\compat\openssl-1.0.1h\out32
1062
+SSLINCDIR = $(B)\compat\openssl-1.0.1i\include
1063
+SSLLIBDIR = $(B)\compat\openssl-1.0.1i\out32
10601064
SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
10611065
!endif
10621066
10631067
!ifdef FOSSIL_ENABLE_TCL
10641068
TCLDIR = $(B)\compat\tcl-8.6
@@ -1123,11 +1127,11 @@
11231127
RCC = $(RCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
11241128
TCC = $(TCC) /DUSE_TCL_STUBS=1
11251129
RCC = $(RCC) /DUSE_TCL_STUBS=1
11261130
!endif
11271131
}
1128
-regsub -all {[-]D} [join $SQLITE_OPTIONS { }] {/D} MSC_SQLITE_OPTIONS
1132
+regsub -all {[-]D} [join $SQLITE_WIN32_OPTIONS { }] {/D} MSC_SQLITE_OPTIONS
11291133
set j " \\\n "
11301134
writeln "SQLITE_OPTIONS = [join $MSC_SQLITE_OPTIONS $j]\n"
11311135
11321136
regsub -all {[-]D} [join $SHELL_WIN32_OPTIONS { }] {/D} MSC_SHELL_OPTIONS
11331137
set j " \\\n "
@@ -1294,11 +1298,11 @@
12941298
puts "building ../win/Makefile.PellesCGMake"
12951299
set output_file [open ../win/Makefile.PellesCGMake w]
12961300
fconfigure $output_file -translation binary
12971301
12981302
writeln [string map [list \
1299
- <<<SQLITE_OPTIONS>>> [join $SQLITE_OPTIONS { }] \
1303
+ <<<SQLITE_OPTIONS>>> [join $SQLITE_WIN32_OPTIONS { }] \
13001304
<<<SHELL_OPTIONS>>> [join $SHELL_WIN32_OPTIONS { }]] {#
13011305
##############################################################################
13021306
# WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "src/makemake.tcl")
13031307
##############################################################################
13041308
#
13051309
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -132,10 +132,11 @@
132 }
133
134 # Options used to compile the included SQLite library.
135 #
136 set SQLITE_OPTIONS {
 
137 -DSQLITE_OMIT_LOAD_EXTENSION=1
138 -DSQLITE_ENABLE_LOCKING_STYLE=0
139 -DSQLITE_THREADSAFE=0
140 -DSQLITE_DEFAULT_FILE_FORMAT=4
141 -DSQLITE_OMIT_DEPRECATED
@@ -455,12 +456,12 @@
455 #### The directories where the OpenSSL include and library files are located.
456 # The recommended usage here is to use the Sysinternals junction tool
457 # to create a hard link between an "openssl-1.x" sub-directory of the
458 # Fossil source code directory and the target OpenSSL source directory.
459 #
460 OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1h/include
461 OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1h
462
463 #### Either the directory where the Tcl library is installed or the Tcl
464 # source code directory resides (depending on the value of the macro
465 # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory,
466 # this directory must have "include" and "lib" sub-directories. If
@@ -826,11 +827,14 @@
826 writeln "\$(OBJDIR)/$s.o:\t\$(OBJDIR)/${s}_.c \$(OBJDIR)/$s.h $extra_h($s) \$(SRCDIR)/config.h"
827 writeln "\t\$(XTCC) -o \$(OBJDIR)/$s.o -c \$(OBJDIR)/${s}_.c\n"
828 writeln "\$(OBJDIR)/${s}.h:\t\$(OBJDIR)/headers\n"
829 }
830
831 set MINGW_SQLITE_OPTIONS $SQLITE_OPTIONS
 
 
 
832 lappend MINGW_SQLITE_OPTIONS -D_HAVE__MINGW_H
833 lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MALLOC_H
834 lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MSIZE
835
836 set j " \\\n "
@@ -1053,12 +1057,12 @@
1053
1054 # Uncomment to enable Tcl support
1055 # FOSSIL_ENABLE_TCL = 1
1056
1057 !ifdef FOSSIL_ENABLE_SSL
1058 SSLINCDIR = $(B)\compat\openssl-1.0.1h\include
1059 SSLLIBDIR = $(B)\compat\openssl-1.0.1h\out32
1060 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
1061 !endif
1062
1063 !ifdef FOSSIL_ENABLE_TCL
1064 TCLDIR = $(B)\compat\tcl-8.6
@@ -1123,11 +1127,11 @@
1123 RCC = $(RCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
1124 TCC = $(TCC) /DUSE_TCL_STUBS=1
1125 RCC = $(RCC) /DUSE_TCL_STUBS=1
1126 !endif
1127 }
1128 regsub -all {[-]D} [join $SQLITE_OPTIONS { }] {/D} MSC_SQLITE_OPTIONS
1129 set j " \\\n "
1130 writeln "SQLITE_OPTIONS = [join $MSC_SQLITE_OPTIONS $j]\n"
1131
1132 regsub -all {[-]D} [join $SHELL_WIN32_OPTIONS { }] {/D} MSC_SHELL_OPTIONS
1133 set j " \\\n "
@@ -1294,11 +1298,11 @@
1294 puts "building ../win/Makefile.PellesCGMake"
1295 set output_file [open ../win/Makefile.PellesCGMake w]
1296 fconfigure $output_file -translation binary
1297
1298 writeln [string map [list \
1299 <<<SQLITE_OPTIONS>>> [join $SQLITE_OPTIONS { }] \
1300 <<<SHELL_OPTIONS>>> [join $SHELL_WIN32_OPTIONS { }]] {#
1301 ##############################################################################
1302 # WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "src/makemake.tcl")
1303 ##############################################################################
1304 #
1305
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -132,10 +132,11 @@
132 }
133
134 # Options used to compile the included SQLite library.
135 #
136 set SQLITE_OPTIONS {
137 -DNDEBUG=1
138 -DSQLITE_OMIT_LOAD_EXTENSION=1
139 -DSQLITE_ENABLE_LOCKING_STYLE=0
140 -DSQLITE_THREADSAFE=0
141 -DSQLITE_DEFAULT_FILE_FORMAT=4
142 -DSQLITE_OMIT_DEPRECATED
@@ -455,12 +456,12 @@
456 #### The directories where the OpenSSL include and library files are located.
457 # The recommended usage here is to use the Sysinternals junction tool
458 # to create a hard link between an "openssl-1.x" sub-directory of the
459 # Fossil source code directory and the target OpenSSL source directory.
460 #
461 OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1i/include
462 OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1i
463
464 #### Either the directory where the Tcl library is installed or the Tcl
465 # source code directory resides (depending on the value of the macro
466 # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory,
467 # this directory must have "include" and "lib" sub-directories. If
@@ -826,11 +827,14 @@
827 writeln "\$(OBJDIR)/$s.o:\t\$(OBJDIR)/${s}_.c \$(OBJDIR)/$s.h $extra_h($s) \$(SRCDIR)/config.h"
828 writeln "\t\$(XTCC) -o \$(OBJDIR)/$s.o -c \$(OBJDIR)/${s}_.c\n"
829 writeln "\$(OBJDIR)/${s}.h:\t\$(OBJDIR)/headers\n"
830 }
831
832 set SQLITE_WIN32_OPTIONS $SQLITE_OPTIONS
833 lappend SQLITE_WIN32_OPTIONS -DSQLITE_WIN32_NO_ANSI
834
835 set MINGW_SQLITE_OPTIONS $SQLITE_WIN32_OPTIONS
836 lappend MINGW_SQLITE_OPTIONS -D_HAVE__MINGW_H
837 lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MALLOC_H
838 lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MSIZE
839
840 set j " \\\n "
@@ -1053,12 +1057,12 @@
1057
1058 # Uncomment to enable Tcl support
1059 # FOSSIL_ENABLE_TCL = 1
1060
1061 !ifdef FOSSIL_ENABLE_SSL
1062 SSLINCDIR = $(B)\compat\openssl-1.0.1i\include
1063 SSLLIBDIR = $(B)\compat\openssl-1.0.1i\out32
1064 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
1065 !endif
1066
1067 !ifdef FOSSIL_ENABLE_TCL
1068 TCLDIR = $(B)\compat\tcl-8.6
@@ -1123,11 +1127,11 @@
1127 RCC = $(RCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
1128 TCC = $(TCC) /DUSE_TCL_STUBS=1
1129 RCC = $(RCC) /DUSE_TCL_STUBS=1
1130 !endif
1131 }
1132 regsub -all {[-]D} [join $SQLITE_WIN32_OPTIONS { }] {/D} MSC_SQLITE_OPTIONS
1133 set j " \\\n "
1134 writeln "SQLITE_OPTIONS = [join $MSC_SQLITE_OPTIONS $j]\n"
1135
1136 regsub -all {[-]D} [join $SHELL_WIN32_OPTIONS { }] {/D} MSC_SHELL_OPTIONS
1137 set j " \\\n "
@@ -1294,11 +1298,11 @@
1298 puts "building ../win/Makefile.PellesCGMake"
1299 set output_file [open ../win/Makefile.PellesCGMake w]
1300 fconfigure $output_file -translation binary
1301
1302 writeln [string map [list \
1303 <<<SQLITE_OPTIONS>>> [join $SQLITE_WIN32_OPTIONS { }] \
1304 <<<SHELL_OPTIONS>>> [join $SHELL_WIN32_OPTIONS { }]] {#
1305 ##############################################################################
1306 # WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "src/makemake.tcl")
1307 ##############################################################################
1308 #
1309
+1 -1
--- src/merge.c
+++ src/merge.c
@@ -644,11 +644,11 @@
644644
fossil_warning("WARNING: %d unmanaged files were overwritten",
645645
nOverwrite);
646646
}
647647
if( dryRunFlag ){
648648
fossil_warning("REMINDER: this was a dry run -"
649
- " no file were actually changed.");
649
+ " no files were actually changed.");
650650
}
651651
652652
/*
653653
** Clean up the mid and pid VFILE entries. Then commit the changes.
654654
*/
655655
--- src/merge.c
+++ src/merge.c
@@ -644,11 +644,11 @@
644 fossil_warning("WARNING: %d unmanaged files were overwritten",
645 nOverwrite);
646 }
647 if( dryRunFlag ){
648 fossil_warning("REMINDER: this was a dry run -"
649 " no file were actually changed.");
650 }
651
652 /*
653 ** Clean up the mid and pid VFILE entries. Then commit the changes.
654 */
655
--- src/merge.c
+++ src/merge.c
@@ -644,11 +644,11 @@
644 fossil_warning("WARNING: %d unmanaged files were overwritten",
645 nOverwrite);
646 }
647 if( dryRunFlag ){
648 fossil_warning("REMINDER: this was a dry run -"
649 " no files were actually changed.");
650 }
651
652 /*
653 ** Clean up the mid and pid VFILE entries. Then commit the changes.
654 */
655
+5 -1
--- src/merge3.c
+++ src/merge3.c
@@ -136,11 +136,11 @@
136136
}
137137
138138
/*
139139
** Text of boundary markers for merge conflicts.
140140
*/
141
-static char const * const mergeMarker[] = {
141
+static const char *const mergeMarker[] = {
142142
/*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
143143
"<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n",
144144
"======= COMMON ANCESTOR content follows ============================\n",
145145
"======= MERGED IN content follows ==================================\n",
146146
">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
@@ -368,10 +368,14 @@
368368
** fossil commit
369369
**
370370
*/
371371
void delta_3waymerge_cmd(void){
372372
Blob pivot, v1, v2, merged;
373
+
374
+ /* We should be done with options.. */
375
+ verify_all_options();
376
+
373377
if( g.argc!=6 ){
374378
usage("PIVOT V1 V2 MERGED");
375379
}
376380
if( blob_read_from_file(&pivot, g.argv[2])<0 ){
377381
fossil_fatal("cannot read %s\n", g.argv[2]);
378382
--- src/merge3.c
+++ src/merge3.c
@@ -136,11 +136,11 @@
136 }
137
138 /*
139 ** Text of boundary markers for merge conflicts.
140 */
141 static char const * const mergeMarker[] = {
142 /*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
143 "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n",
144 "======= COMMON ANCESTOR content follows ============================\n",
145 "======= MERGED IN content follows ==================================\n",
146 ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
@@ -368,10 +368,14 @@
368 ** fossil commit
369 **
370 */
371 void delta_3waymerge_cmd(void){
372 Blob pivot, v1, v2, merged;
 
 
 
 
373 if( g.argc!=6 ){
374 usage("PIVOT V1 V2 MERGED");
375 }
376 if( blob_read_from_file(&pivot, g.argv[2])<0 ){
377 fossil_fatal("cannot read %s\n", g.argv[2]);
378
--- src/merge3.c
+++ src/merge3.c
@@ -136,11 +136,11 @@
136 }
137
138 /*
139 ** Text of boundary markers for merge conflicts.
140 */
141 static const char *const mergeMarker[] = {
142 /*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
143 "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n",
144 "======= COMMON ANCESTOR content follows ============================\n",
145 "======= MERGED IN content follows ==================================\n",
146 ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
@@ -368,10 +368,14 @@
368 ** fossil commit
369 **
370 */
371 void delta_3waymerge_cmd(void){
372 Blob pivot, v1, v2, merged;
373
374 /* We should be done with options.. */
375 verify_all_options();
376
377 if( g.argc!=6 ){
378 usage("PIVOT V1 V2 MERGED");
379 }
380 if( blob_read_from_file(&pivot, g.argv[2])<0 ){
381 fossil_fatal("cannot read %s\n", g.argv[2]);
382
+4
--- src/name.c
+++ src/name.c
@@ -659,10 +659,14 @@
659659
const char *zName;
660660
int verboseFlag;
661661
int i;
662662
db_find_and_open_repository(0,0);
663663
verboseFlag = find_option("verbose","v",0)!=0;
664
+
665
+ /* We should be done with options.. */
666
+ verify_all_options();
667
+
664668
if( g.argc<3 ) usage("whatis NAME ...");
665669
for(i=2; i<g.argc; i++){
666670
zName = g.argv[i];
667671
if( i>2 ) fossil_print("%.79c\n",'-');
668672
rid = symbolic_name_to_rid(zName, 0);
669673
--- src/name.c
+++ src/name.c
@@ -659,10 +659,14 @@
659 const char *zName;
660 int verboseFlag;
661 int i;
662 db_find_and_open_repository(0,0);
663 verboseFlag = find_option("verbose","v",0)!=0;
 
 
 
 
664 if( g.argc<3 ) usage("whatis NAME ...");
665 for(i=2; i<g.argc; i++){
666 zName = g.argv[i];
667 if( i>2 ) fossil_print("%.79c\n",'-');
668 rid = symbolic_name_to_rid(zName, 0);
669
--- src/name.c
+++ src/name.c
@@ -659,10 +659,14 @@
659 const char *zName;
660 int verboseFlag;
661 int i;
662 db_find_and_open_repository(0,0);
663 verboseFlag = find_option("verbose","v",0)!=0;
664
665 /* We should be done with options.. */
666 verify_all_options();
667
668 if( g.argc<3 ) usage("whatis NAME ...");
669 for(i=2; i<g.argc; i++){
670 zName = g.argv[i];
671 if( i>2 ) fossil_print("%.79c\n",'-');
672 rid = symbolic_name_to_rid(zName, 0);
673
--- src/rebuild.c
+++ src/rebuild.c
@@ -578,10 +578,14 @@
578578
usage("?REPOSITORY-FILENAME?");
579579
}
580580
db_close(1);
581581
db_open_repository(g.zRepositoryName);
582582
}
583
+
584
+ /* We should be done with options.. */
585
+ verify_all_options();
586
+
583587
db_begin_transaction();
584588
ttyOutput = 1;
585589
errCnt = rebuild_db(randomizeFlag, 1, doClustering);
586590
reconstruct_private_table();
587591
db_multi_exec(
@@ -793,10 +797,14 @@
793797
int privateOnly = find_option("private",0,0)!=0;
794798
int bNeedRebuild = 0;
795799
db_find_and_open_repository(OPEN_ANY_SCHEMA, 2);
796800
db_close(1);
797801
db_open_repository(g.zRepositoryName);
802
+
803
+ /* We should be done with options.. */
804
+ verify_all_options();
805
+
798806
if( !bForce ){
799807
Blob ans;
800808
char cReply;
801809
prompt_user(
802810
"Scrubbing the repository will permanently delete information.\n"
@@ -915,10 +923,14 @@
915923
fossil_print("\"%s\" is not a directory\n\n", g.argv[3]);
916924
usage("FILENAME DIRECTORY");
917925
}
918926
db_create_repository(g.argv[2]);
919927
db_open_repository(g.argv[2]);
928
+
929
+ /* We should be done with options.. */
930
+ verify_all_options();
931
+
920932
db_open_config(0);
921933
db_begin_transaction();
922934
db_initial_setup(0, 0, 0, 1);
923935
924936
fossil_print("Reading files from directory \"%s\"...\n", g.argv[3]);
925937
--- src/rebuild.c
+++ src/rebuild.c
@@ -578,10 +578,14 @@
578 usage("?REPOSITORY-FILENAME?");
579 }
580 db_close(1);
581 db_open_repository(g.zRepositoryName);
582 }
 
 
 
 
583 db_begin_transaction();
584 ttyOutput = 1;
585 errCnt = rebuild_db(randomizeFlag, 1, doClustering);
586 reconstruct_private_table();
587 db_multi_exec(
@@ -793,10 +797,14 @@
793 int privateOnly = find_option("private",0,0)!=0;
794 int bNeedRebuild = 0;
795 db_find_and_open_repository(OPEN_ANY_SCHEMA, 2);
796 db_close(1);
797 db_open_repository(g.zRepositoryName);
 
 
 
 
798 if( !bForce ){
799 Blob ans;
800 char cReply;
801 prompt_user(
802 "Scrubbing the repository will permanently delete information.\n"
@@ -915,10 +923,14 @@
915 fossil_print("\"%s\" is not a directory\n\n", g.argv[3]);
916 usage("FILENAME DIRECTORY");
917 }
918 db_create_repository(g.argv[2]);
919 db_open_repository(g.argv[2]);
 
 
 
 
920 db_open_config(0);
921 db_begin_transaction();
922 db_initial_setup(0, 0, 0, 1);
923
924 fossil_print("Reading files from directory \"%s\"...\n", g.argv[3]);
925
--- src/rebuild.c
+++ src/rebuild.c
@@ -578,10 +578,14 @@
578 usage("?REPOSITORY-FILENAME?");
579 }
580 db_close(1);
581 db_open_repository(g.zRepositoryName);
582 }
583
584 /* We should be done with options.. */
585 verify_all_options();
586
587 db_begin_transaction();
588 ttyOutput = 1;
589 errCnt = rebuild_db(randomizeFlag, 1, doClustering);
590 reconstruct_private_table();
591 db_multi_exec(
@@ -793,10 +797,14 @@
797 int privateOnly = find_option("private",0,0)!=0;
798 int bNeedRebuild = 0;
799 db_find_and_open_repository(OPEN_ANY_SCHEMA, 2);
800 db_close(1);
801 db_open_repository(g.zRepositoryName);
802
803 /* We should be done with options.. */
804 verify_all_options();
805
806 if( !bForce ){
807 Blob ans;
808 char cReply;
809 prompt_user(
810 "Scrubbing the repository will permanently delete information.\n"
@@ -915,10 +923,14 @@
923 fossil_print("\"%s\" is not a directory\n\n", g.argv[3]);
924 usage("FILENAME DIRECTORY");
925 }
926 db_create_repository(g.argv[2]);
927 db_open_repository(g.argv[2]);
928
929 /* We should be done with options.. */
930 verify_all_options();
931
932 db_open_config(0);
933 db_begin_transaction();
934 db_initial_setup(0, 0, 0, 1);
935
936 fossil_print("Reading files from directory \"%s\"...\n", g.argv[3]);
937
--- src/regexp.c
+++ src/regexp.c
@@ -768,11 +768,10 @@
768768
*/
769769
void re_test_grep(void){
770770
ReCompiled *pRe;
771771
const char *zErr;
772772
int ignoreCase = find_option("ignore-case","i",0)!=0;
773
-
774773
if( g.argc<3 ){
775774
usage("REGEXP [FILE...]");
776775
}
777776
zErr = re_compile(&pRe, g.argv[2], ignoreCase);
778777
if( zErr ) fossil_fatal("%s", zErr);
779778
--- src/regexp.c
+++ src/regexp.c
@@ -768,11 +768,10 @@
768 */
769 void re_test_grep(void){
770 ReCompiled *pRe;
771 const char *zErr;
772 int ignoreCase = find_option("ignore-case","i",0)!=0;
773
774 if( g.argc<3 ){
775 usage("REGEXP [FILE...]");
776 }
777 zErr = re_compile(&pRe, g.argv[2], ignoreCase);
778 if( zErr ) fossil_fatal("%s", zErr);
779
--- src/regexp.c
+++ src/regexp.c
@@ -768,11 +768,10 @@
768 */
769 void re_test_grep(void){
770 ReCompiled *pRe;
771 const char *zErr;
772 int ignoreCase = find_option("ignore-case","i",0)!=0;
 
773 if( g.argc<3 ){
774 usage("REGEXP [FILE...]");
775 }
776 zErr = re_compile(&pRe, g.argv[2], ignoreCase);
777 if( zErr ) fossil_fatal("%s", zErr);
778
+2 -2
--- src/report.c
+++ src/report.c
@@ -1112,11 +1112,11 @@
11121112
** show all reports, which can be used for ticket show.
11131113
** Output is written to stdout as tab delimited table
11141114
*/
11151115
void rpt_list_reports(void){
11161116
Stmt q;
1117
- char const aRptOutFrmt[] = "%s\t%s\n";
1117
+ const char aRptOutFrmt[] = "%s\t%s\n";
11181118
11191119
fossil_print("Available reports:\n");
11201120
fossil_print(aRptOutFrmt,"report number","report title");
11211121
fossil_print(aRptOutFrmt,zFullTicketRptRn,zFullTicketRptTitle);
11221122
db_prepare(&q,"SELECT rn,title FROM reportfmt ORDER BY rn");
@@ -1217,11 +1217,11 @@
12171217
char *zErr1 = 0;
12181218
char *zErr2 = 0;
12191219
int count = 0;
12201220
int rn;
12211221
1222
- if (!zRep || !strcmp(zRep,zFullTicketRptRn) || !strcmp(zRep,zFullTicketRptTitle) ){
1222
+ if( !zRep || !strcmp(zRep,zFullTicketRptRn) || !strcmp(zRep,zFullTicketRptTitle) ){
12231223
zSql = "SELECT * FROM ticket";
12241224
}else{
12251225
rn = atoi(zRep);
12261226
if( rn ){
12271227
db_prepare(&q,
12281228
--- src/report.c
+++ src/report.c
@@ -1112,11 +1112,11 @@
1112 ** show all reports, which can be used for ticket show.
1113 ** Output is written to stdout as tab delimited table
1114 */
1115 void rpt_list_reports(void){
1116 Stmt q;
1117 char const aRptOutFrmt[] = "%s\t%s\n";
1118
1119 fossil_print("Available reports:\n");
1120 fossil_print(aRptOutFrmt,"report number","report title");
1121 fossil_print(aRptOutFrmt,zFullTicketRptRn,zFullTicketRptTitle);
1122 db_prepare(&q,"SELECT rn,title FROM reportfmt ORDER BY rn");
@@ -1217,11 +1217,11 @@
1217 char *zErr1 = 0;
1218 char *zErr2 = 0;
1219 int count = 0;
1220 int rn;
1221
1222 if (!zRep || !strcmp(zRep,zFullTicketRptRn) || !strcmp(zRep,zFullTicketRptTitle) ){
1223 zSql = "SELECT * FROM ticket";
1224 }else{
1225 rn = atoi(zRep);
1226 if( rn ){
1227 db_prepare(&q,
1228
--- src/report.c
+++ src/report.c
@@ -1112,11 +1112,11 @@
1112 ** show all reports, which can be used for ticket show.
1113 ** Output is written to stdout as tab delimited table
1114 */
1115 void rpt_list_reports(void){
1116 Stmt q;
1117 const char aRptOutFrmt[] = "%s\t%s\n";
1118
1119 fossil_print("Available reports:\n");
1120 fossil_print(aRptOutFrmt,"report number","report title");
1121 fossil_print(aRptOutFrmt,zFullTicketRptRn,zFullTicketRptTitle);
1122 db_prepare(&q,"SELECT rn,title FROM reportfmt ORDER BY rn");
@@ -1217,11 +1217,11 @@
1217 char *zErr1 = 0;
1218 char *zErr2 = 0;
1219 int count = 0;
1220 int rn;
1221
1222 if( !zRep || !strcmp(zRep,zFullTicketRptRn) || !strcmp(zRep,zFullTicketRptTitle) ){
1223 zSql = "SELECT * FROM ticket";
1224 }else{
1225 rn = atoi(zRep);
1226 if( rn ){
1227 db_prepare(&q,
1228
+10 -2
--- src/rss.c
+++ src/rss.c
@@ -27,11 +27,13 @@
2727
** URL: /timeline.rss?y=TYPE&n=LIMIT&tkt=UUID&tag=TAG&wiki=NAME&name=FILENAME
2828
**
2929
** Produce an RSS feed of the timeline.
3030
**
3131
** TYPE may be: all, ci (show checkins only), t (show tickets only),
32
-** w (show wiki only). LIMIT is the number of items to show.
32
+** w (show wiki only).
33
+**
34
+** LIMIT is the number of items to show.
3335
**
3436
** tkt=UUID filters for only those events for the specified ticket. tag=TAG
3537
** filters for a tag, and wiki=NAME for a wiki page. Only one may be used.
3638
**
3739
** In addition, name=FILENAME filters for a specific file. This may be
@@ -212,11 +214,14 @@
212214
** The CLI variant of the /timeline.rss page, this produces an RSS
213215
** feed of the timeline to stdout. Options:
214216
**
215217
** -type|y FLAG
216218
** may be: all (default), ci (show checkins only), t (show tickets only),
217
-** w (show wiki only). LIMIT is the number of items to show.
219
+** w (show wiki only).
220
+**
221
+** -limit|n LIMIT
222
+** The maximum number of items to show.
218223
**
219224
** -tkt UUID
220225
** Filters for only those events for the specified ticket.
221226
**
222227
** -tag TAG
@@ -267,10 +272,13 @@
267272
if(!zBaseURL || !*zBaseURL){
268273
zBaseURL = "URL-PLACEHOLDER";
269274
}
270275
271276
db_find_and_open_repository(0, 0);
277
+
278
+ /* We should be done with options.. */
279
+ verify_all_options();
272280
273281
blob_zero(&bSQL);
274282
blob_append( &bSQL, zSQL1, -1 );
275283
276284
if( zType[0]!='a' ){
277285
--- src/rss.c
+++ src/rss.c
@@ -27,11 +27,13 @@
27 ** URL: /timeline.rss?y=TYPE&n=LIMIT&tkt=UUID&tag=TAG&wiki=NAME&name=FILENAME
28 **
29 ** Produce an RSS feed of the timeline.
30 **
31 ** TYPE may be: all, ci (show checkins only), t (show tickets only),
32 ** w (show wiki only). LIMIT is the number of items to show.
 
 
33 **
34 ** tkt=UUID filters for only those events for the specified ticket. tag=TAG
35 ** filters for a tag, and wiki=NAME for a wiki page. Only one may be used.
36 **
37 ** In addition, name=FILENAME filters for a specific file. This may be
@@ -212,11 +214,14 @@
212 ** The CLI variant of the /timeline.rss page, this produces an RSS
213 ** feed of the timeline to stdout. Options:
214 **
215 ** -type|y FLAG
216 ** may be: all (default), ci (show checkins only), t (show tickets only),
217 ** w (show wiki only). LIMIT is the number of items to show.
 
 
 
218 **
219 ** -tkt UUID
220 ** Filters for only those events for the specified ticket.
221 **
222 ** -tag TAG
@@ -267,10 +272,13 @@
267 if(!zBaseURL || !*zBaseURL){
268 zBaseURL = "URL-PLACEHOLDER";
269 }
270
271 db_find_and_open_repository(0, 0);
 
 
 
272
273 blob_zero(&bSQL);
274 blob_append( &bSQL, zSQL1, -1 );
275
276 if( zType[0]!='a' ){
277
--- src/rss.c
+++ src/rss.c
@@ -27,11 +27,13 @@
27 ** URL: /timeline.rss?y=TYPE&n=LIMIT&tkt=UUID&tag=TAG&wiki=NAME&name=FILENAME
28 **
29 ** Produce an RSS feed of the timeline.
30 **
31 ** TYPE may be: all, ci (show checkins only), t (show tickets only),
32 ** w (show wiki only).
33 **
34 ** LIMIT is the number of items to show.
35 **
36 ** tkt=UUID filters for only those events for the specified ticket. tag=TAG
37 ** filters for a tag, and wiki=NAME for a wiki page. Only one may be used.
38 **
39 ** In addition, name=FILENAME filters for a specific file. This may be
@@ -212,11 +214,14 @@
214 ** The CLI variant of the /timeline.rss page, this produces an RSS
215 ** feed of the timeline to stdout. Options:
216 **
217 ** -type|y FLAG
218 ** may be: all (default), ci (show checkins only), t (show tickets only),
219 ** w (show wiki only).
220 **
221 ** -limit|n LIMIT
222 ** The maximum number of items to show.
223 **
224 ** -tkt UUID
225 ** Filters for only those events for the specified ticket.
226 **
227 ** -tag TAG
@@ -267,10 +272,13 @@
272 if(!zBaseURL || !*zBaseURL){
273 zBaseURL = "URL-PLACEHOLDER";
274 }
275
276 db_find_and_open_repository(0, 0);
277
278 /* We should be done with options.. */
279 verify_all_options();
280
281 blob_zero(&bSQL);
282 blob_append( &bSQL, zSQL1, -1 );
283
284 if( zType[0]!='a' ){
285
+104 -14
--- src/shell.c
+++ src/shell.c
@@ -62,10 +62,11 @@
6262
# define stifle_history(X)
6363
#endif
6464
6565
#if defined(_WIN32) || defined(WIN32)
6666
# include <io.h>
67
+# include <fcntl.h>
6768
#define isatty(h) _isatty(h)
6869
#ifndef access
6970
# define access(f,m) _access((f),(m))
7071
#endif
7172
#undef popen
@@ -456,10 +457,11 @@
456457
int mode; /* An output mode setting */
457458
int writableSchema; /* True if PRAGMA writable_schema=ON */
458459
int showHeader; /* True to show column names in List or Column mode */
459460
char *zDestTable; /* Name of destination table when MODE_Insert */
460461
char separator[20]; /* Separator character for MODE_List */
462
+ char newline[20]; /* Record separator in MODE_Csv */
461463
int colWidth[100]; /* Requested width of each column when in column mode*/
462464
int actualWidth[100]; /* Actual width of each column */
463465
char nullvalue[20]; /* The text to print when a NULL comes back from
464466
** the database */
465467
struct previous_mode_data explainPrev;
@@ -657,11 +659,12 @@
657659
};
658660
659661
/*
660662
** Output a single term of CSV. Actually, p->separator is used for
661663
** the separator, which may or may not be a comma. p->nullvalue is
662
-** the null value. Strings are quoted if necessary.
664
+** the null value. Strings are quoted if necessary. The separator
665
+** is only issued if bSep is true.
663666
*/
664667
static void output_csv(struct callback_data *p, const char *z, int bSep){
665668
FILE *out = p->out;
666669
if( z==0 ){
667670
fprintf(out,"%s",p->nullvalue);
@@ -853,21 +856,30 @@
853856
}
854857
fprintf(p->out,"\n");
855858
break;
856859
}
857860
case MODE_Csv: {
861
+#if defined(WIN32) || defined(_WIN32)
862
+ fflush(p->out);
863
+ _setmode(_fileno(p->out), _O_BINARY);
864
+#endif
858865
if( p->cnt++==0 && p->showHeader ){
859866
for(i=0; i<nArg; i++){
860867
output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
861868
}
862
- fprintf(p->out,"\n");
869
+ fprintf(p->out,"%s",p->newline);
863870
}
864
- if( azArg==0 ) break;
865
- for(i=0; i<nArg; i++){
866
- output_csv(p, azArg[i], i<nArg-1);
871
+ if( azArg>0 ){
872
+ for(i=0; i<nArg; i++){
873
+ output_csv(p, azArg[i], i<nArg-1);
874
+ }
875
+ fprintf(p->out,"%s",p->newline);
867876
}
868
- fprintf(p->out,"\n");
877
+#if defined(WIN32) || defined(_WIN32)
878
+ fflush(p->out);
879
+ _setmode(_fileno(p->out), _O_TEXT);
880
+#endif
869881
break;
870882
}
871883
case MODE_Insert: {
872884
p->cnt++;
873885
if( azArg==0 ) break;
@@ -1617,11 +1629,12 @@
16171629
".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n"
16181630
".save FILE Write in-memory database into FILE\n"
16191631
".schema ?TABLE? Show the CREATE statements\n"
16201632
" If TABLE specified, only show tables matching\n"
16211633
" LIKE pattern TABLE.\n"
1622
- ".separator STRING Change separator used by output mode and .import\n"
1634
+ ".separator STRING ?NL? Change separator used by output mode and .import\n"
1635
+ " NL is the end-of-line mark for CSV\n"
16231636
".shell CMD ARGS... Run CMD ARGS... in a system shell\n"
16241637
".show Show the current values for various settings\n"
16251638
".stats on|off Turn stats on or off\n"
16261639
".system CMD ARGS... Run CMD ARGS... in a system shell\n"
16271640
".tables ?TABLE? List names of tables\n"
@@ -1635,10 +1648,70 @@
16351648
" Negative values right-justify\n"
16361649
;
16371650
16381651
/* Forward reference */
16391652
static int process_input(struct callback_data *p, FILE *in);
1653
+/*
1654
+** Implementation of the "readfile(X)" SQL function. The entire content
1655
+** of the file named X is read and returned as a BLOB. NULL is returned
1656
+** if the file does not exist or is unreadable.
1657
+*/
1658
+static void readfileFunc(
1659
+ sqlite3_context *context,
1660
+ int argc,
1661
+ sqlite3_value **argv
1662
+){
1663
+ const char *zName;
1664
+ FILE *in;
1665
+ long nIn;
1666
+ void *pBuf;
1667
+
1668
+ zName = (const char*)sqlite3_value_text(argv[0]);
1669
+ if( zName==0 ) return;
1670
+ in = fopen(zName, "rb");
1671
+ if( in==0 ) return;
1672
+ fseek(in, 0, SEEK_END);
1673
+ nIn = ftell(in);
1674
+ rewind(in);
1675
+ pBuf = sqlite3_malloc( nIn );
1676
+ if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
1677
+ sqlite3_result_blob(context, pBuf, nIn, sqlite3_free);
1678
+ }else{
1679
+ sqlite3_free(pBuf);
1680
+ }
1681
+ fclose(in);
1682
+}
1683
+
1684
+/*
1685
+** Implementation of the "writefile(X,Y)" SQL function. The argument Y
1686
+** is written into file X. The number of bytes written is returned. Or
1687
+** NULL is returned if something goes wrong, such as being unable to open
1688
+** file X for writing.
1689
+*/
1690
+static void writefileFunc(
1691
+ sqlite3_context *context,
1692
+ int argc,
1693
+ sqlite3_value **argv
1694
+){
1695
+ FILE *out;
1696
+ const char *z;
1697
+ sqlite3_int64 rc;
1698
+ const char *zFile;
1699
+
1700
+ zFile = (const char*)sqlite3_value_text(argv[0]);
1701
+ if( zFile==0 ) return;
1702
+ out = fopen(zFile, "wb");
1703
+ if( out==0 ) return;
1704
+ z = (const char*)sqlite3_value_blob(argv[1]);
1705
+ if( z==0 ){
1706
+ rc = 0;
1707
+ }else{
1708
+ rc = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out);
1709
+ }
1710
+ fclose(out);
1711
+ sqlite3_result_int64(context, rc);
1712
+}
16401713
16411714
/*
16421715
** Make sure the database is open. If it is not, then open it. If
16431716
** the database fails to open, print an error message and exit.
16441717
*/
@@ -1658,10 +1731,14 @@
16581731
exit(1);
16591732
}
16601733
#ifndef SQLITE_OMIT_LOAD_EXTENSION
16611734
sqlite3_enable_load_extension(p->db, 1);
16621735
#endif
1736
+ sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,
1737
+ readfileFunc, 0, 0);
1738
+ sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0,
1739
+ writefileFunc, 0, 0);
16631740
}
16641741
}
16651742
16661743
/*
16671744
** Do C-language style dequoting.
@@ -2749,10 +2826,11 @@
27492826
p->mode = MODE_Tcl;
27502827
sqlite3_snprintf(sizeof(p->separator), p->separator, " ");
27512828
}else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
27522829
p->mode = MODE_Csv;
27532830
sqlite3_snprintf(sizeof(p->separator), p->separator, ",");
2831
+ sqlite3_snprintf(sizeof(p->newline), p->newline, "\r\n");
27542832
}else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
27552833
p->mode = MODE_List;
27562834
sqlite3_snprintf(sizeof(p->separator), p->separator, "\t");
27572835
}else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
27582836
p->mode = MODE_Insert;
@@ -3027,24 +3105,27 @@
30273105
}
30283106
}else
30293107
#endif
30303108
30313109
if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
3032
- if( nArg==2 ){
3033
- sqlite3_snprintf(sizeof(p->separator), p->separator,
3034
- "%.*s", (int)sizeof(p->separator)-1, azArg[1]);
3035
- }else{
3036
- fprintf(stderr, "Usage: .separator STRING\n");
3110
+ if( nArg<2 || nArg>3 ){
3111
+ fprintf(stderr, "Usage: .separator SEPARATOR ?NEWLINE?\n");
30373112
rc = 1;
30383113
}
3114
+ if( nArg>=2 ){
3115
+ sqlite3_snprintf(sizeof(p->separator), p->separator, azArg[1]);
3116
+ }
3117
+ if( nArg>=3 ){
3118
+ sqlite3_snprintf(sizeof(p->newline), p->newline, azArg[2]);
3119
+ }
30393120
}else
30403121
30413122
if( c=='s'
30423123
&& (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
30433124
){
30443125
char *zCmd;
3045
- int i;
3126
+ int i, x;
30463127
if( nArg<2 ){
30473128
fprintf(stderr, "Usage: .system COMMAND\n");
30483129
rc = 1;
30493130
goto meta_command_exit;
30503131
}
@@ -3051,12 +3132,13 @@
30513132
zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
30523133
for(i=2; i<nArg; i++){
30533134
zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
30543135
zCmd, azArg[i]);
30553136
}
3056
- (void)system(zCmd);
3137
+ x = system(zCmd);
30573138
sqlite3_free(zCmd);
3139
+ if( x ) fprintf(stderr, "System command returns %d\n", x);
30583140
}else
30593141
30603142
if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
30613143
int i;
30623144
if( nArg!=1 ){
@@ -3074,10 +3156,12 @@
30743156
fprintf(p->out, "\n");
30753157
fprintf(p->out,"%9.9s: %s\n","output",
30763158
strlen30(p->outfile) ? p->outfile : "stdout");
30773159
fprintf(p->out,"%9.9s: ", "separator");
30783160
output_c_string(p->out, p->separator);
3161
+ fprintf(p->out," ");
3162
+ output_c_string(p->out, p->newline);
30793163
fprintf(p->out, "\n");
30803164
fprintf(p->out,"%9.9s: %s\n","stats", p->statsOn ? "on" : "off");
30813165
fprintf(p->out,"%9.9s: ","width");
30823166
for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
30833167
fprintf(p->out,"%d ",p->colWidth[i]);
@@ -3690,10 +3774,11 @@
36903774
" -list set output mode to 'list'\n"
36913775
" -mmap N default mmap size set to N\n"
36923776
#ifdef SQLITE_ENABLE_MULTIPLEX
36933777
" -multiplex enable the multiplexor VFS\n"
36943778
#endif
3779
+ " -newline SEP set newline character(s) for CSV\n"
36953780
" -nullvalue TEXT set text string for NULL values. Default ''\n"
36963781
" -separator SEP set output field separator. Default: '|'\n"
36973782
" -stats print memory stats before each finalize\n"
36983783
" -version show SQLite version\n"
36993784
" -vfs NAME use NAME as the default VFS\n"
@@ -3719,10 +3804,11 @@
37193804
*/
37203805
static void main_init(struct callback_data *data) {
37213806
memset(data, 0, sizeof(*data));
37223807
data->mode = MODE_List;
37233808
memcpy(data->separator,"|", 2);
3809
+ memcpy(data->newline,"\r\n", 3);
37243810
data->showHeader = 0;
37253811
sqlite3_config(SQLITE_CONFIG_URI, 1);
37263812
sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
37273813
sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
37283814
sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
@@ -3811,10 +3897,11 @@
38113897
return 1;
38123898
}
38133899
if( z[1]=='-' ) z++;
38143900
if( strcmp(z,"-separator")==0
38153901
|| strcmp(z,"-nullvalue")==0
3902
+ || strcmp(z,"-newline")==0
38163903
|| strcmp(z,"-cmd")==0
38173904
){
38183905
(void)cmdline_option_value(argc, argv, ++i);
38193906
}else if( strcmp(z,"-init")==0 ){
38203907
zInitFile = cmdline_option_value(argc, argv, ++i);
@@ -3920,10 +4007,13 @@
39204007
data.mode = MODE_Csv;
39214008
memcpy(data.separator,",",2);
39224009
}else if( strcmp(z,"-separator")==0 ){
39234010
sqlite3_snprintf(sizeof(data.separator), data.separator,
39244011
"%s",cmdline_option_value(argc,argv,++i));
4012
+ }else if( strcmp(z,"-newline")==0 ){
4013
+ sqlite3_snprintf(sizeof(data.newline), data.newline,
4014
+ "%s",cmdline_option_value(argc,argv,++i));
39254015
}else if( strcmp(z,"-nullvalue")==0 ){
39264016
sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue,
39274017
"%s",cmdline_option_value(argc,argv,++i));
39284018
}else if( strcmp(z,"-header")==0 ){
39294019
data.showHeader = 1;
39304020
--- src/shell.c
+++ src/shell.c
@@ -62,10 +62,11 @@
62 # define stifle_history(X)
63 #endif
64
65 #if defined(_WIN32) || defined(WIN32)
66 # include <io.h>
 
67 #define isatty(h) _isatty(h)
68 #ifndef access
69 # define access(f,m) _access((f),(m))
70 #endif
71 #undef popen
@@ -456,10 +457,11 @@
456 int mode; /* An output mode setting */
457 int writableSchema; /* True if PRAGMA writable_schema=ON */
458 int showHeader; /* True to show column names in List or Column mode */
459 char *zDestTable; /* Name of destination table when MODE_Insert */
460 char separator[20]; /* Separator character for MODE_List */
 
461 int colWidth[100]; /* Requested width of each column when in column mode*/
462 int actualWidth[100]; /* Actual width of each column */
463 char nullvalue[20]; /* The text to print when a NULL comes back from
464 ** the database */
465 struct previous_mode_data explainPrev;
@@ -657,11 +659,12 @@
657 };
658
659 /*
660 ** Output a single term of CSV. Actually, p->separator is used for
661 ** the separator, which may or may not be a comma. p->nullvalue is
662 ** the null value. Strings are quoted if necessary.
 
663 */
664 static void output_csv(struct callback_data *p, const char *z, int bSep){
665 FILE *out = p->out;
666 if( z==0 ){
667 fprintf(out,"%s",p->nullvalue);
@@ -853,21 +856,30 @@
853 }
854 fprintf(p->out,"\n");
855 break;
856 }
857 case MODE_Csv: {
 
 
 
 
858 if( p->cnt++==0 && p->showHeader ){
859 for(i=0; i<nArg; i++){
860 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
861 }
862 fprintf(p->out,"\n");
863 }
864 if( azArg==0 ) break;
865 for(i=0; i<nArg; i++){
866 output_csv(p, azArg[i], i<nArg-1);
 
 
867 }
868 fprintf(p->out,"\n");
 
 
 
869 break;
870 }
871 case MODE_Insert: {
872 p->cnt++;
873 if( azArg==0 ) break;
@@ -1617,11 +1629,12 @@
1617 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n"
1618 ".save FILE Write in-memory database into FILE\n"
1619 ".schema ?TABLE? Show the CREATE statements\n"
1620 " If TABLE specified, only show tables matching\n"
1621 " LIKE pattern TABLE.\n"
1622 ".separator STRING Change separator used by output mode and .import\n"
 
1623 ".shell CMD ARGS... Run CMD ARGS... in a system shell\n"
1624 ".show Show the current values for various settings\n"
1625 ".stats on|off Turn stats on or off\n"
1626 ".system CMD ARGS... Run CMD ARGS... in a system shell\n"
1627 ".tables ?TABLE? List names of tables\n"
@@ -1635,10 +1648,70 @@
1635 " Negative values right-justify\n"
1636 ;
1637
1638 /* Forward reference */
1639 static int process_input(struct callback_data *p, FILE *in);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1640
1641 /*
1642 ** Make sure the database is open. If it is not, then open it. If
1643 ** the database fails to open, print an error message and exit.
1644 */
@@ -1658,10 +1731,14 @@
1658 exit(1);
1659 }
1660 #ifndef SQLITE_OMIT_LOAD_EXTENSION
1661 sqlite3_enable_load_extension(p->db, 1);
1662 #endif
 
 
 
 
1663 }
1664 }
1665
1666 /*
1667 ** Do C-language style dequoting.
@@ -2749,10 +2826,11 @@
2749 p->mode = MODE_Tcl;
2750 sqlite3_snprintf(sizeof(p->separator), p->separator, " ");
2751 }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
2752 p->mode = MODE_Csv;
2753 sqlite3_snprintf(sizeof(p->separator), p->separator, ",");
 
2754 }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
2755 p->mode = MODE_List;
2756 sqlite3_snprintf(sizeof(p->separator), p->separator, "\t");
2757 }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
2758 p->mode = MODE_Insert;
@@ -3027,24 +3105,27 @@
3027 }
3028 }else
3029 #endif
3030
3031 if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
3032 if( nArg==2 ){
3033 sqlite3_snprintf(sizeof(p->separator), p->separator,
3034 "%.*s", (int)sizeof(p->separator)-1, azArg[1]);
3035 }else{
3036 fprintf(stderr, "Usage: .separator STRING\n");
3037 rc = 1;
3038 }
 
 
 
 
 
 
3039 }else
3040
3041 if( c=='s'
3042 && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
3043 ){
3044 char *zCmd;
3045 int i;
3046 if( nArg<2 ){
3047 fprintf(stderr, "Usage: .system COMMAND\n");
3048 rc = 1;
3049 goto meta_command_exit;
3050 }
@@ -3051,12 +3132,13 @@
3051 zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
3052 for(i=2; i<nArg; i++){
3053 zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
3054 zCmd, azArg[i]);
3055 }
3056 (void)system(zCmd);
3057 sqlite3_free(zCmd);
 
3058 }else
3059
3060 if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
3061 int i;
3062 if( nArg!=1 ){
@@ -3074,10 +3156,12 @@
3074 fprintf(p->out, "\n");
3075 fprintf(p->out,"%9.9s: %s\n","output",
3076 strlen30(p->outfile) ? p->outfile : "stdout");
3077 fprintf(p->out,"%9.9s: ", "separator");
3078 output_c_string(p->out, p->separator);
 
 
3079 fprintf(p->out, "\n");
3080 fprintf(p->out,"%9.9s: %s\n","stats", p->statsOn ? "on" : "off");
3081 fprintf(p->out,"%9.9s: ","width");
3082 for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
3083 fprintf(p->out,"%d ",p->colWidth[i]);
@@ -3690,10 +3774,11 @@
3690 " -list set output mode to 'list'\n"
3691 " -mmap N default mmap size set to N\n"
3692 #ifdef SQLITE_ENABLE_MULTIPLEX
3693 " -multiplex enable the multiplexor VFS\n"
3694 #endif
 
3695 " -nullvalue TEXT set text string for NULL values. Default ''\n"
3696 " -separator SEP set output field separator. Default: '|'\n"
3697 " -stats print memory stats before each finalize\n"
3698 " -version show SQLite version\n"
3699 " -vfs NAME use NAME as the default VFS\n"
@@ -3719,10 +3804,11 @@
3719 */
3720 static void main_init(struct callback_data *data) {
3721 memset(data, 0, sizeof(*data));
3722 data->mode = MODE_List;
3723 memcpy(data->separator,"|", 2);
 
3724 data->showHeader = 0;
3725 sqlite3_config(SQLITE_CONFIG_URI, 1);
3726 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
3727 sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
3728 sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
@@ -3811,10 +3897,11 @@
3811 return 1;
3812 }
3813 if( z[1]=='-' ) z++;
3814 if( strcmp(z,"-separator")==0
3815 || strcmp(z,"-nullvalue")==0
 
3816 || strcmp(z,"-cmd")==0
3817 ){
3818 (void)cmdline_option_value(argc, argv, ++i);
3819 }else if( strcmp(z,"-init")==0 ){
3820 zInitFile = cmdline_option_value(argc, argv, ++i);
@@ -3920,10 +4007,13 @@
3920 data.mode = MODE_Csv;
3921 memcpy(data.separator,",",2);
3922 }else if( strcmp(z,"-separator")==0 ){
3923 sqlite3_snprintf(sizeof(data.separator), data.separator,
3924 "%s",cmdline_option_value(argc,argv,++i));
 
 
 
3925 }else if( strcmp(z,"-nullvalue")==0 ){
3926 sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue,
3927 "%s",cmdline_option_value(argc,argv,++i));
3928 }else if( strcmp(z,"-header")==0 ){
3929 data.showHeader = 1;
3930
--- src/shell.c
+++ src/shell.c
@@ -62,10 +62,11 @@
62 # define stifle_history(X)
63 #endif
64
65 #if defined(_WIN32) || defined(WIN32)
66 # include <io.h>
67 # include <fcntl.h>
68 #define isatty(h) _isatty(h)
69 #ifndef access
70 # define access(f,m) _access((f),(m))
71 #endif
72 #undef popen
@@ -456,10 +457,11 @@
457 int mode; /* An output mode setting */
458 int writableSchema; /* True if PRAGMA writable_schema=ON */
459 int showHeader; /* True to show column names in List or Column mode */
460 char *zDestTable; /* Name of destination table when MODE_Insert */
461 char separator[20]; /* Separator character for MODE_List */
462 char newline[20]; /* Record separator in MODE_Csv */
463 int colWidth[100]; /* Requested width of each column when in column mode*/
464 int actualWidth[100]; /* Actual width of each column */
465 char nullvalue[20]; /* The text to print when a NULL comes back from
466 ** the database */
467 struct previous_mode_data explainPrev;
@@ -657,11 +659,12 @@
659 };
660
661 /*
662 ** Output a single term of CSV. Actually, p->separator is used for
663 ** the separator, which may or may not be a comma. p->nullvalue is
664 ** the null value. Strings are quoted if necessary. The separator
665 ** is only issued if bSep is true.
666 */
667 static void output_csv(struct callback_data *p, const char *z, int bSep){
668 FILE *out = p->out;
669 if( z==0 ){
670 fprintf(out,"%s",p->nullvalue);
@@ -853,21 +856,30 @@
856 }
857 fprintf(p->out,"\n");
858 break;
859 }
860 case MODE_Csv: {
861 #if defined(WIN32) || defined(_WIN32)
862 fflush(p->out);
863 _setmode(_fileno(p->out), _O_BINARY);
864 #endif
865 if( p->cnt++==0 && p->showHeader ){
866 for(i=0; i<nArg; i++){
867 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
868 }
869 fprintf(p->out,"%s",p->newline);
870 }
871 if( azArg>0 ){
872 for(i=0; i<nArg; i++){
873 output_csv(p, azArg[i], i<nArg-1);
874 }
875 fprintf(p->out,"%s",p->newline);
876 }
877 #if defined(WIN32) || defined(_WIN32)
878 fflush(p->out);
879 _setmode(_fileno(p->out), _O_TEXT);
880 #endif
881 break;
882 }
883 case MODE_Insert: {
884 p->cnt++;
885 if( azArg==0 ) break;
@@ -1617,11 +1629,12 @@
1629 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n"
1630 ".save FILE Write in-memory database into FILE\n"
1631 ".schema ?TABLE? Show the CREATE statements\n"
1632 " If TABLE specified, only show tables matching\n"
1633 " LIKE pattern TABLE.\n"
1634 ".separator STRING ?NL? Change separator used by output mode and .import\n"
1635 " NL is the end-of-line mark for CSV\n"
1636 ".shell CMD ARGS... Run CMD ARGS... in a system shell\n"
1637 ".show Show the current values for various settings\n"
1638 ".stats on|off Turn stats on or off\n"
1639 ".system CMD ARGS... Run CMD ARGS... in a system shell\n"
1640 ".tables ?TABLE? List names of tables\n"
@@ -1635,10 +1648,70 @@
1648 " Negative values right-justify\n"
1649 ;
1650
1651 /* Forward reference */
1652 static int process_input(struct callback_data *p, FILE *in);
1653 /*
1654 ** Implementation of the "readfile(X)" SQL function. The entire content
1655 ** of the file named X is read and returned as a BLOB. NULL is returned
1656 ** if the file does not exist or is unreadable.
1657 */
1658 static void readfileFunc(
1659 sqlite3_context *context,
1660 int argc,
1661 sqlite3_value **argv
1662 ){
1663 const char *zName;
1664 FILE *in;
1665 long nIn;
1666 void *pBuf;
1667
1668 zName = (const char*)sqlite3_value_text(argv[0]);
1669 if( zName==0 ) return;
1670 in = fopen(zName, "rb");
1671 if( in==0 ) return;
1672 fseek(in, 0, SEEK_END);
1673 nIn = ftell(in);
1674 rewind(in);
1675 pBuf = sqlite3_malloc( nIn );
1676 if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
1677 sqlite3_result_blob(context, pBuf, nIn, sqlite3_free);
1678 }else{
1679 sqlite3_free(pBuf);
1680 }
1681 fclose(in);
1682 }
1683
1684 /*
1685 ** Implementation of the "writefile(X,Y)" SQL function. The argument Y
1686 ** is written into file X. The number of bytes written is returned. Or
1687 ** NULL is returned if something goes wrong, such as being unable to open
1688 ** file X for writing.
1689 */
1690 static void writefileFunc(
1691 sqlite3_context *context,
1692 int argc,
1693 sqlite3_value **argv
1694 ){
1695 FILE *out;
1696 const char *z;
1697 sqlite3_int64 rc;
1698 const char *zFile;
1699
1700 zFile = (const char*)sqlite3_value_text(argv[0]);
1701 if( zFile==0 ) return;
1702 out = fopen(zFile, "wb");
1703 if( out==0 ) return;
1704 z = (const char*)sqlite3_value_blob(argv[1]);
1705 if( z==0 ){
1706 rc = 0;
1707 }else{
1708 rc = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out);
1709 }
1710 fclose(out);
1711 sqlite3_result_int64(context, rc);
1712 }
1713
1714 /*
1715 ** Make sure the database is open. If it is not, then open it. If
1716 ** the database fails to open, print an error message and exit.
1717 */
@@ -1658,10 +1731,14 @@
1731 exit(1);
1732 }
1733 #ifndef SQLITE_OMIT_LOAD_EXTENSION
1734 sqlite3_enable_load_extension(p->db, 1);
1735 #endif
1736 sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,
1737 readfileFunc, 0, 0);
1738 sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0,
1739 writefileFunc, 0, 0);
1740 }
1741 }
1742
1743 /*
1744 ** Do C-language style dequoting.
@@ -2749,10 +2826,11 @@
2826 p->mode = MODE_Tcl;
2827 sqlite3_snprintf(sizeof(p->separator), p->separator, " ");
2828 }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
2829 p->mode = MODE_Csv;
2830 sqlite3_snprintf(sizeof(p->separator), p->separator, ",");
2831 sqlite3_snprintf(sizeof(p->newline), p->newline, "\r\n");
2832 }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
2833 p->mode = MODE_List;
2834 sqlite3_snprintf(sizeof(p->separator), p->separator, "\t");
2835 }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
2836 p->mode = MODE_Insert;
@@ -3027,24 +3105,27 @@
3105 }
3106 }else
3107 #endif
3108
3109 if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
3110 if( nArg<2 || nArg>3 ){
3111 fprintf(stderr, "Usage: .separator SEPARATOR ?NEWLINE?\n");
 
 
 
3112 rc = 1;
3113 }
3114 if( nArg>=2 ){
3115 sqlite3_snprintf(sizeof(p->separator), p->separator, azArg[1]);
3116 }
3117 if( nArg>=3 ){
3118 sqlite3_snprintf(sizeof(p->newline), p->newline, azArg[2]);
3119 }
3120 }else
3121
3122 if( c=='s'
3123 && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
3124 ){
3125 char *zCmd;
3126 int i, x;
3127 if( nArg<2 ){
3128 fprintf(stderr, "Usage: .system COMMAND\n");
3129 rc = 1;
3130 goto meta_command_exit;
3131 }
@@ -3051,12 +3132,13 @@
3132 zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
3133 for(i=2; i<nArg; i++){
3134 zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
3135 zCmd, azArg[i]);
3136 }
3137 x = system(zCmd);
3138 sqlite3_free(zCmd);
3139 if( x ) fprintf(stderr, "System command returns %d\n", x);
3140 }else
3141
3142 if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
3143 int i;
3144 if( nArg!=1 ){
@@ -3074,10 +3156,12 @@
3156 fprintf(p->out, "\n");
3157 fprintf(p->out,"%9.9s: %s\n","output",
3158 strlen30(p->outfile) ? p->outfile : "stdout");
3159 fprintf(p->out,"%9.9s: ", "separator");
3160 output_c_string(p->out, p->separator);
3161 fprintf(p->out," ");
3162 output_c_string(p->out, p->newline);
3163 fprintf(p->out, "\n");
3164 fprintf(p->out,"%9.9s: %s\n","stats", p->statsOn ? "on" : "off");
3165 fprintf(p->out,"%9.9s: ","width");
3166 for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
3167 fprintf(p->out,"%d ",p->colWidth[i]);
@@ -3690,10 +3774,11 @@
3774 " -list set output mode to 'list'\n"
3775 " -mmap N default mmap size set to N\n"
3776 #ifdef SQLITE_ENABLE_MULTIPLEX
3777 " -multiplex enable the multiplexor VFS\n"
3778 #endif
3779 " -newline SEP set newline character(s) for CSV\n"
3780 " -nullvalue TEXT set text string for NULL values. Default ''\n"
3781 " -separator SEP set output field separator. Default: '|'\n"
3782 " -stats print memory stats before each finalize\n"
3783 " -version show SQLite version\n"
3784 " -vfs NAME use NAME as the default VFS\n"
@@ -3719,10 +3804,11 @@
3804 */
3805 static void main_init(struct callback_data *data) {
3806 memset(data, 0, sizeof(*data));
3807 data->mode = MODE_List;
3808 memcpy(data->separator,"|", 2);
3809 memcpy(data->newline,"\r\n", 3);
3810 data->showHeader = 0;
3811 sqlite3_config(SQLITE_CONFIG_URI, 1);
3812 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
3813 sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
3814 sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
@@ -3811,10 +3897,11 @@
3897 return 1;
3898 }
3899 if( z[1]=='-' ) z++;
3900 if( strcmp(z,"-separator")==0
3901 || strcmp(z,"-nullvalue")==0
3902 || strcmp(z,"-newline")==0
3903 || strcmp(z,"-cmd")==0
3904 ){
3905 (void)cmdline_option_value(argc, argv, ++i);
3906 }else if( strcmp(z,"-init")==0 ){
3907 zInitFile = cmdline_option_value(argc, argv, ++i);
@@ -3920,10 +4007,13 @@
4007 data.mode = MODE_Csv;
4008 memcpy(data.separator,",",2);
4009 }else if( strcmp(z,"-separator")==0 ){
4010 sqlite3_snprintf(sizeof(data.separator), data.separator,
4011 "%s",cmdline_option_value(argc,argv,++i));
4012 }else if( strcmp(z,"-newline")==0 ){
4013 sqlite3_snprintf(sizeof(data.newline), data.newline,
4014 "%s",cmdline_option_value(argc,argv,++i));
4015 }else if( strcmp(z,"-nullvalue")==0 ){
4016 sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue,
4017 "%s",cmdline_option_value(argc,argv,++i));
4018 }else if( strcmp(z,"-header")==0 ){
4019 data.showHeader = 1;
4020
+1733 -906
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -222,11 +222,11 @@
222222
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
223223
** [sqlite_version()] and [sqlite_source_id()].
224224
*/
225225
#define SQLITE_VERSION "3.8.6"
226226
#define SQLITE_VERSION_NUMBER 3008006
227
-#define SQLITE_SOURCE_ID "2014-07-01 11:54:02 21981e35062cc6b30e9576786cbf55265a7a4d41"
227
+#define SQLITE_SOURCE_ID "2014-08-12 16:13:37 6715991296886c2a02b9a285a1e61189ad1f79c0"
228228
229229
/*
230230
** CAPI3REF: Run-Time Library Version Numbers
231231
** KEYWORDS: sqlite3_version, sqlite3_sourceid
232232
**
@@ -382,19 +382,19 @@
382382
/*
383383
** CAPI3REF: Closing A Database Connection
384384
**
385385
** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
386386
** for the [sqlite3] object.
387
-** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if
387
+** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
388388
** the [sqlite3] object is successfully destroyed and all associated
389389
** resources are deallocated.
390390
**
391391
** ^If the database connection is associated with unfinalized prepared
392392
** statements or unfinished sqlite3_backup objects then sqlite3_close()
393393
** will leave the database connection open and return [SQLITE_BUSY].
394394
** ^If sqlite3_close_v2() is called with unfinalized prepared statements
395
-** and unfinished sqlite3_backups, then the database connection becomes
395
+** and/or unfinished sqlite3_backups, then the database connection becomes
396396
** an unusable "zombie" which will automatically be deallocated when the
397397
** last prepared statement is finalized or the last sqlite3_backup is
398398
** finished. The sqlite3_close_v2() interface is intended for use with
399399
** host languages that are garbage collected, and where the order in which
400400
** destructors are called is arbitrary.
@@ -403,11 +403,11 @@
403403
** [sqlite3_blob_close | close] all [BLOB handles], and
404404
** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
405405
** with the [sqlite3] object prior to attempting to close the object. ^If
406406
** sqlite3_close_v2() is called on a [database connection] that still has
407407
** outstanding [prepared statements], [BLOB handles], and/or
408
-** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation
408
+** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
409409
** of resources is deferred until all [prepared statements], [BLOB handles],
410410
** and [sqlite3_backup] objects are also destroyed.
411411
**
412412
** ^If an [sqlite3] object is destroyed while a transaction is open,
413413
** the transaction is automatically rolled back.
@@ -499,20 +499,18 @@
499499
char **errmsg /* Error msg written here */
500500
);
501501
502502
/*
503503
** CAPI3REF: Result Codes
504
-** KEYWORDS: SQLITE_OK {error code} {error codes}
505
-** KEYWORDS: {result code} {result codes}
504
+** KEYWORDS: {result code definitions}
506505
**
507506
** Many SQLite functions return an integer result code from the set shown
508507
** here in order to indicate success or failure.
509508
**
510509
** New error codes may be added in future versions of SQLite.
511510
**
512
-** See also: [SQLITE_IOERR_READ | extended result codes],
513
-** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
511
+** See also: [extended result code definitions]
514512
*/
515513
#define SQLITE_OK 0 /* Successful result */
516514
/* beginning-of-error-codes */
517515
#define SQLITE_ERROR 1 /* SQL error or missing database */
518516
#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
@@ -546,30 +544,23 @@
546544
#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */
547545
/* end-of-error-codes */
548546
549547
/*
550548
** CAPI3REF: Extended Result Codes
551
-** KEYWORDS: {extended error code} {extended error codes}
552
-** KEYWORDS: {extended result code} {extended result codes}
549
+** KEYWORDS: {extended result code definitions}
553550
**
554
-** In its default configuration, SQLite API routines return one of 26 integer
555
-** [SQLITE_OK | result codes]. However, experience has shown that many of
551
+** In its default configuration, SQLite API routines return one of 30 integer
552
+** [result codes]. However, experience has shown that many of
556553
** these result codes are too coarse-grained. They do not provide as
557554
** much information about problems as programmers might like. In an effort to
558555
** address this, newer versions of SQLite (version 3.3.8 and later) include
559556
** support for additional result codes that provide more detailed information
560
-** about errors. The extended result codes are enabled or disabled
557
+** about errors. These [extended result codes] are enabled or disabled
561558
** on a per database connection basis using the
562
-** [sqlite3_extended_result_codes()] API.
563
-**
564
-** Some of the available extended result codes are listed here.
565
-** One may expect the number of extended result codes will increase
566
-** over time. Software that uses extended result codes should expect
567
-** to see new result codes in future releases of SQLite.
568
-**
569
-** The SQLITE_OK result code will never be extended. It will always
570
-** be exactly zero.
559
+** [sqlite3_extended_result_codes()] API. Or, the extended code for
560
+** the most recent error can be obtained using
561
+** [sqlite3_extended_errcode()].
571562
*/
572563
#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
573564
#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
574565
#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8))
575566
#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8))
@@ -798,11 +789,11 @@
798789
** write return values. Potential uses for xFileControl() might be
799790
** functions to enable blocking locks with timeouts, to change the
800791
** locking strategy (for example to use dot-file locks), to inquire
801792
** about the status of a lock, or to break stale locks. The SQLite
802793
** core reserves all opcodes less than 100 for its own use.
803
-** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available.
794
+** A [file control opcodes | list of opcodes] less than 100 is available.
804795
** Applications that define a custom xFileControl method should use opcodes
805796
** greater than 100 to avoid conflicts. VFS implementations should
806797
** return [SQLITE_NOTFOUND] for file control opcodes that they do not
807798
** recognize.
808799
**
@@ -871,10 +862,11 @@
871862
/* Additional methods may be added in future releases */
872863
};
873864
874865
/*
875866
** CAPI3REF: Standard File Control Opcodes
867
+** KEYWORDS: {file control opcodes} {file control opcode}
876868
**
877869
** These integer constants are opcodes for the xFileControl method
878870
** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
879871
** interface.
880872
**
@@ -2150,31 +2142,37 @@
21502142
SQLITE_API int sqlite3_complete16(const void *sql);
21512143
21522144
/*
21532145
** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
21542146
**
2155
-** ^This routine sets a callback function that might be invoked whenever
2156
-** an attempt is made to open a database table that another thread
2157
-** or process has locked.
2147
+** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
2148
+** that might be invoked with argument P whenever
2149
+** an attempt is made to access a database table associated with
2150
+** [database connection] D when another thread
2151
+** or process has the table locked.
2152
+** The sqlite3_busy_handler() interface is used to implement
2153
+** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout].
21582154
**
2159
-** ^If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]
2155
+** ^If the busy callback is NULL, then [SQLITE_BUSY]
21602156
** is returned immediately upon encountering the lock. ^If the busy callback
21612157
** is not NULL, then the callback might be invoked with two arguments.
21622158
**
21632159
** ^The first argument to the busy handler is a copy of the void* pointer which
21642160
** is the third argument to sqlite3_busy_handler(). ^The second argument to
21652161
** the busy handler callback is the number of times that the busy handler has
2166
-** been invoked for this locking event. ^If the
2162
+** been invoked for the same locking event. ^If the
21672163
** busy callback returns 0, then no additional attempts are made to
2168
-** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned.
2164
+** access the database and [SQLITE_BUSY] is returned
2165
+** to the application.
21692166
** ^If the callback returns non-zero, then another attempt
2170
-** is made to open the database for reading and the cycle repeats.
2167
+** is made to access the database and the cycle repeats.
21712168
**
21722169
** The presence of a busy handler does not guarantee that it will be invoked
21732170
** when there is lock contention. ^If SQLite determines that invoking the busy
21742171
** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY]
2175
-** or [SQLITE_IOERR_BLOCKED] instead of invoking the busy handler.
2172
+** to the application instead of invoking the
2173
+** busy handler.
21762174
** Consider a scenario where one process is holding a read lock that
21772175
** it is trying to promote to a reserved lock and
21782176
** a second process is holding a reserved lock that it is trying
21792177
** to promote to an exclusive lock. The first process cannot proceed
21802178
** because it is blocked by the second and the second process cannot
@@ -2184,32 +2182,19 @@
21842182
** will induce the first process to release its read lock and allow
21852183
** the second process to proceed.
21862184
**
21872185
** ^The default busy callback is NULL.
21882186
**
2189
-** ^The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED]
2190
-** when SQLite is in the middle of a large transaction where all the
2191
-** changes will not fit into the in-memory cache. SQLite will
2192
-** already hold a RESERVED lock on the database file, but it needs
2193
-** to promote this lock to EXCLUSIVE so that it can spill cache
2194
-** pages into the database file without harm to concurrent
2195
-** readers. ^If it is unable to promote the lock, then the in-memory
2196
-** cache will be left in an inconsistent state and so the error
2197
-** code is promoted from the relatively benign [SQLITE_BUSY] to
2198
-** the more severe [SQLITE_IOERR_BLOCKED]. ^This error code promotion
2199
-** forces an automatic rollback of the changes. See the
2200
-** <a href="/cvstrac/wiki?p=CorruptionFollowingBusyError">
2201
-** CorruptionFollowingBusyError</a> wiki page for a discussion of why
2202
-** this is important.
2203
-**
22042187
** ^(There can only be a single busy handler defined for each
22052188
** [database connection]. Setting a new busy handler clears any
22062189
** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()]
2207
-** will also set or clear the busy handler.
2190
+** or evaluating [PRAGMA busy_timeout=N] will change the
2191
+** busy handler and thus clear any previously set busy handler.
22082192
**
22092193
** The busy callback should not take any actions which modify the
2210
-** database connection that invoked the busy handler. Any such actions
2194
+** database connection that invoked the busy handler. In other words,
2195
+** the busy handler is not reentrant. Any such actions
22112196
** result in undefined behavior.
22122197
**
22132198
** A busy handler must not close the database connection
22142199
** or [prepared statement] that invoked the busy handler.
22152200
*/
@@ -2221,19 +2206,21 @@
22212206
** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps
22222207
** for a specified amount of time when a table is locked. ^The handler
22232208
** will sleep multiple times until at least "ms" milliseconds of sleeping
22242209
** have accumulated. ^After at least "ms" milliseconds of sleeping,
22252210
** the handler returns 0 which causes [sqlite3_step()] to return
2226
-** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED].
2211
+** [SQLITE_BUSY].
22272212
**
22282213
** ^Calling this routine with an argument less than or equal to zero
22292214
** turns off all busy handlers.
22302215
**
22312216
** ^(There can only be a single busy handler for a particular
22322217
** [database connection] any any given moment. If another busy handler
22332218
** was defined (using [sqlite3_busy_handler()]) prior to calling
22342219
** this routine, that other busy handler is cleared.)^
2220
+**
2221
+** See also: [PRAGMA busy_timeout]
22352222
*/
22362223
SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
22372224
22382225
/*
22392226
** CAPI3REF: Convenience Routines For Running Queries
@@ -2631,12 +2618,12 @@
26312618
** return either [SQLITE_OK] or one of these two constants in order
26322619
** to signal SQLite whether or not the action is permitted. See the
26332620
** [sqlite3_set_authorizer | authorizer documentation] for additional
26342621
** information.
26352622
**
2636
-** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
2637
-** from the [sqlite3_vtab_on_conflict()] interface.
2623
+** Note that SQLITE_IGNORE is also used as a [conflict resolution mode]
2624
+** returned from the [sqlite3_vtab_on_conflict()] interface.
26382625
*/
26392626
#define SQLITE_DENY 1 /* Abort the SQL statement with an error */
26402627
#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
26412628
26422629
/*
@@ -4818,10 +4805,17 @@
48184805
** the name of a folder (a.k.a. directory), then all temporary files
48194806
** created by SQLite when using a built-in [sqlite3_vfs | VFS]
48204807
** will be placed in that directory.)^ ^If this variable
48214808
** is a NULL pointer, then SQLite performs a search for an appropriate
48224809
** temporary file directory.
4810
+**
4811
+** Applications are strongly discouraged from using this global variable.
4812
+** It is required to set a temporary folder on Windows Runtime (WinRT).
4813
+** But for all other platforms, it is highly recommended that applications
4814
+** neither read nor write this variable. This global variable is a relic
4815
+** that exists for backwards compatibility of legacy applications and should
4816
+** be avoided in new projects.
48234817
**
48244818
** It is not safe to read or modify this variable in more than one
48254819
** thread at a time. It is not safe to read or modify this variable
48264820
** if a [database connection] is being used at the same time in a separate
48274821
** thread.
@@ -4837,10 +4831,15 @@
48374831
** [sqlite3_malloc] and the pragma may attempt to free that memory
48384832
** using [sqlite3_free].
48394833
** Hence, if this variable is modified directly, either it should be
48404834
** made NULL or made to point to memory obtained from [sqlite3_malloc]
48414835
** or else the use of the [temp_store_directory pragma] should be avoided.
4836
+** Except when requested by the [temp_store_directory pragma], SQLite
4837
+** does not free the memory that sqlite3_temp_directory points to. If
4838
+** the application wants that memory to be freed, it must do
4839
+** so itself, taking care to only do so after all [database connection]
4840
+** objects have been destroyed.
48424841
**
48434842
** <b>Note to Windows Runtime users:</b> The temporary directory must be set
48444843
** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various
48454844
** features that require the use of temporary files may fail. Here is an
48464845
** example of how to do this using C++ with the Windows Runtime:
@@ -5971,14 +5970,16 @@
59715970
** <ul>
59725971
** <li> SQLITE_MUTEX_FAST
59735972
** <li> SQLITE_MUTEX_RECURSIVE
59745973
** <li> SQLITE_MUTEX_STATIC_MASTER
59755974
** <li> SQLITE_MUTEX_STATIC_MEM
5976
-** <li> SQLITE_MUTEX_STATIC_MEM2
5975
+** <li> SQLITE_MUTEX_STATIC_OPEN
59775976
** <li> SQLITE_MUTEX_STATIC_PRNG
59785977
** <li> SQLITE_MUTEX_STATIC_LRU
5979
-** <li> SQLITE_MUTEX_STATIC_LRU2
5978
+** <li> SQLITE_MUTEX_STATIC_PMEM
5979
+** <li> SQLITE_MUTEX_STATIC_APP1
5980
+** <li> SQLITE_MUTEX_STATIC_APP2
59805981
** </ul>)^
59815982
**
59825983
** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
59835984
** cause sqlite3_mutex_alloc() to create
59845985
** a new mutex. ^The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
@@ -6178,10 +6179,13 @@
61786179
#define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */
61796180
#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */
61806181
#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
61816182
#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */
61826183
#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */
6184
+#define SQLITE_MUTEX_STATIC_APP1 8 /* For use by application */
6185
+#define SQLITE_MUTEX_STATIC_APP2 9 /* For use by application */
6186
+#define SQLITE_MUTEX_STATIC_APP3 10 /* For use by application */
61836187
61846188
/*
61856189
** CAPI3REF: Retrieve the mutex for a database connection
61866190
**
61876191
** ^This interface returns a pointer the [sqlite3_mutex] object that
@@ -6273,11 +6277,12 @@
62736277
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
62746278
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19
62756279
#define SQLITE_TESTCTRL_NEVER_CORRUPT 20
62766280
#define SQLITE_TESTCTRL_VDBE_COVERAGE 21
62776281
#define SQLITE_TESTCTRL_BYTEORDER 22
6278
-#define SQLITE_TESTCTRL_LAST 22
6282
+#define SQLITE_TESTCTRL_ISINIT 23
6283
+#define SQLITE_TESTCTRL_LAST 23
62796284
62806285
/*
62816286
** CAPI3REF: SQLite Runtime Status
62826287
**
62836288
** ^This interface is used to retrieve runtime status information
@@ -7256,10 +7261,13 @@
72567261
** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism
72577262
** configured by this function.
72587263
**
72597264
** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
72607265
** from SQL.
7266
+**
7267
+** ^Checkpoints initiated by this mechanism are
7268
+** [sqlite3_wal_checkpoint_v2|PASSIVE].
72617269
**
72627270
** ^Every new [database connection] defaults to having the auto-checkpoint
72637271
** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
72647272
** pages. The use of this interface
72657273
** is only necessary if the default setting is found to be suboptimal
@@ -7273,10 +7281,14 @@
72737281
** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X
72747282
** on [database connection] D to be [checkpointed]. ^If X is NULL or an
72757283
** empty string, then a checkpoint is run on all databases of
72767284
** connection D. ^If the database connection D is not in
72777285
** [WAL | write-ahead log mode] then this interface is a harmless no-op.
7286
+** ^The [sqlite3_wal_checkpoint(D,X)] interface initiates a
7287
+** [sqlite3_wal_checkpoint_v2|PASSIVE] checkpoint.
7288
+** Use the [sqlite3_wal_checkpoint_v2()] interface to get a FULL
7289
+** or RESET checkpoint.
72787290
**
72797291
** ^The [wal_checkpoint pragma] can be used to invoke this interface
72807292
** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the
72817293
** [wal_autocheckpoint pragma] can be used to cause this interface to be
72827294
** run whenever the WAL reaches a certain size threshold.
@@ -7295,22 +7307,25 @@
72957307
** <dl>
72967308
** <dt>SQLITE_CHECKPOINT_PASSIVE<dd>
72977309
** Checkpoint as many frames as possible without waiting for any database
72987310
** readers or writers to finish. Sync the db file if all frames in the log
72997311
** are checkpointed. This mode is the same as calling
7300
-** sqlite3_wal_checkpoint(). The busy-handler callback is never invoked.
7312
+** sqlite3_wal_checkpoint(). The [sqlite3_busy_handler|busy-handler callback]
7313
+** is never invoked.
73017314
**
73027315
** <dt>SQLITE_CHECKPOINT_FULL<dd>
7303
-** This mode blocks (calls the busy-handler callback) until there is no
7316
+** This mode blocks (it invokes the
7317
+** [sqlite3_busy_handler|busy-handler callback]) until there is no
73047318
** database writer and all readers are reading from the most recent database
73057319
** snapshot. It then checkpoints all frames in the log file and syncs the
73067320
** database file. This call blocks database writers while it is running,
73077321
** but not database readers.
73087322
**
73097323
** <dt>SQLITE_CHECKPOINT_RESTART<dd>
73107324
** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after
7311
-** checkpointing the log file it blocks (calls the busy-handler callback)
7325
+** checkpointing the log file it blocks (calls the
7326
+** [sqlite3_busy_handler|busy-handler callback])
73127327
** until all readers are reading from the database file only. This ensures
73137328
** that the next client to write to the database file restarts the log file
73147329
** from the beginning. This call blocks database writers while it is running,
73157330
** but not database readers.
73167331
** </dl>
@@ -7444,10 +7459,11 @@
74447459
*/
74457460
SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
74467461
74477462
/*
74487463
** CAPI3REF: Conflict resolution modes
7464
+** KEYWORDS: {conflict resolution mode}
74497465
**
74507466
** These constants are returned by [sqlite3_vtab_on_conflict()] to
74517467
** inform a [virtual table] implementation what the [ON CONFLICT] mode
74527468
** is for the SQL statement being evaluated.
74537469
**
@@ -9285,43 +9301,43 @@
92859301
#define OP_Affinity 47 /* synopsis: affinity(r[P1@P2]) */
92869302
#define OP_MakeRecord 48 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
92879303
#define OP_Count 49 /* synopsis: r[P2]=count() */
92889304
#define OP_ReadCookie 50
92899305
#define OP_SetCookie 51
9290
-#define OP_OpenRead 52 /* synopsis: root=P2 iDb=P3 */
9291
-#define OP_OpenWrite 53 /* synopsis: root=P2 iDb=P3 */
9292
-#define OP_OpenAutoindex 54 /* synopsis: nColumn=P2 */
9293
-#define OP_OpenEphemeral 55 /* synopsis: nColumn=P2 */
9294
-#define OP_SorterOpen 56
9295
-#define OP_OpenPseudo 57 /* synopsis: P3 columns in r[P2] */
9296
-#define OP_Close 58
9297
-#define OP_SeekLT 59
9298
-#define OP_SeekLE 60
9299
-#define OP_SeekGE 61
9300
-#define OP_SeekGT 62
9301
-#define OP_Seek 63 /* synopsis: intkey=r[P2] */
9302
-#define OP_NoConflict 64 /* synopsis: key=r[P3@P4] */
9303
-#define OP_NotFound 65 /* synopsis: key=r[P3@P4] */
9304
-#define OP_Found 66 /* synopsis: key=r[P3@P4] */
9305
-#define OP_NotExists 67 /* synopsis: intkey=r[P3] */
9306
-#define OP_Sequence 68 /* synopsis: r[P2]=cursor[P1].ctr++ */
9307
-#define OP_NewRowid 69 /* synopsis: r[P2]=rowid */
9308
-#define OP_Insert 70 /* synopsis: intkey=r[P3] data=r[P2] */
9306
+#define OP_ReopenIdx 52 /* synopsis: root=P2 iDb=P3 */
9307
+#define OP_OpenRead 53 /* synopsis: root=P2 iDb=P3 */
9308
+#define OP_OpenWrite 54 /* synopsis: root=P2 iDb=P3 */
9309
+#define OP_OpenAutoindex 55 /* synopsis: nColumn=P2 */
9310
+#define OP_OpenEphemeral 56 /* synopsis: nColumn=P2 */
9311
+#define OP_SorterOpen 57
9312
+#define OP_OpenPseudo 58 /* synopsis: P3 columns in r[P2] */
9313
+#define OP_Close 59
9314
+#define OP_SeekLT 60 /* synopsis: key=r[P3@P4] */
9315
+#define OP_SeekLE 61 /* synopsis: key=r[P3@P4] */
9316
+#define OP_SeekGE 62 /* synopsis: key=r[P3@P4] */
9317
+#define OP_SeekGT 63 /* synopsis: key=r[P3@P4] */
9318
+#define OP_Seek 64 /* synopsis: intkey=r[P2] */
9319
+#define OP_NoConflict 65 /* synopsis: key=r[P3@P4] */
9320
+#define OP_NotFound 66 /* synopsis: key=r[P3@P4] */
9321
+#define OP_Found 67 /* synopsis: key=r[P3@P4] */
9322
+#define OP_NotExists 68 /* synopsis: intkey=r[P3] */
9323
+#define OP_Sequence 69 /* synopsis: r[P2]=cursor[P1].ctr++ */
9324
+#define OP_NewRowid 70 /* synopsis: r[P2]=rowid */
93099325
#define OP_Or 71 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
93109326
#define OP_And 72 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
9311
-#define OP_InsertInt 73 /* synopsis: intkey=P3 data=r[P2] */
9312
-#define OP_Delete 74
9313
-#define OP_ResetCount 75
9327
+#define OP_Insert 73 /* synopsis: intkey=r[P3] data=r[P2] */
9328
+#define OP_InsertInt 74 /* synopsis: intkey=P3 data=r[P2] */
9329
+#define OP_Delete 75
93149330
#define OP_IsNull 76 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
93159331
#define OP_NotNull 77 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
93169332
#define OP_Ne 78 /* same as TK_NE, synopsis: if r[P1]!=r[P3] goto P2 */
93179333
#define OP_Eq 79 /* same as TK_EQ, synopsis: if r[P1]==r[P3] goto P2 */
93189334
#define OP_Gt 80 /* same as TK_GT, synopsis: if r[P1]>r[P3] goto P2 */
93199335
#define OP_Le 81 /* same as TK_LE, synopsis: if r[P1]<=r[P3] goto P2 */
93209336
#define OP_Lt 82 /* same as TK_LT, synopsis: if r[P1]<r[P3] goto P2 */
93219337
#define OP_Ge 83 /* same as TK_GE, synopsis: if r[P1]>=r[P3] goto P2 */
9322
-#define OP_SorterCompare 84 /* synopsis: if key(P1)!=rtrim(r[P3],P4) goto P2 */
9338
+#define OP_ResetCount 84
93239339
#define OP_BitAnd 85 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
93249340
#define OP_BitOr 86 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
93259341
#define OP_ShiftLeft 87 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
93269342
#define OP_ShiftRight 88 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
93279343
#define OP_Add 89 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
@@ -9328,73 +9344,74 @@
93289344
#define OP_Subtract 90 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
93299345
#define OP_Multiply 91 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
93309346
#define OP_Divide 92 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
93319347
#define OP_Remainder 93 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
93329348
#define OP_Concat 94 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
9333
-#define OP_SorterData 95 /* synopsis: r[P2]=data */
9349
+#define OP_SorterCompare 95 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
93349350
#define OP_BitNot 96 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */
93359351
#define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */
9336
-#define OP_RowKey 98 /* synopsis: r[P2]=key */
9337
-#define OP_RowData 99 /* synopsis: r[P2]=data */
9338
-#define OP_Rowid 100 /* synopsis: r[P2]=rowid */
9339
-#define OP_NullRow 101
9340
-#define OP_Last 102
9341
-#define OP_SorterSort 103
9342
-#define OP_Sort 104
9343
-#define OP_Rewind 105
9344
-#define OP_SorterInsert 106
9345
-#define OP_IdxInsert 107 /* synopsis: key=r[P2] */
9346
-#define OP_IdxDelete 108 /* synopsis: key=r[P2@P3] */
9347
-#define OP_IdxRowid 109 /* synopsis: r[P2]=rowid */
9348
-#define OP_IdxLE 110 /* synopsis: key=r[P3@P4] */
9349
-#define OP_IdxGT 111 /* synopsis: key=r[P3@P4] */
9350
-#define OP_IdxLT 112 /* synopsis: key=r[P3@P4] */
9351
-#define OP_IdxGE 113 /* synopsis: key=r[P3@P4] */
9352
-#define OP_Destroy 114
9353
-#define OP_Clear 115
9354
-#define OP_ResetSorter 116
9355
-#define OP_CreateIndex 117 /* synopsis: r[P2]=root iDb=P1 */
9356
-#define OP_CreateTable 118 /* synopsis: r[P2]=root iDb=P1 */
9357
-#define OP_ParseSchema 119
9358
-#define OP_LoadAnalysis 120
9359
-#define OP_DropTable 121
9360
-#define OP_DropIndex 122
9361
-#define OP_DropTrigger 123
9362
-#define OP_IntegrityCk 124
9363
-#define OP_RowSetAdd 125 /* synopsis: rowset(P1)=r[P2] */
9364
-#define OP_RowSetRead 126 /* synopsis: r[P3]=rowset(P1) */
9365
-#define OP_RowSetTest 127 /* synopsis: if r[P3] in rowset(P1) goto P2 */
9366
-#define OP_Program 128
9367
-#define OP_Param 129
9368
-#define OP_FkCounter 130 /* synopsis: fkctr[P1]+=P2 */
9369
-#define OP_FkIfZero 131 /* synopsis: if fkctr[P1]==0 goto P2 */
9370
-#define OP_MemMax 132 /* synopsis: r[P1]=max(r[P1],r[P2]) */
9352
+#define OP_SorterData 98 /* synopsis: r[P2]=data */
9353
+#define OP_RowKey 99 /* synopsis: r[P2]=key */
9354
+#define OP_RowData 100 /* synopsis: r[P2]=data */
9355
+#define OP_Rowid 101 /* synopsis: r[P2]=rowid */
9356
+#define OP_NullRow 102
9357
+#define OP_Last 103
9358
+#define OP_SorterSort 104
9359
+#define OP_Sort 105
9360
+#define OP_Rewind 106
9361
+#define OP_SorterInsert 107
9362
+#define OP_IdxInsert 108 /* synopsis: key=r[P2] */
9363
+#define OP_IdxDelete 109 /* synopsis: key=r[P2@P3] */
9364
+#define OP_IdxRowid 110 /* synopsis: r[P2]=rowid */
9365
+#define OP_IdxLE 111 /* synopsis: key=r[P3@P4] */
9366
+#define OP_IdxGT 112 /* synopsis: key=r[P3@P4] */
9367
+#define OP_IdxLT 113 /* synopsis: key=r[P3@P4] */
9368
+#define OP_IdxGE 114 /* synopsis: key=r[P3@P4] */
9369
+#define OP_Destroy 115
9370
+#define OP_Clear 116
9371
+#define OP_ResetSorter 117
9372
+#define OP_CreateIndex 118 /* synopsis: r[P2]=root iDb=P1 */
9373
+#define OP_CreateTable 119 /* synopsis: r[P2]=root iDb=P1 */
9374
+#define OP_ParseSchema 120
9375
+#define OP_LoadAnalysis 121
9376
+#define OP_DropTable 122
9377
+#define OP_DropIndex 123
9378
+#define OP_DropTrigger 124
9379
+#define OP_IntegrityCk 125
9380
+#define OP_RowSetAdd 126 /* synopsis: rowset(P1)=r[P2] */
9381
+#define OP_RowSetRead 127 /* synopsis: r[P3]=rowset(P1) */
9382
+#define OP_RowSetTest 128 /* synopsis: if r[P3] in rowset(P1) goto P2 */
9383
+#define OP_Program 129
9384
+#define OP_Param 130
9385
+#define OP_FkCounter 131 /* synopsis: fkctr[P1]+=P2 */
9386
+#define OP_FkIfZero 132 /* synopsis: if fkctr[P1]==0 goto P2 */
93719387
#define OP_Real 133 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
9372
-#define OP_IfPos 134 /* synopsis: if r[P1]>0 goto P2 */
9373
-#define OP_IfNeg 135 /* synopsis: if r[P1]<0 goto P2 */
9374
-#define OP_IfZero 136 /* synopsis: r[P1]+=P3, if r[P1]==0 goto P2 */
9375
-#define OP_AggFinal 137 /* synopsis: accum=r[P1] N=P2 */
9376
-#define OP_IncrVacuum 138
9377
-#define OP_Expire 139
9378
-#define OP_TableLock 140 /* synopsis: iDb=P1 root=P2 write=P3 */
9379
-#define OP_VBegin 141
9380
-#define OP_VCreate 142
9388
+#define OP_MemMax 134 /* synopsis: r[P1]=max(r[P1],r[P2]) */
9389
+#define OP_IfPos 135 /* synopsis: if r[P1]>0 goto P2 */
9390
+#define OP_IfNeg 136 /* synopsis: r[P1]+=P3, if r[P1]<0 goto P2 */
9391
+#define OP_IfZero 137 /* synopsis: r[P1]+=P3, if r[P1]==0 goto P2 */
9392
+#define OP_AggFinal 138 /* synopsis: accum=r[P1] N=P2 */
9393
+#define OP_IncrVacuum 139
9394
+#define OP_Expire 140
9395
+#define OP_TableLock 141 /* synopsis: iDb=P1 root=P2 write=P3 */
9396
+#define OP_VBegin 142
93819397
#define OP_ToText 143 /* same as TK_TO_TEXT */
93829398
#define OP_ToBlob 144 /* same as TK_TO_BLOB */
93839399
#define OP_ToNumeric 145 /* same as TK_TO_NUMERIC */
93849400
#define OP_ToInt 146 /* same as TK_TO_INT */
93859401
#define OP_ToReal 147 /* same as TK_TO_REAL */
9386
-#define OP_VDestroy 148
9387
-#define OP_VOpen 149
9388
-#define OP_VColumn 150 /* synopsis: r[P3]=vcolumn(P2) */
9389
-#define OP_VNext 151
9390
-#define OP_VRename 152
9391
-#define OP_Pagecount 153
9392
-#define OP_MaxPgcnt 154
9393
-#define OP_Init 155 /* synopsis: Start at P2 */
9394
-#define OP_Noop 156
9395
-#define OP_Explain 157
9402
+#define OP_VCreate 148
9403
+#define OP_VDestroy 149
9404
+#define OP_VOpen 150
9405
+#define OP_VColumn 151 /* synopsis: r[P3]=vcolumn(P2) */
9406
+#define OP_VNext 152
9407
+#define OP_VRename 153
9408
+#define OP_Pagecount 154
9409
+#define OP_MaxPgcnt 155
9410
+#define OP_Init 156 /* synopsis: Start at P2 */
9411
+#define OP_Noop 157
9412
+#define OP_Explain 158
93969413
93979414
93989415
/* Properties such as "out2" or "jump" that are specified in
93999416
** comments following the "case" for each opcode in the vdbe.c
94009417
** are encoded into bitvectors as follows:
@@ -9412,23 +9429,23 @@
94129429
/* 16 */ 0x01, 0x01, 0x04, 0x24, 0x01, 0x04, 0x05, 0x10,\
94139430
/* 24 */ 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,\
94149431
/* 32 */ 0x00, 0x00, 0x20, 0x00, 0x00, 0x04, 0x05, 0x04,\
94159432
/* 40 */ 0x00, 0x00, 0x01, 0x01, 0x05, 0x05, 0x00, 0x00,\
94169433
/* 48 */ 0x00, 0x02, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00,\
9417
-/* 56 */ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x08,\
9418
-/* 64 */ 0x11, 0x11, 0x11, 0x11, 0x02, 0x02, 0x00, 0x4c,\
9434
+/* 56 */ 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11,\
9435
+/* 64 */ 0x08, 0x11, 0x11, 0x11, 0x11, 0x02, 0x02, 0x4c,\
94199436
/* 72 */ 0x4c, 0x00, 0x00, 0x00, 0x05, 0x05, 0x15, 0x15,\
94209437
/* 80 */ 0x15, 0x15, 0x15, 0x15, 0x00, 0x4c, 0x4c, 0x4c,\
94219438
/* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00,\
9422
-/* 96 */ 0x24, 0x02, 0x00, 0x00, 0x02, 0x00, 0x01, 0x01,\
9423
-/* 104 */ 0x01, 0x01, 0x08, 0x08, 0x00, 0x02, 0x01, 0x01,\
9424
-/* 112 */ 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00,\
9425
-/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x45, 0x15,\
9426
-/* 128 */ 0x01, 0x02, 0x00, 0x01, 0x08, 0x02, 0x05, 0x05,\
9427
-/* 136 */ 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04,\
9428
-/* 144 */ 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x01,\
9429
-/* 152 */ 0x00, 0x02, 0x02, 0x01, 0x00, 0x00,}
9439
+/* 96 */ 0x24, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01,\
9440
+/* 104 */ 0x01, 0x01, 0x01, 0x08, 0x08, 0x00, 0x02, 0x01,\
9441
+/* 112 */ 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02,\
9442
+/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x45,\
9443
+/* 128 */ 0x15, 0x01, 0x02, 0x00, 0x01, 0x02, 0x08, 0x05,\
9444
+/* 136 */ 0x05, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04,\
9445
+/* 144 */ 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,\
9446
+/* 152 */ 0x01, 0x00, 0x02, 0x02, 0x01, 0x00, 0x00,}
94309447
94319448
/************** End of opcodes.h *********************************************/
94329449
/************** Continuing where we left off in vdbe.h ***********************/
94339450
94349451
/*
@@ -10331,22 +10348,22 @@
1033110348
Hash trigHash; /* All triggers indexed by name */
1033210349
Hash fkeyHash; /* All foreign keys by referenced table name */
1033310350
Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */
1033410351
u8 file_format; /* Schema format version for this file */
1033510352
u8 enc; /* Text encoding used by this database */
10336
- u16 flags; /* Flags associated with this schema */
10353
+ u16 schemaFlags; /* Flags associated with this schema */
1033710354
int cache_size; /* Number of pages to use in the cache */
1033810355
};
1033910356
1034010357
/*
1034110358
** These macros can be used to test, set, or clear bits in the
1034210359
** Db.pSchema->flags field.
1034310360
*/
10344
-#define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))==(P))
10345
-#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))!=0)
10346
-#define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->flags|=(P)
10347
-#define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->flags&=~(P)
10361
+#define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->schemaFlags&(P))==(P))
10362
+#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->schemaFlags&(P))!=0)
10363
+#define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->schemaFlags|=(P)
10364
+#define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->schemaFlags&=~(P)
1034810365
1034910366
/*
1035010367
** Allowed values for the DB.pSchema->flags field.
1035110368
**
1035210369
** The DB_SchemaLoaded flag is set after the database schema has been
@@ -10932,10 +10949,13 @@
1093210949
int tnum; /* Root BTree node for this table (see note above) */
1093310950
i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */
1093410951
i16 nCol; /* Number of columns in this table */
1093510952
u16 nRef; /* Number of pointers to this Table */
1093610953
LogEst szTabRow; /* Estimated size of each table row in bytes */
10954
+#ifdef SQLITE_ENABLE_COSTMULT
10955
+ LogEst costMult; /* Cost multiplier for using this table */
10956
+#endif
1093710957
u8 tabFlags; /* Mask of TF_* values */
1093810958
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
1093910959
#ifndef SQLITE_OMIT_ALTERTABLE
1094010960
int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
1094110961
#endif
@@ -11172,10 +11192,13 @@
1117211192
#define SQLITE_IDXTYPE_PRIMARYKEY 2 /* Is the PRIMARY KEY for the table */
1117311193
1117411194
/* Return true if index X is a PRIMARY KEY index */
1117511195
#define IsPrimaryKeyIndex(X) ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY)
1117611196
11197
+/* Return true if index X is a UNIQUE index */
11198
+#define IsUniqueIndex(X) ((X)->onError!=OE_None)
11199
+
1117711200
/*
1117811201
** Each sample stored in the sqlite_stat3 table is represented in memory
1117911202
** using a structure of this type. See documentation at the top of the
1118011203
** analyze.c source file for additional information.
1118111204
*/
@@ -11591,10 +11614,11 @@
1159111614
#define WHERE_AND_ONLY 0x0080 /* Don't use indices for OR terms */
1159211615
#define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */
1159311616
#define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
1159411617
#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
1159511618
#define WHERE_SORTBYGROUP 0x0800 /* Support sqlite3WhereIsSorted() */
11619
+#define WHERE_REOPEN_IDX 0x1000 /* Try to use OP_ReopenIdx */
1159611620
1159711621
/* Allowed return values from sqlite3WhereIsDistinct()
1159811622
*/
1159911623
#define WHERE_DISTINCT_NOOP 0 /* DISTINCT keyword not used */
1160011624
#define WHERE_DISTINCT_UNIQUE 1 /* No duplicates */
@@ -11847,13 +11871,23 @@
1184711871
1184811872
/*
1184911873
** The yDbMask datatype for the bitmask of all attached databases.
1185011874
*/
1185111875
#if SQLITE_MAX_ATTACHED>30
11852
- typedef sqlite3_uint64 yDbMask;
11876
+ typedef unsigned char yDbMask[(SQLITE_MAX_ATTACHED+9)/8];
11877
+# define DbMaskTest(M,I) (((M)[(I)/8]&(1<<((I)&7)))!=0)
11878
+# define DbMaskZero(M) memset((M),0,sizeof(M))
11879
+# define DbMaskSet(M,I) (M)[(I)/8]|=(1<<((I)&7))
11880
+# define DbMaskAllZero(M) sqlite3DbMaskAllZero(M)
11881
+# define DbMaskNonZero(M) (sqlite3DbMaskAllZero(M)==0)
1185311882
#else
1185411883
typedef unsigned int yDbMask;
11884
+# define DbMaskTest(M,I) (((M)&(((yDbMask)1)<<(I)))!=0)
11885
+# define DbMaskZero(M) (M)=0
11886
+# define DbMaskSet(M,I) (M)|=(((yDbMask)1)<<(I))
11887
+# define DbMaskAllZero(M) (M)==0
11888
+# define DbMaskNonZero(M) (M)!=0
1185511889
#endif
1185611890
1185711891
/*
1185811892
** An SQL parser context. A copy of this structure is passed through
1185911893
** the parser and down into all the parser action routine in order to
@@ -12522,10 +12556,13 @@
1252212556
SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse*,Table*);
1252312557
#else
1252412558
# define sqlite3ViewGetColumnNames(A,B) 0
1252512559
#endif
1252612560
12561
+#if SQLITE_MAX_ATTACHED>30
12562
+SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask);
12563
+#endif
1252712564
SQLITE_PRIVATE void sqlite3DropTable(Parse*, SrcList*, int, int);
1252812565
SQLITE_PRIVATE void sqlite3CodeDropTable(Parse*, Table*, int, int);
1252912566
SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3*, Table*);
1253012567
#ifndef SQLITE_OMIT_AUTOINCREMENT
1253112568
SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse);
@@ -12772,10 +12809,11 @@
1277212809
SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe*, Table*, int);
1277312810
SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2);
1277412811
SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
1277512812
SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr);
1277612813
SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8);
12814
+SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char*, i64*);
1277712815
SQLITE_PRIVATE void sqlite3Error(sqlite3*, int, const char*,...);
1277812816
SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
1277912817
SQLITE_PRIVATE u8 sqlite3HexToInt(int h);
1278012818
SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
1278112819
@@ -12801,11 +12839,11 @@
1280112839
#ifdef SQLITE_ENABLE_8_3_NAMES
1280212840
SQLITE_PRIVATE void sqlite3FileSuffix3(const char*, char*);
1280312841
#else
1280412842
# define sqlite3FileSuffix3(X,Y)
1280512843
#endif
12806
-SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z,int);
12844
+SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z,u8);
1280712845
1280812846
SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8);
1280912847
SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8);
1281012848
SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
1281112849
void(*)(void*));
@@ -13025,15 +13063,25 @@
1302513063
#else
1302613064
#define sqlite3BeginBenignMalloc()
1302713065
#define sqlite3EndBenignMalloc()
1302813066
#endif
1302913067
13030
-#define IN_INDEX_ROWID 1
13031
-#define IN_INDEX_EPH 2
13032
-#define IN_INDEX_INDEX_ASC 3
13033
-#define IN_INDEX_INDEX_DESC 4
13034
-SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, int*);
13068
+/*
13069
+** Allowed return values from sqlite3FindInIndex()
13070
+*/
13071
+#define IN_INDEX_ROWID 1 /* Search the rowid of the table */
13072
+#define IN_INDEX_EPH 2 /* Search an ephemeral b-tree */
13073
+#define IN_INDEX_INDEX_ASC 3 /* Existing index ASCENDING */
13074
+#define IN_INDEX_INDEX_DESC 4 /* Existing index DESCENDING */
13075
+#define IN_INDEX_NOOP 5 /* No table available. Use comparisons */
13076
+/*
13077
+** Allowed flags for the 3rd parameter to sqlite3FindInIndex().
13078
+*/
13079
+#define IN_INDEX_NOOP_OK 0x0001 /* OK to return IN_INDEX_NOOP */
13080
+#define IN_INDEX_MEMBERSHIP 0x0002 /* IN operator used for membership test */
13081
+#define IN_INDEX_LOOP 0x0004 /* IN operator used as a loop */
13082
+SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, u32, int*);
1303513083
1303613084
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
1303713085
SQLITE_PRIVATE int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
1303813086
SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *);
1303913087
SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *);
@@ -13876,18 +13924,22 @@
1387613924
KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
1387713925
int seekResult; /* Result of previous sqlite3BtreeMoveto() */
1387813926
int pseudoTableReg; /* Register holding pseudotable content. */
1387913927
i16 nField; /* Number of fields in the header */
1388013928
u16 nHdrParsed; /* Number of header fields parsed so far */
13929
+#ifdef SQLITE_DEBUG
13930
+ u8 seekOp; /* Most recent seek operation on this cursor */
13931
+#endif
1388113932
i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */
1388213933
u8 nullRow; /* True if pointing to a row with no data */
1388313934
u8 rowidIsValid; /* True if lastRowid is valid */
1388413935
u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
1388513936
Bool isEphemeral:1; /* True for an ephemeral table */
1388613937
Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */
1388713938
Bool isTable:1; /* True if a table requiring integer keys */
1388813939
Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */
13940
+ Pgno pgnoRoot; /* Root page of the open btree cursor */
1388913941
sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
1389013942
i64 seqCount; /* Sequence counter */
1389113943
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
1389213944
i64 lastRowid; /* Rowid being deleted by OP_Delete */
1389313945
VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */
@@ -18396,11 +18448,11 @@
1839618448
/*
1839718449
** Retrieve a pointer to a static mutex or allocate a new dynamic one.
1839818450
*/
1839918451
SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int id){
1840018452
#ifndef SQLITE_OMIT_AUTOINIT
18401
- if( sqlite3_initialize() ) return 0;
18453
+ if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0;
1840218454
#endif
1840318455
return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
1840418456
}
1840518457
1840618458
SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int id){
@@ -18577,11 +18629,11 @@
1857718629
** The sqlite3_mutex_alloc() routine allocates a new
1857818630
** mutex and returns a pointer to it. If it returns NULL
1857918631
** that means that a mutex could not be allocated.
1858018632
*/
1858118633
static sqlite3_mutex *debugMutexAlloc(int id){
18582
- static sqlite3_debug_mutex aStatic[6];
18634
+ static sqlite3_debug_mutex aStatic[SQLITE_MUTEX_STATIC_APP3 - 1];
1858318635
sqlite3_debug_mutex *pNew = 0;
1858418636
switch( id ){
1858518637
case SQLITE_MUTEX_FAST:
1858618638
case SQLITE_MUTEX_RECURSIVE: {
1858718639
pNew = sqlite3Malloc(sizeof(*pNew));
@@ -18774,14 +18826,17 @@
1877418826
** <ul>
1877518827
** <li> SQLITE_MUTEX_FAST
1877618828
** <li> SQLITE_MUTEX_RECURSIVE
1877718829
** <li> SQLITE_MUTEX_STATIC_MASTER
1877818830
** <li> SQLITE_MUTEX_STATIC_MEM
18779
-** <li> SQLITE_MUTEX_STATIC_MEM2
18831
+** <li> SQLITE_MUTEX_STATIC_OPEN
1878018832
** <li> SQLITE_MUTEX_STATIC_PRNG
1878118833
** <li> SQLITE_MUTEX_STATIC_LRU
1878218834
** <li> SQLITE_MUTEX_STATIC_PMEM
18835
+** <li> SQLITE_MUTEX_STATIC_APP1
18836
+** <li> SQLITE_MUTEX_STATIC_APP2
18837
+** <li> SQLITE_MUTEX_STATIC_APP3
1878318838
** </ul>
1878418839
**
1878518840
** The first two constants cause sqlite3_mutex_alloc() to create
1878618841
** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
1878718842
** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
@@ -18806,10 +18861,13 @@
1880618861
** mutex types, the same mutex is returned on every call that has
1880718862
** the same type number.
1880818863
*/
1880918864
static sqlite3_mutex *pthreadMutexAlloc(int iType){
1881018865
static sqlite3_mutex staticMutexes[] = {
18866
+ SQLITE3_MUTEX_INITIALIZER,
18867
+ SQLITE3_MUTEX_INITIALIZER,
18868
+ SQLITE3_MUTEX_INITIALIZER,
1881118869
SQLITE3_MUTEX_INITIALIZER,
1881218870
SQLITE3_MUTEX_INITIALIZER,
1881318871
SQLITE3_MUTEX_INITIALIZER,
1881418872
SQLITE3_MUTEX_INITIALIZER,
1881518873
SQLITE3_MUTEX_INITIALIZER,
@@ -19041,14 +19099,227 @@
1904119099
** May you do good and not evil.
1904219100
** May you find forgiveness for yourself and forgive others.
1904319101
** May you share freely, never taking more than you give.
1904419102
**
1904519103
*************************************************************************
19046
-** This file contains the C functions that implement mutexes for win32
19104
+** This file contains the C functions that implement mutexes for Win32.
1904719105
*/
1904819106
1904919107
#if SQLITE_OS_WIN
19108
+/*
19109
+** Include code that is common to all os_*.c files
19110
+*/
19111
+/************** Include os_common.h in the middle of mutex_w32.c *************/
19112
+/************** Begin file os_common.h ***************************************/
19113
+/*
19114
+** 2004 May 22
19115
+**
19116
+** The author disclaims copyright to this source code. In place of
19117
+** a legal notice, here is a blessing:
19118
+**
19119
+** May you do good and not evil.
19120
+** May you find forgiveness for yourself and forgive others.
19121
+** May you share freely, never taking more than you give.
19122
+**
19123
+******************************************************************************
19124
+**
19125
+** This file contains macros and a little bit of code that is common to
19126
+** all of the platform-specific files (os_*.c) and is #included into those
19127
+** files.
19128
+**
19129
+** This file should be #included by the os_*.c files only. It is not a
19130
+** general purpose header file.
19131
+*/
19132
+#ifndef _OS_COMMON_H_
19133
+#define _OS_COMMON_H_
19134
+
19135
+/*
19136
+** At least two bugs have slipped in because we changed the MEMORY_DEBUG
19137
+** macro to SQLITE_DEBUG and some older makefiles have not yet made the
19138
+** switch. The following code should catch this problem at compile-time.
19139
+*/
19140
+#ifdef MEMORY_DEBUG
19141
+# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
19142
+#endif
19143
+
19144
+#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
19145
+# ifndef SQLITE_DEBUG_OS_TRACE
19146
+# define SQLITE_DEBUG_OS_TRACE 0
19147
+# endif
19148
+ int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
19149
+# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
19150
+#else
19151
+# define OSTRACE(X)
19152
+#endif
19153
+
19154
+/*
19155
+** Macros for performance tracing. Normally turned off. Only works
19156
+** on i486 hardware.
19157
+*/
19158
+#ifdef SQLITE_PERFORMANCE_TRACE
19159
+
19160
+/*
19161
+** hwtime.h contains inline assembler code for implementing
19162
+** high-performance timing routines.
19163
+*/
19164
+/************** Include hwtime.h in the middle of os_common.h ****************/
19165
+/************** Begin file hwtime.h ******************************************/
19166
+/*
19167
+** 2008 May 27
19168
+**
19169
+** The author disclaims copyright to this source code. In place of
19170
+** a legal notice, here is a blessing:
19171
+**
19172
+** May you do good and not evil.
19173
+** May you find forgiveness for yourself and forgive others.
19174
+** May you share freely, never taking more than you give.
19175
+**
19176
+******************************************************************************
19177
+**
19178
+** This file contains inline asm code for retrieving "high-performance"
19179
+** counters for x86 class CPUs.
19180
+*/
19181
+#ifndef _HWTIME_H_
19182
+#define _HWTIME_H_
19183
+
19184
+/*
19185
+** The following routine only works on pentium-class (or newer) processors.
19186
+** It uses the RDTSC opcode to read the cycle count value out of the
19187
+** processor and returns that value. This can be used for high-res
19188
+** profiling.
19189
+*/
19190
+#if (defined(__GNUC__) || defined(_MSC_VER)) && \
19191
+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
19192
+
19193
+ #if defined(__GNUC__)
19194
+
19195
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
19196
+ unsigned int lo, hi;
19197
+ __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
19198
+ return (sqlite_uint64)hi << 32 | lo;
19199
+ }
19200
+
19201
+ #elif defined(_MSC_VER)
19202
+
19203
+ __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
19204
+ __asm {
19205
+ rdtsc
19206
+ ret ; return value at EDX:EAX
19207
+ }
19208
+ }
19209
+
19210
+ #endif
19211
+
19212
+#elif (defined(__GNUC__) && defined(__x86_64__))
19213
+
19214
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
19215
+ unsigned long val;
19216
+ __asm__ __volatile__ ("rdtsc" : "=A" (val));
19217
+ return val;
19218
+ }
19219
+
19220
+#elif (defined(__GNUC__) && defined(__ppc__))
19221
+
19222
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
19223
+ unsigned long long retval;
19224
+ unsigned long junk;
19225
+ __asm__ __volatile__ ("\n\
19226
+ 1: mftbu %1\n\
19227
+ mftb %L0\n\
19228
+ mftbu %0\n\
19229
+ cmpw %0,%1\n\
19230
+ bne 1b"
19231
+ : "=r" (retval), "=r" (junk));
19232
+ return retval;
19233
+ }
19234
+
19235
+#else
19236
+
19237
+ #error Need implementation of sqlite3Hwtime() for your platform.
19238
+
19239
+ /*
19240
+ ** To compile without implementing sqlite3Hwtime() for your platform,
19241
+ ** you can remove the above #error and use the following
19242
+ ** stub function. You will lose timing support for many
19243
+ ** of the debugging and testing utilities, but it should at
19244
+ ** least compile and run.
19245
+ */
19246
+SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
19247
+
19248
+#endif
19249
+
19250
+#endif /* !defined(_HWTIME_H_) */
19251
+
19252
+/************** End of hwtime.h **********************************************/
19253
+/************** Continuing where we left off in os_common.h ******************/
19254
+
19255
+static sqlite_uint64 g_start;
19256
+static sqlite_uint64 g_elapsed;
19257
+#define TIMER_START g_start=sqlite3Hwtime()
19258
+#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
19259
+#define TIMER_ELAPSED g_elapsed
19260
+#else
19261
+#define TIMER_START
19262
+#define TIMER_END
19263
+#define TIMER_ELAPSED ((sqlite_uint64)0)
19264
+#endif
19265
+
19266
+/*
19267
+** If we compile with the SQLITE_TEST macro set, then the following block
19268
+** of code will give us the ability to simulate a disk I/O error. This
19269
+** is used for testing the I/O recovery logic.
19270
+*/
19271
+#ifdef SQLITE_TEST
19272
+SQLITE_API int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */
19273
+SQLITE_API int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */
19274
+SQLITE_API int sqlite3_io_error_pending = 0; /* Count down to first I/O error */
19275
+SQLITE_API int sqlite3_io_error_persist = 0; /* True if I/O errors persist */
19276
+SQLITE_API int sqlite3_io_error_benign = 0; /* True if errors are benign */
19277
+SQLITE_API int sqlite3_diskfull_pending = 0;
19278
+SQLITE_API int sqlite3_diskfull = 0;
19279
+#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
19280
+#define SimulateIOError(CODE) \
19281
+ if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
19282
+ || sqlite3_io_error_pending-- == 1 ) \
19283
+ { local_ioerr(); CODE; }
19284
+static void local_ioerr(){
19285
+ IOTRACE(("IOERR\n"));
19286
+ sqlite3_io_error_hit++;
19287
+ if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
19288
+}
19289
+#define SimulateDiskfullError(CODE) \
19290
+ if( sqlite3_diskfull_pending ){ \
19291
+ if( sqlite3_diskfull_pending == 1 ){ \
19292
+ local_ioerr(); \
19293
+ sqlite3_diskfull = 1; \
19294
+ sqlite3_io_error_hit = 1; \
19295
+ CODE; \
19296
+ }else{ \
19297
+ sqlite3_diskfull_pending--; \
19298
+ } \
19299
+ }
19300
+#else
19301
+#define SimulateIOErrorBenign(X)
19302
+#define SimulateIOError(A)
19303
+#define SimulateDiskfullError(A)
19304
+#endif
19305
+
19306
+/*
19307
+** When testing, keep a count of the number of open files.
19308
+*/
19309
+#ifdef SQLITE_TEST
19310
+SQLITE_API int sqlite3_open_file_count = 0;
19311
+#define OpenCounter(X) sqlite3_open_file_count+=(X)
19312
+#else
19313
+#define OpenCounter(X)
19314
+#endif
19315
+
19316
+#endif /* !defined(_OS_COMMON_H_) */
19317
+
19318
+/************** End of os_common.h *******************************************/
19319
+/************** Continuing where we left off in mutex_w32.c ******************/
19320
+
1905019321
/*
1905119322
** Include the header file for the Windows VFS.
1905219323
*/
1905319324
/************** Include os_win.h in the middle of mutex_w32.c ****************/
1905419325
/************** Begin file os_win.h ******************************************/
@@ -19124,11 +19395,11 @@
1912419395
/************** Continuing where we left off in mutex_w32.c ******************/
1912519396
#endif
1912619397
1912719398
/*
1912819399
** The code in this file is only used if we are compiling multithreaded
19129
-** on a win32 system.
19400
+** on a Win32 system.
1913019401
*/
1913119402
#ifdef SQLITE_MUTEX_W32
1913219403
1913319404
/*
1913419405
** Each recursive mutex is an instance of the following structure.
@@ -19137,94 +19408,75 @@
1913719408
CRITICAL_SECTION mutex; /* Mutex controlling the lock */
1913819409
int id; /* Mutex type */
1913919410
#ifdef SQLITE_DEBUG
1914019411
volatile int nRef; /* Number of enterances */
1914119412
volatile DWORD owner; /* Thread holding this mutex */
19142
- int trace; /* True to trace changes */
19413
+ volatile int trace; /* True to trace changes */
1914319414
#endif
1914419415
};
19416
+
19417
+/*
19418
+** These are the initializer values used when declaring a "static" mutex
19419
+** on Win32. It should be noted that all mutexes require initialization
19420
+** on the Win32 platform.
19421
+*/
1914519422
#define SQLITE_W32_MUTEX_INITIALIZER { 0 }
19423
+
1914619424
#ifdef SQLITE_DEBUG
19147
-#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0, 0 }
19425
+#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, \
19426
+ 0L, (DWORD)0, 0 }
1914819427
#else
1914919428
#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 }
1915019429
#endif
1915119430
19152
-/*
19153
-** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
19154
-** or WinCE. Return false (zero) for Win95, Win98, or WinME.
19155
-**
19156
-** Here is an interesting observation: Win95, Win98, and WinME lack
19157
-** the LockFileEx() API. But we can still statically link against that
19158
-** API as long as we don't call it win running Win95/98/ME. A call to
19159
-** this routine is used to determine if the host is Win95/98/ME or
19160
-** WinNT/2K/XP so that we will know whether or not we can safely call
19161
-** the LockFileEx() API.
19162
-**
19163
-** mutexIsNT() is only used for the TryEnterCriticalSection() API call,
19164
-** which is only available if your application was compiled with
19165
-** _WIN32_WINNT defined to a value >= 0x0400. Currently, the only
19166
-** call to TryEnterCriticalSection() is #ifdef'ed out, so #ifdef
19167
-** this out as well.
19168
-*/
19169
-#if 0
19170
-#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
19171
-# define mutexIsNT() (1)
19172
-#else
19173
- static int mutexIsNT(void){
19174
- static int osType = 0;
19175
- if( osType==0 ){
19176
- OSVERSIONINFO sInfo;
19177
- sInfo.dwOSVersionInfoSize = sizeof(sInfo);
19178
- GetVersionEx(&sInfo);
19179
- osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
19180
- }
19181
- return osType==2;
19182
- }
19183
-#endif /* SQLITE_OS_WINCE || SQLITE_OS_WINRT */
19184
-#endif
19185
-
1918619431
#ifdef SQLITE_DEBUG
1918719432
/*
1918819433
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
1918919434
** intended for use only inside assert() statements.
1919019435
*/
1919119436
static int winMutexHeld(sqlite3_mutex *p){
1919219437
return p->nRef!=0 && p->owner==GetCurrentThreadId();
1919319438
}
19439
+
1919419440
static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){
1919519441
return p->nRef==0 || p->owner!=tid;
1919619442
}
19443
+
1919719444
static int winMutexNotheld(sqlite3_mutex *p){
19198
- DWORD tid = GetCurrentThreadId();
19445
+ DWORD tid = GetCurrentThreadId();
1919919446
return winMutexNotheld2(p, tid);
1920019447
}
1920119448
#endif
1920219449
19203
-
1920419450
/*
1920519451
** Initialize and deinitialize the mutex subsystem.
1920619452
*/
19207
-static sqlite3_mutex winMutex_staticMutexes[6] = {
19453
+static sqlite3_mutex winMutex_staticMutexes[] = {
19454
+ SQLITE3_MUTEX_INITIALIZER,
19455
+ SQLITE3_MUTEX_INITIALIZER,
19456
+ SQLITE3_MUTEX_INITIALIZER,
1920819457
SQLITE3_MUTEX_INITIALIZER,
1920919458
SQLITE3_MUTEX_INITIALIZER,
1921019459
SQLITE3_MUTEX_INITIALIZER,
1921119460
SQLITE3_MUTEX_INITIALIZER,
1921219461
SQLITE3_MUTEX_INITIALIZER,
1921319462
SQLITE3_MUTEX_INITIALIZER
1921419463
};
19464
+
1921519465
static int winMutex_isInit = 0;
19216
-/* As winMutexInit() and winMutexEnd() are called as part
19217
-** of the sqlite3_initialize and sqlite3_shutdown()
19218
-** processing, the "interlocked" magic is probably not
19219
-** strictly necessary.
19466
+static int winMutex_isNt = -1; /* <0 means "need to query" */
19467
+
19468
+/* As the winMutexInit() and winMutexEnd() functions are called as part
19469
+** of the sqlite3_initialize() and sqlite3_shutdown() processing, the
19470
+** "interlocked" magic used here is probably not strictly necessary.
1922019471
*/
19221
-static LONG winMutex_lock = 0;
19472
+static LONG volatile winMutex_lock = 0;
1922219473
19474
+SQLITE_API int sqlite3_win32_is_nt(void); /* os_win.c */
1922319475
SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
1922419476
19225
-static int winMutexInit(void){
19477
+static int winMutexInit(void){
1922619478
/* The first to increment to 1 does actual initialization */
1922719479
if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
1922819480
int i;
1922919481
for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
1923019482
#if SQLITE_OS_WINRT
@@ -19233,20 +19485,21 @@
1923319485
InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);
1923419486
#endif
1923519487
}
1923619488
winMutex_isInit = 1;
1923719489
}else{
19238
- /* Someone else is in the process of initing the static mutexes */
19490
+ /* Another thread is (in the process of) initializing the static
19491
+ ** mutexes */
1923919492
while( !winMutex_isInit ){
1924019493
sqlite3_win32_sleep(1);
1924119494
}
1924219495
}
19243
- return SQLITE_OK;
19496
+ return SQLITE_OK;
1924419497
}
1924519498
19246
-static int winMutexEnd(void){
19247
- /* The first to decrement to 0 does actual shutdown
19499
+static int winMutexEnd(void){
19500
+ /* The first to decrement to 0 does actual shutdown
1924819501
** (which should be the last to shutdown.) */
1924919502
if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){
1925019503
if( winMutex_isInit==1 ){
1925119504
int i;
1925219505
for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
@@ -19253,11 +19506,11 @@
1925319506
DeleteCriticalSection(&winMutex_staticMutexes[i].mutex);
1925419507
}
1925519508
winMutex_isInit = 0;
1925619509
}
1925719510
}
19258
- return SQLITE_OK;
19511
+ return SQLITE_OK;
1925919512
}
1926019513
1926119514
/*
1926219515
** The sqlite3_mutex_alloc() routine allocates a new
1926319516
** mutex and returns a pointer to it. If it returns NULL
@@ -19268,14 +19521,17 @@
1926819521
** <ul>
1926919522
** <li> SQLITE_MUTEX_FAST
1927019523
** <li> SQLITE_MUTEX_RECURSIVE
1927119524
** <li> SQLITE_MUTEX_STATIC_MASTER
1927219525
** <li> SQLITE_MUTEX_STATIC_MEM
19273
-** <li> SQLITE_MUTEX_STATIC_MEM2
19526
+** <li> SQLITE_MUTEX_STATIC_OPEN
1927419527
** <li> SQLITE_MUTEX_STATIC_PRNG
1927519528
** <li> SQLITE_MUTEX_STATIC_LRU
1927619529
** <li> SQLITE_MUTEX_STATIC_PMEM
19530
+** <li> SQLITE_MUTEX_STATIC_APP1
19531
+** <li> SQLITE_MUTEX_STATIC_APP2
19532
+** <li> SQLITE_MUTEX_STATIC_APP3
1927719533
** </ul>
1927819534
**
1927919535
** The first two constants cause sqlite3_mutex_alloc() to create
1928019536
** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
1928119537
** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
@@ -19294,11 +19550,11 @@
1929419550
** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
1929519551
** SQLITE_MUTEX_RECURSIVE.
1929619552
**
1929719553
** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
1929819554
** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
19299
-** returns a different mutex on every call. But for the static
19555
+** returns a different mutex on every call. But for the static
1930019556
** mutex types, the same mutex is returned on every call that has
1930119557
** the same type number.
1930219558
*/
1930319559
static sqlite3_mutex *winMutexAlloc(int iType){
1930419560
sqlite3_mutex *p;
@@ -19305,13 +19561,16 @@
1930519561
1930619562
switch( iType ){
1930719563
case SQLITE_MUTEX_FAST:
1930819564
case SQLITE_MUTEX_RECURSIVE: {
1930919565
p = sqlite3MallocZero( sizeof(*p) );
19310
- if( p ){
19566
+ if( p ){
1931119567
#ifdef SQLITE_DEBUG
1931219568
p->id = iType;
19569
+#ifdef SQLITE_WIN32_MUTEX_TRACE_DYNAMIC
19570
+ p->trace = 1;
19571
+#endif
1931319572
#endif
1931419573
#if SQLITE_OS_WINRT
1931519574
InitializeCriticalSectionEx(&p->mutex, 0, 0);
1931619575
#else
1931719576
InitializeCriticalSection(&p->mutex);
@@ -19318,16 +19577,19 @@
1931819577
#endif
1931919578
}
1932019579
break;
1932119580
}
1932219581
default: {
19323
- assert( winMutex_isInit==1 );
1932419582
assert( iType-2 >= 0 );
1932519583
assert( iType-2 < ArraySize(winMutex_staticMutexes) );
19584
+ assert( winMutex_isInit==1 );
1932619585
p = &winMutex_staticMutexes[iType-2];
1932719586
#ifdef SQLITE_DEBUG
1932819587
p->id = iType;
19588
+#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC
19589
+ p->trace = 1;
19590
+#endif
1932919591
#endif
1933019592
break;
1933119593
}
1933219594
}
1933319595
return p;
@@ -19339,12 +19601,15 @@
1933919601
** allocated mutex. SQLite is careful to deallocate every
1934019602
** mutex that it allocates.
1934119603
*/
1934219604
static void winMutexFree(sqlite3_mutex *p){
1934319605
assert( p );
19606
+#ifdef SQLITE_DEBUG
1934419607
assert( p->nRef==0 && p->owner==0 );
1934519608
assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
19609
+#endif
19610
+ assert( winMutex_isInit==1 );
1934619611
DeleteCriticalSection(&p->mutex);
1934719612
sqlite3_free(p);
1934819613
}
1934919614
1935019615
/*
@@ -19357,53 +19622,71 @@
1935719622
** mutex must be exited an equal number of times before another thread
1935819623
** can enter. If the same thread tries to enter any other kind of mutex
1935919624
** more than once, the behavior is undefined.
1936019625
*/
1936119626
static void winMutexEnter(sqlite3_mutex *p){
19627
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
19628
+ DWORD tid = GetCurrentThreadId();
19629
+#endif
1936219630
#ifdef SQLITE_DEBUG
19363
- DWORD tid = GetCurrentThreadId();
19631
+ assert( p );
1936419632
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
19633
+#else
19634
+ assert( p );
1936519635
#endif
19636
+ assert( winMutex_isInit==1 );
1936619637
EnterCriticalSection(&p->mutex);
1936719638
#ifdef SQLITE_DEBUG
1936819639
assert( p->nRef>0 || p->owner==0 );
19369
- p->owner = tid;
19640
+ p->owner = tid;
1937019641
p->nRef++;
1937119642
if( p->trace ){
19372
- printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
19643
+ OSTRACE(("ENTER-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n",
19644
+ tid, p, p->trace, p->nRef));
1937319645
}
1937419646
#endif
1937519647
}
19648
+
1937619649
static int winMutexTry(sqlite3_mutex *p){
19377
-#ifndef NDEBUG
19378
- DWORD tid = GetCurrentThreadId();
19650
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
19651
+ DWORD tid = GetCurrentThreadId();
1937919652
#endif
1938019653
int rc = SQLITE_BUSY;
19654
+ assert( p );
1938119655
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
1938219656
/*
1938319657
** The sqlite3_mutex_try() routine is very rarely used, and when it
1938419658
** is used it is merely an optimization. So it is OK for it to always
19385
- ** fail.
19659
+ ** fail.
1938619660
**
1938719661
** The TryEnterCriticalSection() interface is only available on WinNT.
1938819662
** And some windows compilers complain if you try to use it without
1938919663
** first doing some #defines that prevent SQLite from building on Win98.
1939019664
** For that reason, we will omit this optimization for now. See
1939119665
** ticket #2685.
1939219666
*/
19393
-#if 0
19394
- if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){
19667
+#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400
19668
+ assert( winMutex_isInit==1 );
19669
+ assert( winMutex_isNt>=-1 && winMutex_isNt<=1 );
19670
+ if( winMutex_isNt<0 ){
19671
+ winMutex_isNt = sqlite3_win32_is_nt();
19672
+ }
19673
+ assert( winMutex_isNt==0 || winMutex_isNt==1 );
19674
+ if( winMutex_isNt && TryEnterCriticalSection(&p->mutex) ){
19675
+#ifdef SQLITE_DEBUG
1939519676
p->owner = tid;
1939619677
p->nRef++;
19678
+#endif
1939719679
rc = SQLITE_OK;
1939819680
}
1939919681
#else
1940019682
UNUSED_PARAMETER(p);
1940119683
#endif
1940219684
#ifdef SQLITE_DEBUG
19403
- if( rc==SQLITE_OK && p->trace ){
19404
- printf("try mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
19685
+ if( p->trace ){
19686
+ OSTRACE(("TRY-MUTEX tid=%lu, mutex=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
19687
+ tid, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc)));
1940519688
}
1940619689
#endif
1940719690
return rc;
1940819691
}
1940919692
@@ -19412,22 +19695,27 @@
1941219695
** previously entered by the same thread. The behavior
1941319696
** is undefined if the mutex is not currently entered or
1941419697
** is not currently allocated. SQLite will never do either.
1941519698
*/
1941619699
static void winMutexLeave(sqlite3_mutex *p){
19417
-#ifndef NDEBUG
19700
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
1941819701
DWORD tid = GetCurrentThreadId();
19702
+#endif
19703
+ assert( p );
19704
+#ifdef SQLITE_DEBUG
1941919705
assert( p->nRef>0 );
1942019706
assert( p->owner==tid );
1942119707
p->nRef--;
1942219708
if( p->nRef==0 ) p->owner = 0;
1942319709
assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
1942419710
#endif
19711
+ assert( winMutex_isInit==1 );
1942519712
LeaveCriticalSection(&p->mutex);
1942619713
#ifdef SQLITE_DEBUG
1942719714
if( p->trace ){
19428
- printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
19715
+ OSTRACE(("LEAVE-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n",
19716
+ tid, p, p->trace, p->nRef));
1942919717
}
1943019718
#endif
1943119719
}
1943219720
1943319721
SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
@@ -19445,13 +19733,13 @@
1944519733
#else
1944619734
0,
1944719735
0
1944819736
#endif
1944919737
};
19450
-
1945119738
return &sMutex;
1945219739
}
19740
+
1945319741
#endif /* SQLITE_MUTEX_W32 */
1945419742
1945519743
/************** End of mutex_w32.c *******************************************/
1945619744
/************** Begin file malloc.c ******************************************/
1945719745
/*
@@ -22422,13 +22710,13 @@
2242222710
testcase( c==(+1) );
2242322711
}
2242422712
return c;
2242522713
}
2242622714
22427
-
2242822715
/*
22429
-** Convert zNum to a 64-bit signed integer.
22716
+** Convert zNum to a 64-bit signed integer. zNum must be decimal. This
22717
+** routine does *not* accept hexadecimal notation.
2243022718
**
2243122719
** If the zNum value is representable as a 64-bit twos-complement
2243222720
** integer, then write that value into *pNum and return 0.
2243322721
**
2243422722
** If zNum is exactly 9223372036854775808, return 2. This special
@@ -22511,14 +22799,48 @@
2251122799
assert( u-1==LARGEST_INT64 );
2251222800
return neg ? 0 : 2;
2251322801
}
2251422802
}
2251522803
}
22804
+
22805
+/*
22806
+** Transform a UTF-8 integer literal, in either decimal or hexadecimal,
22807
+** into a 64-bit signed integer. This routine accepts hexadecimal literals,
22808
+** whereas sqlite3Atoi64() does not.
22809
+**
22810
+** Returns:
22811
+**
22812
+** 0 Successful transformation. Fits in a 64-bit signed integer.
22813
+** 1 Integer too large for a 64-bit signed integer or is malformed
22814
+** 2 Special case of 9223372036854775808
22815
+*/
22816
+SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
22817
+#ifndef SQLITE_OMIT_HEX_INTEGER
22818
+ if( z[0]=='0'
22819
+ && (z[1]=='x' || z[1]=='X')
22820
+ && sqlite3Isxdigit(z[2])
22821
+ ){
22822
+ u64 u = 0;
22823
+ int i, k;
22824
+ for(i=2; z[i]=='0'; i++){}
22825
+ for(k=i; sqlite3Isxdigit(z[k]); k++){
22826
+ u = u*16 + sqlite3HexToInt(z[k]);
22827
+ }
22828
+ memcpy(pOut, &u, 8);
22829
+ return (z[k]==0 && k-i<=16) ? 0 : 1;
22830
+ }else
22831
+#endif /* SQLITE_OMIT_HEX_INTEGER */
22832
+ {
22833
+ return sqlite3Atoi64(z, pOut, sqlite3Strlen30(z), SQLITE_UTF8);
22834
+ }
22835
+}
2251622836
2251722837
/*
2251822838
** If zNum represents an integer that will fit in 32-bits, then set
2251922839
** *pValue to that integer and return true. Otherwise return false.
22840
+**
22841
+** This routine accepts both decimal and hexadecimal notation for integers.
2252022842
**
2252122843
** Any non-numeric characters that following zNum are ignored.
2252222844
** This is different from sqlite3Atoi64() which requires the
2252322845
** input number to be zero-terminated.
2252422846
*/
@@ -22530,11 +22852,29 @@
2253022852
neg = 1;
2253122853
zNum++;
2253222854
}else if( zNum[0]=='+' ){
2253322855
zNum++;
2253422856
}
22535
- while( zNum[0]=='0' ) zNum++;
22857
+#ifndef SQLITE_OMIT_HEX_INTEGER
22858
+ else if( zNum[0]=='0'
22859
+ && (zNum[1]=='x' || zNum[1]=='X')
22860
+ && sqlite3Isxdigit(zNum[2])
22861
+ ){
22862
+ u32 u = 0;
22863
+ zNum += 2;
22864
+ while( zNum[0]=='0' ) zNum++;
22865
+ for(i=0; sqlite3Isxdigit(zNum[i]) && i<8; i++){
22866
+ u = u*16 + sqlite3HexToInt(zNum[i]);
22867
+ }
22868
+ if( (u&0x80000000)==0 && sqlite3Isxdigit(zNum[i])==0 ){
22869
+ memcpy(pValue, &u, 4);
22870
+ return 1;
22871
+ }else{
22872
+ return 0;
22873
+ }
22874
+ }
22875
+#endif
2253622876
for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){
2253722877
v = v*10 + c;
2253822878
}
2253922879
2254022880
/* The longest decimal representation of a 32 bit integer is 10 digits:
@@ -23606,43 +23946,43 @@
2360623946
/* 47 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
2360723947
/* 48 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
2360823948
/* 49 */ "Count" OpHelp("r[P2]=count()"),
2360923949
/* 50 */ "ReadCookie" OpHelp(""),
2361023950
/* 51 */ "SetCookie" OpHelp(""),
23611
- /* 52 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
23612
- /* 53 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
23613
- /* 54 */ "OpenAutoindex" OpHelp("nColumn=P2"),
23614
- /* 55 */ "OpenEphemeral" OpHelp("nColumn=P2"),
23615
- /* 56 */ "SorterOpen" OpHelp(""),
23616
- /* 57 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
23617
- /* 58 */ "Close" OpHelp(""),
23618
- /* 59 */ "SeekLT" OpHelp(""),
23619
- /* 60 */ "SeekLE" OpHelp(""),
23620
- /* 61 */ "SeekGE" OpHelp(""),
23621
- /* 62 */ "SeekGT" OpHelp(""),
23622
- /* 63 */ "Seek" OpHelp("intkey=r[P2]"),
23623
- /* 64 */ "NoConflict" OpHelp("key=r[P3@P4]"),
23624
- /* 65 */ "NotFound" OpHelp("key=r[P3@P4]"),
23625
- /* 66 */ "Found" OpHelp("key=r[P3@P4]"),
23626
- /* 67 */ "NotExists" OpHelp("intkey=r[P3]"),
23627
- /* 68 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
23628
- /* 69 */ "NewRowid" OpHelp("r[P2]=rowid"),
23629
- /* 70 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
23951
+ /* 52 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
23952
+ /* 53 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
23953
+ /* 54 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
23954
+ /* 55 */ "OpenAutoindex" OpHelp("nColumn=P2"),
23955
+ /* 56 */ "OpenEphemeral" OpHelp("nColumn=P2"),
23956
+ /* 57 */ "SorterOpen" OpHelp(""),
23957
+ /* 58 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
23958
+ /* 59 */ "Close" OpHelp(""),
23959
+ /* 60 */ "SeekLT" OpHelp("key=r[P3@P4]"),
23960
+ /* 61 */ "SeekLE" OpHelp("key=r[P3@P4]"),
23961
+ /* 62 */ "SeekGE" OpHelp("key=r[P3@P4]"),
23962
+ /* 63 */ "SeekGT" OpHelp("key=r[P3@P4]"),
23963
+ /* 64 */ "Seek" OpHelp("intkey=r[P2]"),
23964
+ /* 65 */ "NoConflict" OpHelp("key=r[P3@P4]"),
23965
+ /* 66 */ "NotFound" OpHelp("key=r[P3@P4]"),
23966
+ /* 67 */ "Found" OpHelp("key=r[P3@P4]"),
23967
+ /* 68 */ "NotExists" OpHelp("intkey=r[P3]"),
23968
+ /* 69 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
23969
+ /* 70 */ "NewRowid" OpHelp("r[P2]=rowid"),
2363023970
/* 71 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"),
2363123971
/* 72 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"),
23632
- /* 73 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"),
23633
- /* 74 */ "Delete" OpHelp(""),
23634
- /* 75 */ "ResetCount" OpHelp(""),
23972
+ /* 73 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
23973
+ /* 74 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"),
23974
+ /* 75 */ "Delete" OpHelp(""),
2363523975
/* 76 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
2363623976
/* 77 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
2363723977
/* 78 */ "Ne" OpHelp("if r[P1]!=r[P3] goto P2"),
2363823978
/* 79 */ "Eq" OpHelp("if r[P1]==r[P3] goto P2"),
2363923979
/* 80 */ "Gt" OpHelp("if r[P1]>r[P3] goto P2"),
2364023980
/* 81 */ "Le" OpHelp("if r[P1]<=r[P3] goto P2"),
2364123981
/* 82 */ "Lt" OpHelp("if r[P1]<r[P3] goto P2"),
2364223982
/* 83 */ "Ge" OpHelp("if r[P1]>=r[P3] goto P2"),
23643
- /* 84 */ "SorterCompare" OpHelp("if key(P1)!=rtrim(r[P3],P4) goto P2"),
23983
+ /* 84 */ "ResetCount" OpHelp(""),
2364423984
/* 85 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
2364523985
/* 86 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
2364623986
/* 87 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
2364723987
/* 88 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
2364823988
/* 89 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
@@ -23649,73 +23989,74 @@
2364923989
/* 90 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
2365023990
/* 91 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
2365123991
/* 92 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
2365223992
/* 93 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
2365323993
/* 94 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
23654
- /* 95 */ "SorterData" OpHelp("r[P2]=data"),
23994
+ /* 95 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
2365523995
/* 96 */ "BitNot" OpHelp("r[P1]= ~r[P1]"),
2365623996
/* 97 */ "String8" OpHelp("r[P2]='P4'"),
23657
- /* 98 */ "RowKey" OpHelp("r[P2]=key"),
23658
- /* 99 */ "RowData" OpHelp("r[P2]=data"),
23659
- /* 100 */ "Rowid" OpHelp("r[P2]=rowid"),
23660
- /* 101 */ "NullRow" OpHelp(""),
23661
- /* 102 */ "Last" OpHelp(""),
23662
- /* 103 */ "SorterSort" OpHelp(""),
23663
- /* 104 */ "Sort" OpHelp(""),
23664
- /* 105 */ "Rewind" OpHelp(""),
23665
- /* 106 */ "SorterInsert" OpHelp(""),
23666
- /* 107 */ "IdxInsert" OpHelp("key=r[P2]"),
23667
- /* 108 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
23668
- /* 109 */ "IdxRowid" OpHelp("r[P2]=rowid"),
23669
- /* 110 */ "IdxLE" OpHelp("key=r[P3@P4]"),
23670
- /* 111 */ "IdxGT" OpHelp("key=r[P3@P4]"),
23671
- /* 112 */ "IdxLT" OpHelp("key=r[P3@P4]"),
23672
- /* 113 */ "IdxGE" OpHelp("key=r[P3@P4]"),
23673
- /* 114 */ "Destroy" OpHelp(""),
23674
- /* 115 */ "Clear" OpHelp(""),
23675
- /* 116 */ "ResetSorter" OpHelp(""),
23676
- /* 117 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"),
23677
- /* 118 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"),
23678
- /* 119 */ "ParseSchema" OpHelp(""),
23679
- /* 120 */ "LoadAnalysis" OpHelp(""),
23680
- /* 121 */ "DropTable" OpHelp(""),
23681
- /* 122 */ "DropIndex" OpHelp(""),
23682
- /* 123 */ "DropTrigger" OpHelp(""),
23683
- /* 124 */ "IntegrityCk" OpHelp(""),
23684
- /* 125 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
23685
- /* 126 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
23686
- /* 127 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
23687
- /* 128 */ "Program" OpHelp(""),
23688
- /* 129 */ "Param" OpHelp(""),
23689
- /* 130 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
23690
- /* 131 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
23691
- /* 132 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
23997
+ /* 98 */ "SorterData" OpHelp("r[P2]=data"),
23998
+ /* 99 */ "RowKey" OpHelp("r[P2]=key"),
23999
+ /* 100 */ "RowData" OpHelp("r[P2]=data"),
24000
+ /* 101 */ "Rowid" OpHelp("r[P2]=rowid"),
24001
+ /* 102 */ "NullRow" OpHelp(""),
24002
+ /* 103 */ "Last" OpHelp(""),
24003
+ /* 104 */ "SorterSort" OpHelp(""),
24004
+ /* 105 */ "Sort" OpHelp(""),
24005
+ /* 106 */ "Rewind" OpHelp(""),
24006
+ /* 107 */ "SorterInsert" OpHelp(""),
24007
+ /* 108 */ "IdxInsert" OpHelp("key=r[P2]"),
24008
+ /* 109 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
24009
+ /* 110 */ "IdxRowid" OpHelp("r[P2]=rowid"),
24010
+ /* 111 */ "IdxLE" OpHelp("key=r[P3@P4]"),
24011
+ /* 112 */ "IdxGT" OpHelp("key=r[P3@P4]"),
24012
+ /* 113 */ "IdxLT" OpHelp("key=r[P3@P4]"),
24013
+ /* 114 */ "IdxGE" OpHelp("key=r[P3@P4]"),
24014
+ /* 115 */ "Destroy" OpHelp(""),
24015
+ /* 116 */ "Clear" OpHelp(""),
24016
+ /* 117 */ "ResetSorter" OpHelp(""),
24017
+ /* 118 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"),
24018
+ /* 119 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"),
24019
+ /* 120 */ "ParseSchema" OpHelp(""),
24020
+ /* 121 */ "LoadAnalysis" OpHelp(""),
24021
+ /* 122 */ "DropTable" OpHelp(""),
24022
+ /* 123 */ "DropIndex" OpHelp(""),
24023
+ /* 124 */ "DropTrigger" OpHelp(""),
24024
+ /* 125 */ "IntegrityCk" OpHelp(""),
24025
+ /* 126 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
24026
+ /* 127 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
24027
+ /* 128 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
24028
+ /* 129 */ "Program" OpHelp(""),
24029
+ /* 130 */ "Param" OpHelp(""),
24030
+ /* 131 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
24031
+ /* 132 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
2369224032
/* 133 */ "Real" OpHelp("r[P2]=P4"),
23693
- /* 134 */ "IfPos" OpHelp("if r[P1]>0 goto P2"),
23694
- /* 135 */ "IfNeg" OpHelp("if r[P1]<0 goto P2"),
23695
- /* 136 */ "IfZero" OpHelp("r[P1]+=P3, if r[P1]==0 goto P2"),
23696
- /* 137 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
23697
- /* 138 */ "IncrVacuum" OpHelp(""),
23698
- /* 139 */ "Expire" OpHelp(""),
23699
- /* 140 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
23700
- /* 141 */ "VBegin" OpHelp(""),
23701
- /* 142 */ "VCreate" OpHelp(""),
24033
+ /* 134 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
24034
+ /* 135 */ "IfPos" OpHelp("if r[P1]>0 goto P2"),
24035
+ /* 136 */ "IfNeg" OpHelp("r[P1]+=P3, if r[P1]<0 goto P2"),
24036
+ /* 137 */ "IfZero" OpHelp("r[P1]+=P3, if r[P1]==0 goto P2"),
24037
+ /* 138 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
24038
+ /* 139 */ "IncrVacuum" OpHelp(""),
24039
+ /* 140 */ "Expire" OpHelp(""),
24040
+ /* 141 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
24041
+ /* 142 */ "VBegin" OpHelp(""),
2370224042
/* 143 */ "ToText" OpHelp(""),
2370324043
/* 144 */ "ToBlob" OpHelp(""),
2370424044
/* 145 */ "ToNumeric" OpHelp(""),
2370524045
/* 146 */ "ToInt" OpHelp(""),
2370624046
/* 147 */ "ToReal" OpHelp(""),
23707
- /* 148 */ "VDestroy" OpHelp(""),
23708
- /* 149 */ "VOpen" OpHelp(""),
23709
- /* 150 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
23710
- /* 151 */ "VNext" OpHelp(""),
23711
- /* 152 */ "VRename" OpHelp(""),
23712
- /* 153 */ "Pagecount" OpHelp(""),
23713
- /* 154 */ "MaxPgcnt" OpHelp(""),
23714
- /* 155 */ "Init" OpHelp("Start at P2"),
23715
- /* 156 */ "Noop" OpHelp(""),
23716
- /* 157 */ "Explain" OpHelp(""),
24047
+ /* 148 */ "VCreate" OpHelp(""),
24048
+ /* 149 */ "VDestroy" OpHelp(""),
24049
+ /* 150 */ "VOpen" OpHelp(""),
24050
+ /* 151 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
24051
+ /* 152 */ "VNext" OpHelp(""),
24052
+ /* 153 */ "VRename" OpHelp(""),
24053
+ /* 154 */ "Pagecount" OpHelp(""),
24054
+ /* 155 */ "MaxPgcnt" OpHelp(""),
24055
+ /* 156 */ "Init" OpHelp("Start at P2"),
24056
+ /* 157 */ "Noop" OpHelp(""),
24057
+ /* 158 */ "Explain" OpHelp(""),
2371724058
};
2371824059
return azName[i];
2371924060
}
2372024061
#endif
2372124062
@@ -23814,15 +24155,14 @@
2381424155
#include <unistd.h>
2381524156
/* #include <time.h> */
2381624157
#include <sys/time.h>
2381724158
#include <errno.h>
2381824159
#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
23819
-#include <sys/mman.h>
24160
+# include <sys/mman.h>
2382024161
#endif
2382124162
23822
-
23823
-#if SQLITE_ENABLE_LOCKING_STYLE
24163
+#if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS
2382424164
# include <sys/ioctl.h>
2382524165
# if OS_VXWORKS
2382624166
# include <semaphore.h>
2382724167
# include <limits.h>
2382824168
# else
@@ -24246,11 +24586,15 @@
2424624586
** On some systems, calls to fchown() will trigger a message in a security
2424724587
** log if they come from non-root processes. So avoid calling fchown() if
2424824588
** we are not running as root.
2424924589
*/
2425024590
static int posixFchown(int fd, uid_t uid, gid_t gid){
24591
+#if OS_VXWORKS
24592
+ return 0;
24593
+#else
2425124594
return geteuid() ? 0 : fchown(fd,uid,gid);
24595
+#endif
2425224596
}
2425324597
2425424598
/* Forward reference */
2425524599
static int openDirectory(const char*, int*);
2425624600
static int unixGetpagesize(void);
@@ -24302,11 +24646,11 @@
2430224646
#define osFcntl ((int(*)(int,int,...))aSyscall[7].pCurrent)
2430324647
2430424648
{ "read", (sqlite3_syscall_ptr)read, 0 },
2430524649
#define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
2430624650
24307
-#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
24651
+#if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
2430824652
{ "pread", (sqlite3_syscall_ptr)pread, 0 },
2430924653
#else
2431024654
{ "pread", (sqlite3_syscall_ptr)0, 0 },
2431124655
#endif
2431224656
#define osPread ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].pCurrent)
@@ -24319,11 +24663,11 @@
2431924663
#define osPread64 ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].pCurrent)
2432024664
2432124665
{ "write", (sqlite3_syscall_ptr)write, 0 },
2432224666
#define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
2432324667
24324
-#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
24668
+#if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
2432524669
{ "pwrite", (sqlite3_syscall_ptr)pwrite, 0 },
2432624670
#else
2432724671
{ "pwrite", (sqlite3_syscall_ptr)0, 0 },
2432824672
#endif
2432924673
#define osPwrite ((ssize_t(*)(int,const void*,size_t,off_t))\
@@ -24689,20 +25033,10 @@
2468925033
}
2469025034
/* else fall through */
2469125035
case EPERM:
2469225036
return SQLITE_PERM;
2469325037
24694
- /* EDEADLK is only possible if a call to fcntl(F_SETLKW) is made. And
24695
- ** this module never makes such a call. And the code in SQLite itself
24696
- ** asserts that SQLITE_IOERR_BLOCKED is never returned. For these reasons
24697
- ** this case is also commented out. If the system does set errno to EDEADLK,
24698
- ** the default SQLITE_IOERR_XXX code will be returned. */
24699
-#if 0
24700
- case EDEADLK:
24701
- return SQLITE_IOERR_BLOCKED;
24702
-#endif
24703
-
2470425038
#if EOPNOTSUPP!=ENOTSUP
2470525039
case EOPNOTSUPP:
2470625040
/* something went terribly awry, unless during file system support
2470725041
* introspection, in which it actually means what it says */
2470825042
#endif
@@ -25231,13 +25565,17 @@
2523125565
2523225566
/*
2523325567
** Return TRUE if pFile has been renamed or unlinked since it was first opened.
2523425568
*/
2523525569
static int fileHasMoved(unixFile *pFile){
25570
+#if OS_VXWORKS
25571
+ return pFile->pInode!=0 && pFile->pId!=pFile->pInode->fileId.pId;
25572
+#else
2523625573
struct stat buf;
2523725574
return pFile->pInode!=0 &&
25238
- (osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino);
25575
+ (osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino);
25576
+#endif
2523925577
}
2524025578
2524125579
2524225580
/*
2524325581
** Check a unixFile that is a database. Verify the following:
@@ -26376,11 +26714,10 @@
2637626714
}
2637726715
2637826716
/* Otherwise see if some other process holds it. */
2637926717
if( !reserved ){
2638026718
sem_t *pSem = pFile->pInode->pSem;
26381
- struct stat statBuf;
2638226719
2638326720
if( sem_trywait(pSem)==-1 ){
2638426721
int tErrno = errno;
2638526722
if( EAGAIN != tErrno ){
2638626723
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
@@ -26429,11 +26766,10 @@
2642926766
** This routine will only increase a lock. Use the sqlite3OsUnlock()
2643026767
** routine to lower a locking level.
2643126768
*/
2643226769
static int semLock(sqlite3_file *id, int eFileLock) {
2643326770
unixFile *pFile = (unixFile*)id;
26434
- int fd;
2643526771
sem_t *pSem = pFile->pInode->pSem;
2643626772
int rc = SQLITE_OK;
2643726773
2643826774
/* if we already have a lock, it is exclusive.
2643926775
** Just adjust level and punt on outta here. */
@@ -31713,22 +32049,18 @@
3171332049
#ifndef NTDDI_WINBLUE
3171432050
# define NTDDI_WINBLUE 0x06030000
3171532051
#endif
3171632052
3171732053
/*
31718
-** Check if the GetVersionEx[AW] functions should be considered deprecated
31719
-** and avoid using them in that case. It should be noted here that if the
31720
-** value of the SQLITE_WIN32_GETVERSIONEX pre-processor macro is zero
31721
-** (whether via this block or via being manually specified), that implies
31722
-** the underlying operating system will always be based on the Windows NT
31723
-** Kernel.
32054
+** Check to see if the GetVersionEx[AW] functions are deprecated on the
32055
+** target system. GetVersionEx was first deprecated in Win8.1.
3172432056
*/
3172532057
#ifndef SQLITE_WIN32_GETVERSIONEX
3172632058
# if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINBLUE
31727
-# define SQLITE_WIN32_GETVERSIONEX 0
32059
+# define SQLITE_WIN32_GETVERSIONEX 0 /* GetVersionEx() is deprecated */
3172832060
# else
31729
-# define SQLITE_WIN32_GETVERSIONEX 1
32061
+# define SQLITE_WIN32_GETVERSIONEX 1 /* GetVersionEx() is current */
3173032062
# endif
3173132063
#endif
3173232064
3173332065
/*
3173432066
** This constant should already be defined (in the "WinDef.h" SDK file).
@@ -31796,11 +32128,11 @@
3179632128
/*
3179732129
** This macro is used when a local variable is set to a value that is
3179832130
** [sometimes] not used by the code (e.g. via conditional compilation).
3179932131
*/
3180032132
#ifndef UNUSED_VARIABLE_VALUE
31801
-# define UNUSED_VARIABLE_VALUE(x) (void)(x)
32133
+# define UNUSED_VARIABLE_VALUE(x) (void)(x)
3180232134
#endif
3180332135
3180432136
/*
3180532137
** Returns the character that should be used as the directory separator.
3180632138
*/
@@ -31845,11 +32177,11 @@
3184532177
3184632178
/*
3184732179
** Some Microsoft compilers lack this definition.
3184832180
*/
3184932181
#ifndef INVALID_FILE_ATTRIBUTES
31850
-# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
32182
+# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
3185132183
#endif
3185232184
3185332185
#ifndef FILE_FLAG_MASK
3185432186
# define FILE_FLAG_MASK (0xFF3C0000)
3185532187
#endif
@@ -31895,11 +32227,11 @@
3189532227
#endif
3189632228
const char *zPath; /* Full pathname of this file */
3189732229
int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */
3189832230
#if SQLITE_OS_WINCE
3189932231
LPWSTR zDeleteOnClose; /* Name of file to delete when closing */
31900
- HANDLE hMutex; /* Mutex used to control access to shared lock */
32232
+ HANDLE hMutex; /* Mutex used to control access to shared lock */
3190132233
HANDLE hShared; /* Shared memory segment used for locking */
3190232234
winceLock local; /* Locks obtained by this instance of winFile */
3190332235
winceLock *shared; /* Global shared lock memory for the file */
3190432236
#endif
3190532237
#if SQLITE_MAX_MMAP_SIZE>0
@@ -32055,14 +32387,13 @@
3205532387
**
3205632388
** In order to facilitate testing on a WinNT system, the test fixture
3205732389
** can manually set this value to 1 to emulate Win98 behavior.
3205832390
*/
3205932391
#ifdef SQLITE_TEST
32060
-SQLITE_API int sqlite3_os_type = 0;
32061
-#elif !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \
32062
- defined(SQLITE_WIN32_HAS_ANSI) && defined(SQLITE_WIN32_HAS_WIDE)
32063
-static int sqlite3_os_type = 0;
32392
+SQLITE_API LONG volatile sqlite3_os_type = 0;
32393
+#else
32394
+static LONG volatile sqlite3_os_type = 0;
3206432395
#endif
3206532396
3206632397
#ifndef SYSCALL
3206732398
# define SYSCALL sqlite3_syscall_ptr
3206832399
#endif
@@ -32689,10 +33020,26 @@
3268933020
#endif
3269033021
3269133022
#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
3269233023
LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[75].pCurrent)
3269333024
33025
+/*
33026
+** NOTE: On some sub-platforms, the InterlockedCompareExchange "function"
33027
+** is really just a macro that uses a compiler intrinsic (e.g. x64).
33028
+** So do not try to make this is into a redefinable interface.
33029
+*/
33030
+#if defined(InterlockedCompareExchange)
33031
+ { "InterlockedCompareExchange", (SYSCALL)0, 0 },
33032
+
33033
+#define osInterlockedCompareExchange InterlockedCompareExchange
33034
+#else
33035
+ { "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 },
33036
+
33037
+#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG volatile*, \
33038
+ LONG,LONG))aSyscall[76].pCurrent)
33039
+#endif /* defined(InterlockedCompareExchange) */
33040
+
3269433041
}; /* End of the overrideable system calls */
3269533042
3269633043
/*
3269733044
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
3269833045
** "win32" VFSes. Return SQLITE_OK opon successfully updating the
@@ -32939,26 +33286,42 @@
3293933286
#elif SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI)
3294033287
# define osIsNT() (1)
3294133288
#elif !defined(SQLITE_WIN32_HAS_WIDE)
3294233289
# define osIsNT() (0)
3294333290
#else
32944
- static int osIsNT(void){
32945
- if( sqlite3_os_type==0 ){
32946
-#if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WIN8
32947
- OSVERSIONINFOW sInfo;
32948
- sInfo.dwOSVersionInfoSize = sizeof(sInfo);
32949
- osGetVersionExW(&sInfo);
33291
+# define osIsNT() ((sqlite3_os_type==2) || sqlite3_win32_is_nt())
33292
+#endif
33293
+
33294
+/*
33295
+** This function determines if the machine is running a version of Windows
33296
+** based on the NT kernel.
33297
+*/
33298
+SQLITE_API int sqlite3_win32_is_nt(void){
33299
+#if defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX
33300
+ if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){
33301
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
33302
+ defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WIN8
33303
+ OSVERSIONINFOW sInfo;
33304
+ sInfo.dwOSVersionInfoSize = sizeof(sInfo);
33305
+ osGetVersionExW(&sInfo);
33306
+ osInterlockedCompareExchange(&sqlite3_os_type,
33307
+ (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
33308
+#elif defined(SQLITE_WIN32_HAS_ANSI)
33309
+ OSVERSIONINFOA sInfo;
33310
+ sInfo.dwOSVersionInfoSize = sizeof(sInfo);
33311
+ osGetVersionExA(&sInfo);
33312
+ osInterlockedCompareExchange(&sqlite3_os_type,
33313
+ (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
33314
+#endif
33315
+ }
33316
+ return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
33317
+#elif SQLITE_TEST
33318
+ return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
3295033319
#else
32951
- OSVERSIONINFOA sInfo;
32952
- sInfo.dwOSVersionInfoSize = sizeof(sInfo);
32953
- osGetVersionExA(&sInfo);
32954
-#endif
32955
- sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
32956
- }
32957
- return sqlite3_os_type==2;
32958
- }
32959
-#endif
33320
+ return 1;
33321
+#endif
33322
+}
3296033323
3296133324
#ifdef SQLITE_WIN32_MALLOC
3296233325
/*
3296333326
** Allocate nBytes of memory.
3296433327
*/
@@ -33162,11 +33525,11 @@
3316233525
sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32());
3316333526
}
3316433527
#endif /* SQLITE_WIN32_MALLOC */
3316533528
3316633529
/*
33167
-** Convert a UTF-8 string to Microsoft Unicode (UTF-16?).
33530
+** Convert a UTF-8 string to Microsoft Unicode (UTF-16?).
3316833531
**
3316933532
** Space to hold the returned string is obtained from malloc.
3317033533
*/
3317133534
static LPWSTR winUtf8ToUnicode(const char *zFilename){
3317233535
int nChar;
@@ -33215,11 +33578,11 @@
3321533578
}
3321633579
3321733580
/*
3321833581
** Convert an ANSI string to Microsoft Unicode, based on the
3321933582
** current codepage settings for file apis.
33220
-**
33583
+**
3322133584
** Space to hold the returned string is obtained
3322233585
** from sqlite3_malloc.
3322333586
*/
3322433587
static LPWSTR winMbcsToUnicode(const char *zFilename){
3322533588
int nByte;
@@ -33289,11 +33652,11 @@
3328933652
sqlite3_free(zTmpWide);
3329033653
return zFilenameUtf8;
3329133654
}
3329233655
3329333656
/*
33294
-** Convert UTF-8 to multibyte character string. Space to hold the
33657
+** Convert UTF-8 to multibyte character string. Space to hold the
3329533658
** returned string is obtained from sqlite3_malloc().
3329633659
*/
3329733660
SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
3329833661
char *zFilenameMbcs;
3329933662
LPWSTR zTmpWide;
@@ -33429,15 +33792,15 @@
3342933792
** This function - winLogErrorAtLine() - is only ever called via the macro
3343033793
** winLogError().
3343133794
**
3343233795
** This routine is invoked after an error occurs in an OS function.
3343333796
** It logs a message using sqlite3_log() containing the current value of
33434
-** error code and, if possible, the human-readable equivalent from
33797
+** error code and, if possible, the human-readable equivalent from
3343533798
** FormatMessage.
3343633799
**
3343733800
** The first argument passed to the macro should be the error code that
33438
-** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
33801
+** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
3343933802
** The two subsequent arguments should be the name of the OS function that
3344033803
** failed and the associated file-system path, if any.
3344133804
*/
3344233805
#define winLogError(a,b,c,d) winLogErrorAtLine(a,b,c,d,__LINE__)
3344333806
static int winLogErrorAtLine(
@@ -33464,11 +33827,11 @@
3346433827
return errcode;
3346533828
}
3346633829
3346733830
/*
3346833831
** The number of times that a ReadFile(), WriteFile(), and DeleteFile()
33469
-** will be retried following a locking error - probably caused by
33832
+** will be retried following a locking error - probably caused by
3347033833
** antivirus software. Also the initial delay before the first retry.
3347133834
** The delay increases linearly with each retry.
3347233835
*/
3347333836
#ifndef SQLITE_WIN32_IOERR_RETRY
3347433837
# define SQLITE_WIN32_IOERR_RETRY 10
@@ -33539,11 +33902,11 @@
3353933902
/*
3354033903
** Log a I/O error retry episode.
3354133904
*/
3354233905
static void winLogIoerr(int nRetry){
3354333906
if( nRetry ){
33544
- sqlite3_log(SQLITE_IOERR,
33907
+ sqlite3_log(SQLITE_IOERR,
3354533908
"delayed %dms for lock/sharing conflict",
3354633909
winIoerrRetryDelay*nRetry*(nRetry+1)/2
3354733910
);
3354833911
}
3354933912
}
@@ -33633,21 +33996,21 @@
3363333996
"winceCreateLock1", zFilename);
3363433997
}
3363533998
3363633999
/* Acquire the mutex before continuing */
3363734000
winceMutexAcquire(pFile->hMutex);
33638
-
33639
- /* Since the names of named mutexes, semaphores, file mappings etc are
34001
+
34002
+ /* Since the names of named mutexes, semaphores, file mappings etc are
3364034003
** case-sensitive, take advantage of that by uppercasing the mutex name
3364134004
** and using that as the shared filemapping name.
3364234005
*/
3364334006
osCharUpperW(zName);
3364434007
pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
3364534008
PAGE_READWRITE, 0, sizeof(winceLock),
33646
- zName);
34009
+ zName);
3364734010
33648
- /* Set a flag that indicates we're the first to create the memory so it
34011
+ /* Set a flag that indicates we're the first to create the memory so it
3364934012
** must be zero-initialized */
3365034013
lastErrno = osGetLastError();
3365134014
if (lastErrno == ERROR_ALREADY_EXISTS){
3365234015
bInit = FALSE;
3365334016
}
@@ -33654,11 +34017,11 @@
3365434017
3365534018
sqlite3_free(zName);
3365634019
3365734020
/* If we succeeded in making the shared memory handle, map it. */
3365834021
if( pFile->hShared ){
33659
- pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared,
34022
+ pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared,
3366034023
FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
3366134024
/* If mapping failed, close the shared memory handle and erase it */
3366234025
if( !pFile->shared ){
3366334026
pFile->lastErrno = osGetLastError();
3366434027
winLogError(SQLITE_IOERR, pFile->lastErrno,
@@ -33680,11 +34043,11 @@
3368034043
winceMutexRelease(pFile->hMutex);
3368134044
osCloseHandle(pFile->hMutex);
3368234045
pFile->hMutex = NULL;
3368334046
return SQLITE_IOERR;
3368434047
}
33685
-
34048
+
3368634049
/* Initialize the shared memory if we're supposed to */
3368734050
if( bInit ){
3368834051
memset(pFile->shared, 0, sizeof(winceLock));
3368934052
}
3369034053
@@ -33718,17 +34081,17 @@
3371834081
/* De-reference and close our copy of the shared memory handle */
3371934082
osUnmapViewOfFile(pFile->shared);
3372034083
osCloseHandle(pFile->hShared);
3372134084
3372234085
/* Done with the mutex */
33723
- winceMutexRelease(pFile->hMutex);
34086
+ winceMutexRelease(pFile->hMutex);
3372434087
osCloseHandle(pFile->hMutex);
3372534088
pFile->hMutex = NULL;
3372634089
}
3372734090
}
3372834091
33729
-/*
34092
+/*
3373034093
** An implementation of the LockFile() API of Windows for CE
3373134094
*/
3373234095
static BOOL winceLockFile(
3373334096
LPHANDLE phFile,
3373434097
DWORD dwFileOffsetLow,
@@ -33935,12 +34298,12 @@
3393534298
#ifndef INVALID_SET_FILE_POINTER
3393634299
# define INVALID_SET_FILE_POINTER ((DWORD)-1)
3393734300
#endif
3393834301
3393934302
/*
33940
-** Move the current position of the file handle passed as the first
33941
-** argument to offset iOffset within the file. If successful, return 0.
34303
+** Move the current position of the file handle passed as the first
34304
+** argument to offset iOffset within the file. If successful, return 0.
3394234305
** Otherwise, set pFile->lastErrno and return non-zero.
3394334306
*/
3394434307
static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){
3394534308
#if !SQLITE_OS_WINRT
3394634309
LONG upperBits; /* Most sig. 32 bits of new offset */
@@ -33951,15 +34314,15 @@
3395134314
OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset));
3395234315
3395334316
upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
3395434317
lowerBits = (LONG)(iOffset & 0xffffffff);
3395534318
33956
- /* API oddity: If successful, SetFilePointer() returns a dword
34319
+ /* API oddity: If successful, SetFilePointer() returns a dword
3395734320
** containing the lower 32-bits of the new file-offset. Or, if it fails,
33958
- ** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
33959
- ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
33960
- ** whether an error has actually occurred, it is also necessary to call
34321
+ ** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
34322
+ ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
34323
+ ** whether an error has actually occurred, it is also necessary to call
3396134324
** GetLastError().
3396234325
*/
3396334326
dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
3396434327
3396534328
if( (dwRet==INVALID_SET_FILE_POINTER
@@ -34038,11 +34401,11 @@
3403834401
winceDestroyLock(pFile);
3403934402
if( pFile->zDeleteOnClose ){
3404034403
int cnt = 0;
3404134404
while(
3404234405
osDeleteFileW(pFile->zDeleteOnClose)==0
34043
- && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
34406
+ && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
3404434407
&& cnt++ < WINCE_DELETION_ATTEMPTS
3404534408
){
3404634409
sqlite3_win32_sleep(100); /* Wait a little before trying again */
3404734410
}
3404834411
sqlite3_free(pFile->zDeleteOnClose);
@@ -34886,11 +35249,11 @@
3488635249
winFile *p = (winFile*)id;
3488735250
return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
3488835251
((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
3488935252
}
3489035253
34891
-/*
35254
+/*
3489235255
** Windows will only let you create file view mappings
3489335256
** on allocation size granularity boundaries.
3489435257
** During sqlite3_os_init() we do a GetSystemInfo()
3489535258
** to get the granularity size.
3489635259
*/
@@ -34898,15 +35261,15 @@
3489835261
3489935262
#ifndef SQLITE_OMIT_WAL
3490035263
3490135264
/*
3490235265
** Helper functions to obtain and relinquish the global mutex. The
34903
-** global mutex is used to protect the winLockInfo objects used by
35266
+** global mutex is used to protect the winLockInfo objects used by
3490435267
** this file, all of which may be shared by multiple threads.
3490535268
**
34906
-** Function winShmMutexHeld() is used to assert() that the global mutex
34907
-** is held when required. This function is only used as part of assert()
35269
+** Function winShmMutexHeld() is used to assert() that the global mutex
35270
+** is held when required. This function is only used as part of assert()
3490835271
** statements. e.g.
3490935272
**
3491035273
** winShmEnterMutex()
3491135274
** assert( winShmMutexHeld() );
3491235275
** winShmLeaveMutex()
@@ -34932,14 +35295,14 @@
3493235295
**
3493335296
** winShmMutexHeld() must be true when creating or destroying
3493435297
** this object or while reading or writing the following fields:
3493535298
**
3493635299
** nRef
34937
-** pNext
35300
+** pNext
3493835301
**
3493935302
** The following fields are read-only after the object is created:
34940
-**
35303
+**
3494135304
** fid
3494235305
** zFilename
3494335306
**
3494435307
** Either winShmNode.mutex must be held or winShmNode.nRef==0 and
3494535308
** winShmMutexHeld() is true when reading or writing any other field
@@ -35031,11 +35394,11 @@
3503135394
/* Initialize the locking parameters */
3503235395
DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
3503335396
if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
3503435397
rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0);
3503535398
}
35036
-
35399
+
3503735400
if( rc!= 0 ){
3503835401
rc = SQLITE_OK;
3503935402
}else{
3504035403
pFile->lastErrno = osGetLastError();
3504135404
rc = SQLITE_BUSY;
@@ -35127,11 +35490,11 @@
3512735490
sqlite3_free(p);
3512835491
return SQLITE_IOERR_NOMEM;
3512935492
}
3513035493
pNew->zFilename = (char*)&pNew[1];
3513135494
sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
35132
- sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
35495
+ sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
3513335496
3513435497
/* Look to see if there is an existing winShmNode that can be used.
3513535498
** If no matching winShmNode currently exists, create a new one.
3513635499
*/
3513735500
winShmEnterMutex();
@@ -35164,11 +35527,11 @@
3516435527
if( SQLITE_OK!=rc ){
3516535528
goto shm_open_err;
3516635529
}
3516735530
3516835531
/* Check to see if another process is holding the dead-man switch.
35169
- ** If not, truncate the file to zero length.
35532
+ ** If not, truncate the file to zero length.
3517035533
*/
3517135534
if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
3517235535
rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
3517335536
if( rc!=SQLITE_OK ){
3517435537
rc = winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
@@ -35193,11 +35556,11 @@
3519335556
3519435557
/* The reference count on pShmNode has already been incremented under
3519535558
** the cover of the winShmEnterMutex() mutex and the pointer from the
3519635559
** new (struct winShm) object to the pShmNode has been set. All that is
3519735560
** left to do is to link the new object into the linked list starting
35198
- ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
35561
+ ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
3519935562
** mutex.
3520035563
*/
3520135564
sqlite3_mutex_enter(pShmNode->mutex);
3520235565
p->pNext = pShmNode->pFirst;
3520335566
pShmNode->pFirst = p;
@@ -35213,11 +35576,11 @@
3521335576
winShmLeaveMutex();
3521435577
return rc;
3521535578
}
3521635579
3521735580
/*
35218
-** Close a connection to shared-memory. Delete the underlying
35581
+** Close a connection to shared-memory. Delete the underlying
3521935582
** storage if deleteFlag is true.
3522035583
*/
3522135584
static int winShmUnmap(
3522235585
sqlite3_file *fd, /* Database holding shared memory */
3522335586
int deleteFlag /* Delete after closing if true */
@@ -35302,11 +35665,11 @@
3530235665
3530335666
/* Undo the local locks */
3530435667
if( rc==SQLITE_OK ){
3530535668
p->exclMask &= ~mask;
3530635669
p->sharedMask &= ~mask;
35307
- }
35670
+ }
3530835671
}else if( flags & SQLITE_SHM_SHARED ){
3530935672
u16 allShared = 0; /* Union of locks held by connections other than "p" */
3531035673
3531135674
/* Find out which shared locks are already held by sibling connections.
3531235675
** If any sibling already holds an exclusive lock, go ahead and return
@@ -35341,11 +35704,11 @@
3534135704
if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
3534235705
rc = SQLITE_BUSY;
3534335706
break;
3534435707
}
3534535708
}
35346
-
35709
+
3534735710
/* Get the exclusive locks at the system level. Then if successful
3534835711
** also mark the local connection as being locked.
3534935712
*/
3535035713
if( rc==SQLITE_OK ){
3535135714
rc = winShmSystemLock(pShmNode, _SHM_WRLCK, ofst+WIN_SHM_BASE, n);
@@ -35361,11 +35724,11 @@
3536135724
sqlite3ErrName(rc)));
3536235725
return rc;
3536335726
}
3536435727
3536535728
/*
35366
-** Implement a memory barrier or memory fence on shared memory.
35729
+** Implement a memory barrier or memory fence on shared memory.
3536735730
**
3536835731
** All loads and stores begun before the barrier must complete before
3536935732
** any load or store begun after the barrier.
3537035733
*/
3537135734
static void winShmBarrier(
@@ -35376,26 +35739,26 @@
3537635739
winShmEnterMutex();
3537735740
winShmLeaveMutex();
3537835741
}
3537935742
3538035743
/*
35381
-** This function is called to obtain a pointer to region iRegion of the
35382
-** shared-memory associated with the database file fd. Shared-memory regions
35383
-** are numbered starting from zero. Each shared-memory region is szRegion
35744
+** This function is called to obtain a pointer to region iRegion of the
35745
+** shared-memory associated with the database file fd. Shared-memory regions
35746
+** are numbered starting from zero. Each shared-memory region is szRegion
3538435747
** bytes in size.
3538535748
**
3538635749
** If an error occurs, an error code is returned and *pp is set to NULL.
3538735750
**
3538835751
** Otherwise, if the isWrite parameter is 0 and the requested shared-memory
3538935752
** region has not been allocated (by any client, including one running in a
35390
-** separate process), then *pp is set to NULL and SQLITE_OK returned. If
35391
-** isWrite is non-zero and the requested shared-memory region has not yet
35753
+** separate process), then *pp is set to NULL and SQLITE_OK returned. If
35754
+** isWrite is non-zero and the requested shared-memory region has not yet
3539235755
** been allocated, it is allocated by this function.
3539335756
**
3539435757
** If the shared-memory region has already been allocated or is allocated by
35395
-** this call as described above, then it is mapped into this processes
35396
-** address space (if it is not already), *pp is set to point to the mapped
35758
+** this call as described above, then it is mapped into this processes
35759
+** address space (if it is not already), *pp is set to point to the mapped
3539735760
** memory and SQLITE_OK returned.
3539835761
*/
3539935762
static int winShmMap(
3540035763
sqlite3_file *fd, /* Handle open on database file */
3540135764
int iRegion, /* Region to retrieve */
@@ -35463,21 +35826,21 @@
3546335826
pShmNode->aRegion = apNew;
3546435827
3546535828
while( pShmNode->nRegion<=iRegion ){
3546635829
HANDLE hMap = NULL; /* file-mapping handle */
3546735830
void *pMap = 0; /* Mapped memory region */
35468
-
35831
+
3546935832
#if SQLITE_OS_WINRT
3547035833
hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
3547135834
NULL, PAGE_READWRITE, nByte, NULL
3547235835
);
3547335836
#elif defined(SQLITE_WIN32_HAS_WIDE)
35474
- hMap = osCreateFileMappingW(pShmNode->hFile.h,
35837
+ hMap = osCreateFileMappingW(pShmNode->hFile.h,
3547535838
NULL, PAGE_READWRITE, 0, nByte, NULL
3547635839
);
3547735840
#elif defined(SQLITE_WIN32_HAS_ANSI)
35478
- hMap = osCreateFileMappingA(pShmNode->hFile.h,
35841
+ hMap = osCreateFileMappingA(pShmNode->hFile.h,
3547935842
NULL, PAGE_READWRITE, 0, nByte, NULL
3548035843
);
3548135844
#endif
3548235845
OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
3548335846
osGetCurrentProcessId(), pShmNode->nRegion, nByte,
@@ -35570,18 +35933,18 @@
3557035933
return SQLITE_OK;
3557135934
}
3557235935
3557335936
/*
3557435937
** Memory map or remap the file opened by file-descriptor pFd (if the file
35575
-** is already mapped, the existing mapping is replaced by the new). Or, if
35576
-** there already exists a mapping for this file, and there are still
35938
+** is already mapped, the existing mapping is replaced by the new). Or, if
35939
+** there already exists a mapping for this file, and there are still
3557735940
** outstanding xFetch() references to it, this function is a no-op.
3557835941
**
35579
-** If parameter nByte is non-negative, then it is the requested size of
35580
-** the mapping to create. Otherwise, if nByte is less than zero, then the
35942
+** If parameter nByte is non-negative, then it is the requested size of
35943
+** the mapping to create. Otherwise, if nByte is less than zero, then the
3558135944
** requested size is the size of the file on disk. The actual size of the
35582
-** created mapping is either the requested size or the value configured
35945
+** created mapping is either the requested size or the value configured
3558335946
** using SQLITE_FCNTL_MMAP_SIZE, whichever is smaller.
3558435947
**
3558535948
** SQLITE_OK is returned if no error occurs (even if the mapping is not
3558635949
** recreated as a result of outstanding references) or an SQLite error
3558735950
** code otherwise.
@@ -35606,11 +35969,11 @@
3560635969
}
3560735970
if( nMap>pFd->mmapSizeMax ){
3560835971
nMap = pFd->mmapSizeMax;
3560935972
}
3561035973
nMap &= ~(sqlite3_int64)(winSysInfo.dwPageSize - 1);
35611
-
35974
+
3561235975
if( nMap==0 && pFd->mmapSize>0 ){
3561335976
winUnmapfile(pFd);
3561435977
}
3561535978
if( nMap!=pFd->mmapSize ){
3561635979
void *pNew = 0;
@@ -35678,11 +36041,11 @@
3567836041
** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
3567936042
** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
3568036043
** Finally, if an error does occur, return an SQLite error code. The final
3568136044
** value of *pp is undefined in this case.
3568236045
**
35683
-** If this function does return a pointer, the caller must eventually
36046
+** If this function does return a pointer, the caller must eventually
3568436047
** release the reference by calling winUnfetch().
3568536048
*/
3568636049
static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
3568736050
#if SQLITE_MAX_MMAP_SIZE>0
3568836051
winFile *pFd = (winFile*)fd; /* The underlying database file */
@@ -35713,24 +36076,24 @@
3571336076
osGetCurrentProcessId(), fd, pp, *pp));
3571436077
return SQLITE_OK;
3571536078
}
3571636079
3571736080
/*
35718
-** If the third argument is non-NULL, then this function releases a
36081
+** If the third argument is non-NULL, then this function releases a
3571936082
** reference obtained by an earlier call to winFetch(). The second
3572036083
** argument passed to this function must be the same as the corresponding
35721
-** argument that was passed to the winFetch() invocation.
36084
+** argument that was passed to the winFetch() invocation.
3572236085
**
35723
-** Or, if the third argument is NULL, then this function is being called
35724
-** to inform the VFS layer that, according to POSIX, any existing mapping
36086
+** Or, if the third argument is NULL, then this function is being called
36087
+** to inform the VFS layer that, according to POSIX, any existing mapping
3572536088
** may now be invalid and should be unmapped.
3572636089
*/
3572736090
static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){
3572836091
#if SQLITE_MAX_MMAP_SIZE>0
3572936092
winFile *pFd = (winFile*)fd; /* The underlying database file */
3573036093
35731
- /* If p==0 (unmap the entire file) then there must be no outstanding
36094
+ /* If p==0 (unmap the entire file) then there must be no outstanding
3573236095
** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
3573336096
** then there must be at least one outstanding. */
3573436097
assert( (p==0)==(pFd->nFetchOut==0) );
3573536098
3573636099
/* If p!=0, it must match the iOff value. */
@@ -35872,11 +36235,11 @@
3587236235
int nMax, nBuf, nDir, nLen;
3587336236
char *zBuf;
3587436237
3587536238
/* It's odd to simulate an io-error here, but really this is just
3587636239
** using the io-error infrastructure to test that SQLite handles this
35877
- ** function failing.
36240
+ ** function failing.
3587836241
*/
3587936242
SimulateIOError( return SQLITE_IOERR );
3588036243
3588136244
/* Allocate a temporary buffer to store the fully qualified file
3588236245
** name for the temporary file. If this fails, we cannot continue.
@@ -36054,11 +36417,11 @@
3605436417
OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
3605536418
return winLogError(SQLITE_ERROR, 0, "winGetTempname4", 0);
3605636419
}
3605736420
3605836421
/*
36059
- ** Check that the output buffer is large enough for the temporary file
36422
+ ** Check that the output buffer is large enough for the temporary file
3606036423
** name in the following format:
3606136424
**
3606236425
** "<temporary_directory>/etilqs_XXXXXXXXXXXXXXX\0\0"
3606336426
**
3606436427
** If not, return SQLITE_ERROR. The number 17 is used here in order to
@@ -36157,42 +36520,42 @@
3615736520
int isReadonly = (flags & SQLITE_OPEN_READONLY);
3615836521
int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
3615936522
3616036523
#ifndef NDEBUG
3616136524
int isOpenJournal = (isCreate && (
36162
- eType==SQLITE_OPEN_MASTER_JOURNAL
36163
- || eType==SQLITE_OPEN_MAIN_JOURNAL
36525
+ eType==SQLITE_OPEN_MASTER_JOURNAL
36526
+ || eType==SQLITE_OPEN_MAIN_JOURNAL
3616436527
|| eType==SQLITE_OPEN_WAL
3616536528
));
3616636529
#endif
3616736530
3616836531
OSTRACE(("OPEN name=%s, pFile=%p, flags=%x, pOutFlags=%p\n",
3616936532
zUtf8Name, id, flags, pOutFlags));
3617036533
36171
- /* Check the following statements are true:
36534
+ /* Check the following statements are true:
3617236535
**
36173
- ** (a) Exactly one of the READWRITE and READONLY flags must be set, and
36536
+ ** (a) Exactly one of the READWRITE and READONLY flags must be set, and
3617436537
** (b) if CREATE is set, then READWRITE must also be set, and
3617536538
** (c) if EXCLUSIVE is set, then CREATE must also be set.
3617636539
** (d) if DELETEONCLOSE is set, then CREATE must also be set.
3617736540
*/
3617836541
assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
3617936542
assert(isCreate==0 || isReadWrite);
3618036543
assert(isExclusive==0 || isCreate);
3618136544
assert(isDelete==0 || isCreate);
3618236545
36183
- /* The main DB, main journal, WAL file and master journal are never
36546
+ /* The main DB, main journal, WAL file and master journal are never
3618436547
** automatically deleted. Nor are they ever temporary files. */
3618536548
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
3618636549
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
3618736550
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
3618836551
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
3618936552
3619036553
/* Assert that the upper layer has set one of the "file-type" flags. */
36191
- assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
36192
- || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
36193
- || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
36554
+ assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
36555
+ || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
36556
+ || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
3619436557
|| eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
3619536558
);
3619636559
3619736560
assert( pFile!=0 );
3619836561
memset(pFile, 0, sizeof(winFile));
@@ -36203,12 +36566,12 @@
3620336566
sqlite3_log(SQLITE_ERROR,
3620436567
"sqlite3_temp_directory variable should be set for WinRT");
3620536568
}
3620636569
#endif
3620736570
36208
- /* If the second argument to this function is NULL, generate a
36209
- ** temporary file name to use
36571
+ /* If the second argument to this function is NULL, generate a
36572
+ ** temporary file name to use
3621036573
*/
3621136574
if( !zUtf8Name ){
3621236575
assert( isDelete && !isOpenJournal );
3621336576
rc = winGetTempname(pVfs, &zTmpname);
3621436577
if( rc!=SQLITE_OK ){
@@ -36244,12 +36607,12 @@
3624436607
dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
3624536608
}else{
3624636609
dwDesiredAccess = GENERIC_READ;
3624736610
}
3624836611
36249
- /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is
36250
- ** created. SQLite doesn't use it to indicate "exclusive access"
36612
+ /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is
36613
+ ** created. SQLite doesn't use it to indicate "exclusive access"
3625136614
** as it is usually understood.
3625236615
*/
3625336616
if( isExclusive ){
3625436617
/* Creates a new file, only if it does not already exist. */
3625536618
/* If the file exists, it fails. */
@@ -36334,11 +36697,11 @@
3633436697
pFile->lastErrno = lastErrno;
3633536698
winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name);
3633636699
sqlite3_free(zConverted);
3633736700
sqlite3_free(zTmpname);
3633836701
if( isReadWrite && !isExclusive ){
36339
- return winOpen(pVfs, zName, id,
36702
+ return winOpen(pVfs, zName, id,
3634036703
((flags|SQLITE_OPEN_READONLY) &
3634136704
~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
3634236705
pOutFlags);
3634336706
}else{
3634436707
return SQLITE_CANTOPEN_BKPT;
@@ -36543,18 +36906,18 @@
3654336906
if( osIsNT() ){
3654436907
int cnt = 0;
3654536908
WIN32_FILE_ATTRIBUTE_DATA sAttrData;
3654636909
memset(&sAttrData, 0, sizeof(sAttrData));
3654736910
while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
36548
- GetFileExInfoStandard,
36911
+ GetFileExInfoStandard,
3654936912
&sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){}
3655036913
if( rc ){
3655136914
/* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
3655236915
** as if it does not exist.
3655336916
*/
3655436917
if( flags==SQLITE_ACCESS_EXISTS
36555
- && sAttrData.nFileSizeHigh==0
36918
+ && sAttrData.nFileSizeHigh==0
3655636919
&& sAttrData.nFileSizeLow==0 ){
3655736920
attr = INVALID_FILE_ATTRIBUTES;
3655836921
}else{
3655936922
attr = sAttrData.dwFileAttributes;
3656036923
}
@@ -36649,11 +37012,11 @@
3664937012
sqlite3_vfs *pVfs, /* Pointer to vfs object */
3665037013
const char *zRelative, /* Possibly relative input path */
3665137014
int nFull, /* Size of output buffer in bytes */
3665237015
char *zFull /* Output buffer */
3665337016
){
36654
-
37017
+
3665537018
#if defined(__CYGWIN__)
3665637019
SimulateIOError( return SQLITE_ERROR );
3665737020
UNUSED_PARAMETER(nFull);
3665837021
assert( nFull>=pVfs->mxPathname );
3665937022
if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
@@ -36962,24 +37325,24 @@
3696237325
** the current time and date as a Julian Day number times 86_400_000. In
3696337326
** other words, write into *piNow the number of milliseconds since the Julian
3696437327
** epoch of noon in Greenwich on November 24, 4714 B.C according to the
3696537328
** proleptic Gregorian calendar.
3696637329
**
36967
-** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
37330
+** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
3696837331
** cannot be found.
3696937332
*/
3697037333
static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
36971
- /* FILETIME structure is a 64-bit value representing the number of
36972
- 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
37334
+ /* FILETIME structure is a 64-bit value representing the number of
37335
+ 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
3697337336
*/
3697437337
FILETIME ft;
3697537338
static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000;
3697637339
#ifdef SQLITE_TEST
3697737340
static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
3697837341
#endif
3697937342
/* 2^32 - to avoid use of LL and warnings in gcc */
36980
- static const sqlite3_int64 max32BitValue =
37343
+ static const sqlite3_int64 max32BitValue =
3698137344
(sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 +
3698237345
(sqlite3_int64)294967296;
3698337346
3698437347
#if SQLITE_OS_WINCE
3698537348
SYSTEMTIME time;
@@ -36991,11 +37354,11 @@
3699137354
#else
3699237355
osGetSystemTimeAsFileTime( &ft );
3699337356
#endif
3699437357
3699537358
*piNow = winFiletimeEpoch +
36996
- ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) +
37359
+ ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) +
3699737360
(sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000;
3699837361
3699937362
#ifdef SQLITE_TEST
3700037363
if( sqlite3_current_time ){
3700137364
*piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
@@ -37110,11 +37473,11 @@
3711037473
};
3711137474
#endif
3711237475
3711337476
/* Double-check that the aSyscall[] array has been constructed
3711437477
** correctly. See ticket [bb3a86e890c8e96ab] */
37115
- assert( ArraySize(aSyscall)==76 );
37478
+ assert( ArraySize(aSyscall)==77 );
3711637479
3711737480
/* get memory map allocation granularity */
3711837481
memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
3711937482
#if SQLITE_OS_WINRT
3712037483
osGetNativeSystemInfo(&winSysInfo);
@@ -37128,14 +37491,14 @@
3712837491
3712937492
#if defined(SQLITE_WIN32_HAS_WIDE)
3713037493
sqlite3_vfs_register(&winLongPathVfs, 0);
3713137494
#endif
3713237495
37133
- return SQLITE_OK;
37496
+ return SQLITE_OK;
3713437497
}
3713537498
37136
-SQLITE_API int sqlite3_os_end(void){
37499
+SQLITE_API int sqlite3_os_end(void){
3713737500
#if SQLITE_OS_WINRT
3713837501
if( sleepObj!=NULL ){
3713937502
osCloseHandle(sleepObj);
3714037503
sleepObj = NULL;
3714137504
}
@@ -51332,11 +51695,11 @@
5133251695
/* If the client is reading or writing an index and the schema is
5133351696
** not loaded, then it is too difficult to actually check to see if
5133451697
** the correct locks are held. So do not bother - just return true.
5133551698
** This case does not come up very often anyhow.
5133651699
*/
51337
- if( isIndex && (!pSchema || (pSchema->flags&DB_SchemaLoaded)==0) ){
51700
+ if( isIndex && (!pSchema || (pSchema->schemaFlags&DB_SchemaLoaded)==0) ){
5133851701
return 1;
5133951702
}
5134051703
5134151704
/* Figure out the root-page that the lock should be held on. For table
5134251705
** b-trees, this is just the root page of the b-tree being read or
@@ -52802,11 +53165,11 @@
5280253165
return pBt->nPage;
5280353166
}
5280453167
SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree *p){
5280553168
assert( sqlite3BtreeHoldsMutex(p) );
5280653169
assert( ((p->pBt->nPage)&0x8000000)==0 );
52807
- return (int)btreePagecount(p->pBt);
53170
+ return btreePagecount(p->pBt);
5280853171
}
5280953172
5281053173
/*
5281153174
** Get a page from the pager and initialize it. This routine is just a
5281253175
** convenience wrapper around separate calls to btreeGetPage() and
@@ -61928,22 +62291,39 @@
6192862291
pB->zSql = zTmp;
6192962292
pB->isPrepareV2 = pA->isPrepareV2;
6193062293
}
6193162294
6193262295
/*
61933
-** Resize the Vdbe.aOp array so that it is at least one op larger than
61934
-** it was.
62296
+** Resize the Vdbe.aOp array so that it is at least nOp elements larger
62297
+** than its current size. nOp is guaranteed to be less than or equal
62298
+** to 1024/sizeof(Op).
6193562299
**
6193662300
** If an out-of-memory error occurs while resizing the array, return
61937
-** SQLITE_NOMEM. In this case Vdbe.aOp and Vdbe.nOpAlloc remain
62301
+** SQLITE_NOMEM. In this case Vdbe.aOp and Parse.nOpAlloc remain
6193862302
** unchanged (this is so that any opcodes already allocated can be
6193962303
** correctly deallocated along with the rest of the Vdbe).
6194062304
*/
61941
-static int growOpArray(Vdbe *v){
62305
+static int growOpArray(Vdbe *v, int nOp){
6194262306
VdbeOp *pNew;
6194362307
Parse *p = v->pParse;
62308
+
62309
+ /* The SQLITE_TEST_REALLOC_STRESS compile-time option is designed to force
62310
+ ** more frequent reallocs and hence provide more opportunities for
62311
+ ** simulated OOM faults. SQLITE_TEST_REALLOC_STRESS is generally used
62312
+ ** during testing only. With SQLITE_TEST_REALLOC_STRESS grow the op array
62313
+ ** by the minimum* amount required until the size reaches 512. Normal
62314
+ ** operation (without SQLITE_TEST_REALLOC_STRESS) is to double the current
62315
+ ** size of the op array or add 1KB of space, whichever is smaller. */
62316
+#ifdef SQLITE_TEST_REALLOC_STRESS
62317
+ int nNew = (p->nOpAlloc>=512 ? p->nOpAlloc*2 : p->nOpAlloc+nOp);
62318
+#else
6194462319
int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op)));
62320
+ UNUSED_PARAMETER(nOp);
62321
+#endif
62322
+
62323
+ assert( nOp<=(1024/sizeof(Op)) );
62324
+ assert( nNew>=(p->nOpAlloc+nOp) );
6194562325
pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
6194662326
if( pNew ){
6194762327
p->nOpAlloc = sqlite3DbMallocSize(p->db, pNew)/sizeof(Op);
6194862328
v->aOp = pNew;
6194962329
}
@@ -61983,11 +62363,11 @@
6198362363
6198462364
i = p->nOp;
6198562365
assert( p->magic==VDBE_MAGIC_INIT );
6198662366
assert( op>0 && op<0xff );
6198762367
if( p->pParse->nOpAlloc<=i ){
61988
- if( growOpArray(p) ){
62368
+ if( growOpArray(p, 1) ){
6198962369
return 1;
6199062370
}
6199162371
}
6199262372
p->nOp++;
6199362373
pOp = &p->aOp[i];
@@ -62343,11 +62723,11 @@
6234362723
}
6234462724
sqlite3DbFree(p->db, pParse->aLabel);
6234562725
pParse->aLabel = 0;
6234662726
pParse->nLabel = 0;
6234762727
*pMaxFuncArgs = nMaxArgs;
62348
- assert( p->bIsReader!=0 || p->btreeMask==0 );
62728
+ assert( p->bIsReader!=0 || DbMaskAllZero(p->btreeMask) );
6234962729
}
6235062730
6235162731
/*
6235262732
** Return the address of the next instruction to be inserted.
6235362733
*/
@@ -62370,11 +62750,11 @@
6237062750
SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){
6237162751
VdbeOp *aOp = p->aOp;
6237262752
assert( aOp && !p->db->mallocFailed );
6237362753
6237462754
/* Check that sqlite3VdbeUsesBtree() was not called on this VM */
62375
- assert( p->btreeMask==0 );
62755
+ assert( DbMaskAllZero(p->btreeMask) );
6237662756
6237762757
resolveP2Values(p, pnMaxArg);
6237862758
*pnOp = p->nOp;
6237962759
p->aOp = 0;
6238062760
return aOp;
@@ -62385,11 +62765,11 @@
6238562765
** address of the first operation added.
6238662766
*/
6238762767
SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp, int iLineno){
6238862768
int addr;
6238962769
assert( p->magic==VDBE_MAGIC_INIT );
62390
- if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p) ){
62770
+ if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p, nOp) ){
6239162771
return 0;
6239262772
}
6239362773
addr = p->nOp;
6239462774
if( ALWAYS(nOp>0) ){
6239562775
int i;
@@ -62570,11 +62950,11 @@
6257062950
6257162951
/*
6257262952
** Change the opcode at addr into OP_Noop
6257362953
*/
6257462954
SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
62575
- if( p->aOp ){
62955
+ if( addr<p->nOp ){
6257662956
VdbeOp *pOp = &p->aOp[addr];
6257762957
sqlite3 *db = p->db;
6257862958
freeP4(db, pOp->p4type, pOp->p4.p);
6257962959
memset(pOp, 0, sizeof(pOp[0]));
6258062960
pOp->opcode = OP_Noop;
@@ -62955,13 +63335,13 @@
6295563335
** p->btreeMask of databases that will require a lock.
6295663336
*/
6295763337
SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe *p, int i){
6295863338
assert( i>=0 && i<p->db->nDb && i<(int)sizeof(yDbMask)*8 );
6295963339
assert( i<(int)sizeof(p->btreeMask)*8 );
62960
- p->btreeMask |= ((yDbMask)1)<<i;
63340
+ DbMaskSet(p->btreeMask, i);
6296163341
if( i!=1 && sqlite3BtreeSharable(p->db->aDb[i].pBt) ){
62962
- p->lockMask |= ((yDbMask)1)<<i;
63342
+ DbMaskSet(p->lockMask, i);
6296363343
}
6296463344
}
6296563345
6296663346
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
6296763347
/*
@@ -62985,20 +63365,19 @@
6298563365
** this routine is N*N. But as N is rarely more than 1, this should not
6298663366
** be a problem.
6298763367
*/
6298863368
SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe *p){
6298963369
int i;
62990
- yDbMask mask;
6299163370
sqlite3 *db;
6299263371
Db *aDb;
6299363372
int nDb;
62994
- if( p->lockMask==0 ) return; /* The common case */
63373
+ if( DbMaskAllZero(p->lockMask) ) return; /* The common case */
6299563374
db = p->db;
6299663375
aDb = db->aDb;
6299763376
nDb = db->nDb;
62998
- for(i=0, mask=1; i<nDb; i++, mask += mask){
62999
- if( i!=1 && (mask & p->lockMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){
63377
+ for(i=0; i<nDb; i++){
63378
+ if( i!=1 && DbMaskTest(p->lockMask,i) && ALWAYS(aDb[i].pBt!=0) ){
6300063379
sqlite3BtreeEnter(aDb[i].pBt);
6300163380
}
6300263381
}
6300363382
}
6300463383
#endif
@@ -63007,20 +63386,19 @@
6300763386
/*
6300863387
** Unlock all of the btrees previously locked by a call to sqlite3VdbeEnter().
6300963388
*/
6301063389
SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe *p){
6301163390
int i;
63012
- yDbMask mask;
6301363391
sqlite3 *db;
6301463392
Db *aDb;
6301563393
int nDb;
63016
- if( p->lockMask==0 ) return; /* The common case */
63394
+ if( DbMaskAllZero(p->lockMask) ) return; /* The common case */
6301763395
db = p->db;
6301863396
aDb = db->aDb;
6301963397
nDb = db->nDb;
63020
- for(i=0, mask=1; i<nDb; i++, mask += mask){
63021
- if( i!=1 && (mask & p->lockMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){
63398
+ for(i=0; i<nDb; i++){
63399
+ if( i!=1 && DbMaskTest(p->lockMask,i) && ALWAYS(aDb[i].pBt!=0) ){
6302263400
sqlite3BtreeLeave(aDb[i].pBt);
6302363401
}
6302463402
}
6302563403
}
6302663404
#endif
@@ -63987,11 +64365,11 @@
6398764365
int cnt = 0;
6398864366
int nWrite = 0;
6398964367
int nRead = 0;
6399064368
p = db->pVdbe;
6399164369
while( p ){
63992
- if( p->magic==VDBE_MAGIC_RUN && p->pc>=0 ){
64370
+ if( sqlite3_stmt_busy((sqlite3_stmt*)p) ){
6399364371
cnt++;
6399464372
if( p->readOnly==0 ) nWrite++;
6399564373
if( p->bIsReader ) nRead++;
6399664374
}
6399764375
p = p->pNext;
@@ -64147,11 +64525,10 @@
6414764525
/* Lock all btrees used by the statement */
6414864526
sqlite3VdbeEnter(p);
6414964527
6415064528
/* Check for one of the special errors */
6415164529
mrc = p->rc & 0xff;
64152
- assert( p->rc!=SQLITE_IOERR_BLOCKED ); /* This error no longer exists */
6415364530
isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR
6415464531
|| mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL;
6415564532
if( isSpecialError ){
6415664533
/* If the query was read-only and the error code is SQLITE_INTERRUPT,
6415764534
** no rollback is necessary. Otherwise, at least a savepoint
@@ -64632,11 +65009,11 @@
6463265009
/*
6463365010
** Return the serial-type for the value stored in pMem.
6463465011
*/
6463565012
SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
6463665013
int flags = pMem->flags;
64637
- int n;
65014
+ u32 n;
6463865015
6463965016
if( flags&MEM_Null ){
6464065017
return 0;
6464165018
}
6464265019
if( flags&MEM_Int ){
@@ -64662,15 +65039,15 @@
6466265039
}
6466365040
if( flags&MEM_Real ){
6466465041
return 7;
6466565042
}
6466665043
assert( pMem->db->mallocFailed || flags&(MEM_Str|MEM_Blob) );
64667
- n = pMem->n;
65044
+ assert( pMem->n>=0 );
65045
+ n = (u32)pMem->n;
6466865046
if( flags & MEM_Zero ){
6466965047
n += pMem->u.nZero;
6467065048
}
64671
- assert( n>=0 );
6467265049
return ((n*2) + 12 + ((flags&MEM_Str)!=0));
6467365050
}
6467465051
6467565052
/*
6467665053
** Return the length of the data corresponding to the supplied serial-type.
@@ -67184,11 +67561,11 @@
6718467561
/*
6718567562
** Return true if the prepared statement is in need of being reset.
6718667563
*/
6718767564
SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
6718867565
Vdbe *v = (Vdbe*)pStmt;
67189
- return v!=0 && v->pc>0 && v->magic==VDBE_MAGIC_RUN;
67566
+ return v!=0 && v->pc>=0 && v->magic==VDBE_MAGIC_RUN;
6719067567
}
6719167568
6719267569
/*
6719367570
** Return a pointer to the next prepared statement after pStmt associated
6719467571
** with database connection pDb. If pStmt is NULL, return the first
@@ -67634,10 +68011,16 @@
6763468011
**
6763568012
** M is an integer, 2 or 3, that indices how many different ways the
6763668013
** branch can go. It is usually 2. "I" is the direction the branch
6763768014
** goes. 0 means falls through. 1 means branch is taken. 2 means the
6763868015
** second alternative branch is taken.
68016
+**
68017
+** iSrcLine is the source code line (from the __LINE__ macro) that
68018
+** generated the VDBE instruction. This instrumentation assumes that all
68019
+** source code is in a single file (the amalgamation). Special values 1
68020
+** and 2 for the iSrcLine parameter mean that this particular branch is
68021
+** always taken or never taken, respectively.
6763968022
*/
6764068023
#if !defined(SQLITE_VDBE_COVERAGE)
6764168024
# define VdbeBranchTaken(I,M)
6764268025
#else
6764368026
# define VdbeBranchTaken(I,M) vdbeTakeBranch(pOp->iSrcLine,I,M)
@@ -67742,25 +68125,25 @@
6774268125
** do so without loss of information. In other words, if the string
6774368126
** looks like a number, convert it into a number. If it does not
6774468127
** look like a number, leave it alone.
6774568128
*/
6774668129
static void applyNumericAffinity(Mem *pRec){
67747
- if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){
67748
- double rValue;
67749
- i64 iValue;
67750
- u8 enc = pRec->enc;
67751
- if( (pRec->flags&MEM_Str)==0 ) return;
67752
- if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return;
67753
- if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){
67754
- pRec->u.i = iValue;
67755
- pRec->flags |= MEM_Int;
67756
- }else{
67757
- pRec->r = rValue;
67758
- pRec->flags |= MEM_Real;
67759
- }
67760
- }
67761
-}
68130
+ double rValue;
68131
+ i64 iValue;
68132
+ u8 enc = pRec->enc;
68133
+ if( (pRec->flags&MEM_Str)==0 ) return;
68134
+ if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return;
68135
+ if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){
68136
+ pRec->u.i = iValue;
68137
+ pRec->flags |= MEM_Int;
68138
+ }else{
68139
+ pRec->r = rValue;
68140
+ pRec->flags |= MEM_Real;
68141
+ }
68142
+}
68143
+#define ApplyNumericAffinity(X) \
68144
+ if(((X)->flags&(MEM_Real|MEM_Int))==0){applyNumericAffinity(X);}
6776268145
6776368146
/*
6776468147
** Processing is determine by the affinity parameter:
6776568148
**
6776668149
** SQLITE_AFF_INTEGER:
@@ -67793,11 +68176,11 @@
6779368176
}
6779468177
pRec->flags &= ~(MEM_Real|MEM_Int);
6779568178
}else if( affinity!=SQLITE_AFF_NONE ){
6779668179
assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL
6779768180
|| affinity==SQLITE_AFF_NUMERIC );
67798
- applyNumericAffinity(pRec);
68181
+ ApplyNumericAffinity(pRec);
6779968182
if( pRec->flags & MEM_Real ){
6780068183
sqlite3VdbeIntegerAffinity(pRec);
6780168184
}
6780268185
}
6780368186
}
@@ -68374,16 +68757,18 @@
6837468757
break;
6837568758
}
6837668759
6837768760
/* Opcode: InitCoroutine P1 P2 P3 * *
6837868761
**
68379
-** Set up register P1 so that it will OP_Yield to the co-routine
68762
+** Set up register P1 so that it will Yield to the coroutine
6838068763
** located at address P3.
6838168764
**
68382
-** If P2!=0 then the co-routine implementation immediately follows
68383
-** this opcode. So jump over the co-routine implementation to
68765
+** If P2!=0 then the coroutine implementation immediately follows
68766
+** this opcode. So jump over the coroutine implementation to
6838468767
** address P2.
68768
+**
68769
+** See also: EndCoroutine
6838568770
*/
6838668771
case OP_InitCoroutine: { /* jump */
6838768772
assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
6838868773
assert( pOp->p2>=0 && pOp->p2<p->nOp );
6838968774
assert( pOp->p3>=0 && pOp->p3<p->nOp );
@@ -68395,13 +68780,15 @@
6839568780
break;
6839668781
}
6839768782
6839868783
/* Opcode: EndCoroutine P1 * * * *
6839968784
**
68400
-** The instruction at the address in register P1 is an OP_Yield.
68401
-** Jump to the P2 parameter of that OP_Yield.
68785
+** The instruction at the address in register P1 is a Yield.
68786
+** Jump to the P2 parameter of that Yield.
6840268787
** After the jump, register P1 becomes undefined.
68788
+**
68789
+** See also: InitCoroutine
6840368790
*/
6840468791
case OP_EndCoroutine: { /* in1 */
6840568792
VdbeOp *pCaller;
6840668793
pIn1 = &aMem[pOp->p1];
6840768794
assert( pIn1->flags==MEM_Int );
@@ -68414,15 +68801,20 @@
6841468801
break;
6841568802
}
6841668803
6841768804
/* Opcode: Yield P1 P2 * * *
6841868805
**
68419
-** Swap the program counter with the value in register P1.
68806
+** Swap the program counter with the value in register P1. This
68807
+** has the effect of yielding to a coroutine.
6842068808
**
68421
-** If the co-routine ends with OP_Yield or OP_Return then continue
68422
-** to the next instruction. But if the co-routine ends with
68423
-** OP_EndCoroutine, jump immediately to P2.
68809
+** If the coroutine that is launched by this instruction ends with
68810
+** Yield or Return then continue to the next instruction. But if
68811
+** the coroutine launched by this instruction ends with
68812
+** EndCoroutine, then jump to P2 rather than continuing with the
68813
+** next instruction.
68814
+**
68815
+** See also: InitCoroutine
6842468816
*/
6842568817
case OP_Yield: { /* in1, jump */
6842668818
int pcDest;
6842768819
pIn1 = &aMem[pOp->p1];
6842868820
assert( VdbeMemDynamic(pIn1)==0 );
@@ -68581,11 +68973,11 @@
6858168973
6858268974
/* Opcode: String8 * P2 * P4 *
6858368975
** Synopsis: r[P2]='P4'
6858468976
**
6858568977
** P4 points to a nul terminated UTF-8 string. This opcode is transformed
68586
-** into an OP_String before it is executed for the first time. During
68978
+** into a String before it is executed for the first time. During
6858768979
** this transformation, the length of string P4 is computed and stored
6858868980
** as the P1 parameter.
6858968981
*/
6859068982
case OP_String8: { /* same as TK_STRING, out2-prerelease */
6859168983
assert( pOp->p4.z!=0 );
@@ -69803,14 +70195,18 @@
6980370195
break;
6980470196
}
6980570197
6980670198
/* Opcode: Once P1 P2 * * *
6980770199
**
69808
-** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise,
69809
-** set the flag and fall through to the next instruction. In other words,
69810
-** this opcode causes all following opcodes up through P2 (but not including
69811
-** P2) to run just once and to be skipped on subsequent times through the loop.
70200
+** Check the "once" flag number P1. If it is set, jump to instruction P2.
70201
+** Otherwise, set the flag and fall through to the next instruction.
70202
+** In other words, this opcode causes all following opcodes up through P2
70203
+** (but not including P2) to run just once and to be skipped on subsequent
70204
+** times through the loop.
70205
+**
70206
+** All "once" flags are initially cleared whenever a prepared statement
70207
+** first begins to run.
6981270208
*/
6981370209
case OP_Once: { /* jump */
6981470210
assert( pOp->p1<p->nOnceFlag );
6981570211
VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2);
6981670212
if( p->aOnceFlag[pOp->p1] ){
@@ -69823,17 +70219,17 @@
6982370219
6982470220
/* Opcode: If P1 P2 P3 * *
6982570221
**
6982670222
** Jump to P2 if the value in register P1 is true. The value
6982770223
** is considered true if it is numeric and non-zero. If the value
69828
-** in P1 is NULL then take the jump if P3 is non-zero.
70224
+** in P1 is NULL then take the jump if and only if P3 is non-zero.
6982970225
*/
6983070226
/* Opcode: IfNot P1 P2 P3 * *
6983170227
**
6983270228
** Jump to P2 if the value in register P1 is False. The value
6983370229
** is considered false if it has a numeric value of zero. If the value
69834
-** in P1 is NULL then take the jump if P3 is zero.
70230
+** in P1 is NULL then take the jump if and only if P3 is non-zero.
6983570231
*/
6983670232
case OP_If: /* jump, in1 */
6983770233
case OP_IfNot: { /* jump, in1 */
6983870234
int c;
6983970235
pIn1 = &aMem[pOp->p1];
@@ -70641,11 +71037,11 @@
7064171037
int iGen;
7064271038
7064371039
assert( p->bIsReader );
7064471040
assert( p->readOnly==0 || pOp->p2==0 );
7064571041
assert( pOp->p1>=0 && pOp->p1<db->nDb );
70646
- assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
71042
+ assert( DbMaskTest(p->btreeMask, pOp->p1) );
7064771043
if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
7064871044
rc = SQLITE_READONLY;
7064971045
goto abort_due_to_error;
7065071046
}
7065171047
pBt = db->aDb[pOp->p1].pBt;
@@ -70736,11 +71132,11 @@
7073671132
iDb = pOp->p1;
7073771133
iCookie = pOp->p3;
7073871134
assert( pOp->p3<SQLITE_N_BTREE_META );
7073971135
assert( iDb>=0 && iDb<db->nDb );
7074071136
assert( db->aDb[iDb].pBt!=0 );
70741
- assert( (p->btreeMask & (((yDbMask)1)<<iDb))!=0 );
71137
+ assert( DbMaskTest(p->btreeMask, iDb) );
7074271138
7074371139
sqlite3BtreeGetMeta(db->aDb[iDb].pBt, iCookie, (u32 *)&iMeta);
7074471140
pOut->u.i = iMeta;
7074571141
break;
7074671142
}
@@ -70757,11 +71153,11 @@
7075771153
*/
7075871154
case OP_SetCookie: { /* in3 */
7075971155
Db *pDb;
7076071156
assert( pOp->p2<SQLITE_N_BTREE_META );
7076171157
assert( pOp->p1>=0 && pOp->p1<db->nDb );
70762
- assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
71158
+ assert( DbMaskTest(p->btreeMask, pOp->p1) );
7076371159
assert( p->readOnly==0 );
7076471160
pDb = &db->aDb[pOp->p1];
7076571161
assert( pDb->pBt!=0 );
7076671162
assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
7076771163
pIn3 = &aMem[pOp->p3];
@@ -70812,11 +71208,25 @@
7081271208
** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
7081371209
** structure, then said structure defines the content and collating
7081471210
** sequence of the index being opened. Otherwise, if P4 is an integer
7081571211
** value, it is set to the number of columns in the table.
7081671212
**
70817
-** See also OpenWrite.
71213
+** See also: OpenWrite, ReopenIdx
71214
+*/
71215
+/* Opcode: ReopenIdx P1 P2 P3 P4 P5
71216
+** Synopsis: root=P2 iDb=P3
71217
+**
71218
+** The ReopenIdx opcode works exactly like ReadOpen except that it first
71219
+** checks to see if the cursor on P1 is already open with a root page
71220
+** number of P2 and if it is this opcode becomes a no-op. In other words,
71221
+** if the cursor is already open, do not reopen it.
71222
+**
71223
+** The ReopenIdx opcode may only be used with P5==0 and with P4 being
71224
+** a P4_KEYINFO object. Furthermore, the P3 value must be the same as
71225
+** every other ReopenIdx or OpenRead for the same cursor number.
71226
+**
71227
+** See the OpenRead opcode documentation for additional information.
7081871228
*/
7081971229
/* Opcode: OpenWrite P1 P2 P3 P4 P5
7082071230
** Synopsis: root=P2 iDb=P3
7082171231
**
7082271232
** Open a read/write cursor named P1 on the table or index whose root
@@ -70834,10 +71244,23 @@
7083471244
** in read/write mode. For a given table, there can be one or more read-only
7083571245
** cursors or a single read/write cursor but not both.
7083671246
**
7083771247
** See also OpenRead.
7083871248
*/
71249
+case OP_ReopenIdx: {
71250
+ VdbeCursor *pCur;
71251
+
71252
+ assert( pOp->p5==0 );
71253
+ assert( pOp->p4type==P4_KEYINFO );
71254
+ pCur = p->apCsr[pOp->p1];
71255
+ if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){
71256
+ assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */
71257
+ break;
71258
+ }
71259
+ /* If the cursor is not currently open or is open on a different
71260
+ ** index, then fall through into OP_OpenRead to force a reopen */
71261
+}
7083971262
case OP_OpenRead:
7084071263
case OP_OpenWrite: {
7084171264
int nField;
7084271265
KeyInfo *pKeyInfo;
7084371266
int p2;
@@ -70848,11 +71271,12 @@
7084871271
Db *pDb;
7084971272
7085071273
assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 );
7085171274
assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 );
7085271275
assert( p->bIsReader );
70853
- assert( pOp->opcode==OP_OpenRead || p->readOnly==0 );
71276
+ assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx
71277
+ || p->readOnly==0 );
7085471278
7085571279
if( p->expired ){
7085671280
rc = SQLITE_ABORT;
7085771281
break;
7085871282
}
@@ -70860,11 +71284,11 @@
7086071284
nField = 0;
7086171285
pKeyInfo = 0;
7086271286
p2 = pOp->p2;
7086371287
iDb = pOp->p3;
7086471288
assert( iDb>=0 && iDb<db->nDb );
70865
- assert( (p->btreeMask & (((yDbMask)1)<<iDb))!=0 );
71289
+ assert( DbMaskTest(p->btreeMask, iDb) );
7086671290
pDb = &db->aDb[iDb];
7086771291
pX = pDb->pBt;
7086871292
assert( pX!=0 );
7086971293
if( pOp->opcode==OP_OpenWrite ){
7087071294
wrFlag = 1;
@@ -70905,10 +71329,11 @@
7090571329
testcase( nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */
7090671330
pCur = allocateCursor(p, pOp->p1, nField, iDb, 1);
7090771331
if( pCur==0 ) goto no_mem;
7090871332
pCur->nullRow = 1;
7090971333
pCur->isOrdered = 1;
71334
+ pCur->pgnoRoot = p2;
7091071335
rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor);
7091171336
pCur->pKeyInfo = pKeyInfo;
7091271337
assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
7091371338
sqlite3BtreeCursorHints(pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
7091471339
@@ -71059,11 +71484,11 @@
7105971484
sqlite3VdbeFreeCursor(p, p->apCsr[pOp->p1]);
7106071485
p->apCsr[pOp->p1] = 0;
7106171486
break;
7106271487
}
7106371488
71064
-/* Opcode: SeekGe P1 P2 P3 P4 *
71489
+/* Opcode: SeekGE P1 P2 P3 P4 *
7106571490
** Synopsis: key=r[P3@P4]
7106671491
**
7106771492
** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
7106871493
** use the value in register P3 as the key. If cursor P1 refers
7106971494
** to an SQL index, then P3 is the first in an array of P4 registers
@@ -71070,14 +71495,18 @@
7107071495
** that are used as an unpacked index key.
7107171496
**
7107271497
** Reposition cursor P1 so that it points to the smallest entry that
7107371498
** is greater than or equal to the key value. If there are no records
7107471499
** greater than or equal to the key and P2 is not zero, then jump to P2.
71500
+**
71501
+** This opcode leaves the cursor configured to move in forward order,
71502
+** from the beginning toward the end. In other words, the cursor is
71503
+** configured to use Next, not Prev.
7107571504
**
7107671505
** See also: Found, NotFound, SeekLt, SeekGt, SeekLe
7107771506
*/
71078
-/* Opcode: SeekGt P1 P2 P3 P4 *
71507
+/* Opcode: SeekGT P1 P2 P3 P4 *
7107971508
** Synopsis: key=r[P3@P4]
7108071509
**
7108171510
** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
7108271511
** use the value in register P3 as a key. If cursor P1 refers
7108371512
** to an SQL index, then P3 is the first in an array of P4 registers
@@ -71084,14 +71513,18 @@
7108471513
** that are used as an unpacked index key.
7108571514
**
7108671515
** Reposition cursor P1 so that it points to the smallest entry that
7108771516
** is greater than the key value. If there are no records greater than
7108871517
** the key and P2 is not zero, then jump to P2.
71518
+**
71519
+** This opcode leaves the cursor configured to move in forward order,
71520
+** from the begining toward the end. In other words, the cursor is
71521
+** configured to use Next, not Prev.
7108971522
**
7109071523
** See also: Found, NotFound, SeekLt, SeekGe, SeekLe
7109171524
*/
71092
-/* Opcode: SeekLt P1 P2 P3 P4 *
71525
+/* Opcode: SeekLT P1 P2 P3 P4 *
7109371526
** Synopsis: key=r[P3@P4]
7109471527
**
7109571528
** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
7109671529
** use the value in register P3 as a key. If cursor P1 refers
7109771530
** to an SQL index, then P3 is the first in an array of P4 registers
@@ -71098,14 +71531,18 @@
7109871531
** that are used as an unpacked index key.
7109971532
**
7110071533
** Reposition cursor P1 so that it points to the largest entry that
7110171534
** is less than the key value. If there are no records less than
7110271535
** the key and P2 is not zero, then jump to P2.
71536
+**
71537
+** This opcode leaves the cursor configured to move in reverse order,
71538
+** from the end toward the beginning. In other words, the cursor is
71539
+** configured to use Prev, not Next.
7110371540
**
7110471541
** See also: Found, NotFound, SeekGt, SeekGe, SeekLe
7110571542
*/
71106
-/* Opcode: SeekLe P1 P2 P3 P4 *
71543
+/* Opcode: SeekLE P1 P2 P3 P4 *
7110771544
** Synopsis: key=r[P3@P4]
7110871545
**
7110971546
** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
7111071547
** use the value in register P3 as a key. If cursor P1 refers
7111171548
** to an SQL index, then P3 is the first in an array of P4 registers
@@ -71112,10 +71549,14 @@
7111271549
** that are used as an unpacked index key.
7111371550
**
7111471551
** Reposition cursor P1 so that it points to the largest entry that
7111571552
** is less than or equal to the key value. If there are no records
7111671553
** less than or equal to the key and P2 is not zero, then jump to P2.
71554
+**
71555
+** This opcode leaves the cursor configured to move in reverse order,
71556
+** from the end toward the beginning. In other words, the cursor is
71557
+** configured to use Prev, not Next.
7111771558
**
7111871559
** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
7111971560
*/
7112071561
case OP_SeekLT: /* jump, in3 */
7112171562
case OP_SeekLE: /* jump, in3 */
@@ -71138,16 +71579,19 @@
7113871579
assert( OP_SeekGT == OP_SeekLT+3 );
7113971580
assert( pC->isOrdered );
7114071581
assert( pC->pCursor!=0 );
7114171582
oc = pOp->opcode;
7114271583
pC->nullRow = 0;
71584
+#ifdef SQLITE_DEBUG
71585
+ pC->seekOp = pOp->opcode;
71586
+#endif
7114371587
if( pC->isTable ){
7114471588
/* The input value in P3 might be of any type: integer, real, string,
7114571589
** blob, or NULL. But it needs to be an integer before we can do
7114671590
** the seek, so covert it. */
7114771591
pIn3 = &aMem[pOp->p3];
71148
- applyNumericAffinity(pIn3);
71592
+ ApplyNumericAffinity(pIn3);
7114971593
iKey = sqlite3VdbeIntValue(pIn3);
7115071594
pC->rowidIsValid = 0;
7115171595
7115271596
/* If the P3 value could not be converted into an integer without
7115371597
** loss of information, then special processing is required... */
@@ -71292,10 +71736,14 @@
7129271736
** record.
7129371737
**
7129471738
** Cursor P1 is on an index btree. If the record identified by P3 and P4
7129571739
** is a prefix of any entry in P1 then a jump is made to P2 and
7129671740
** P1 is left pointing at the matching entry.
71741
+**
71742
+** This operation leaves the cursor in a state where it can be
71743
+** advanced in the forward direction. The Next instruction will work,
71744
+** but not the Prev instruction.
7129771745
**
7129871746
** See also: NotFound, NoConflict, NotExists. SeekGe
7129971747
*/
7130071748
/* Opcode: NotFound P1 P2 P3 P4 *
7130171749
** Synopsis: key=r[P3@P4]
@@ -71307,10 +71755,14 @@
7130771755
** Cursor P1 is on an index btree. If the record identified by P3 and P4
7130871756
** is not the prefix of any entry in P1 then a jump is made to P2. If P1
7130971757
** does contain an entry whose prefix matches the P3/P4 record then control
7131071758
** falls through to the next instruction and P1 is left pointing at the
7131171759
** matching entry.
71760
+**
71761
+** This operation leaves the cursor in a state where it cannot be
71762
+** advanced in either direction. In other words, the Next and Prev
71763
+** opcodes do not work after this operation.
7131271764
**
7131371765
** See also: Found, NotExists, NoConflict
7131471766
*/
7131571767
/* Opcode: NoConflict P1 P2 P3 P4 *
7131671768
** Synopsis: key=r[P3@P4]
@@ -71326,10 +71778,14 @@
7132671778
** immediately to P2. If there is a match, fall through and leave the P1
7132771779
** cursor pointing to the matching row.
7132871780
**
7132971781
** This opcode is similar to OP_NotFound with the exceptions that the
7133071782
** branch is always taken if any part of the search key input is NULL.
71783
+**
71784
+** This operation leaves the cursor in a state where it cannot be
71785
+** advanced in either direction. In other words, the Next and Prev
71786
+** opcodes do not work after this operation.
7133171787
**
7133271788
** See also: NotFound, Found, NotExists
7133371789
*/
7133471790
case OP_NoConflict: /* jump, in3 */
7133571791
case OP_NotFound: /* jump, in3 */
@@ -71349,10 +71805,13 @@
7134971805
7135071806
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
7135171807
assert( pOp->p4type==P4_INT32 );
7135271808
pC = p->apCsr[pOp->p1];
7135371809
assert( pC!=0 );
71810
+#ifdef SQLITE_DEBUG
71811
+ pC->seekOp = pOp->opcode;
71812
+#endif
7135471813
pIn3 = &aMem[pOp->p3];
7135571814
assert( pC->pCursor!=0 );
7135671815
assert( pC->isTable==0 );
7135771816
pFree = 0; /* Not needed. Only used to suppress a compiler warning. */
7135871817
if( pOp->p4.i>0 ){
@@ -71419,10 +71878,14 @@
7141971878
** with rowid P3 then leave the cursor pointing at that record and fall
7142071879
** through to the next instruction.
7142171880
**
7142271881
** The OP_NotFound opcode performs the same operation on index btrees
7142371882
** (with arbitrary multi-value keys).
71883
+**
71884
+** This opcode leaves the cursor in a state where it cannot be advanced
71885
+** in either direction. In other words, the Next and Prev opcodes will
71886
+** not work following this opcode.
7142471887
**
7142571888
** See also: Found, NotFound, NoConflict
7142671889
*/
7142771890
case OP_NotExists: { /* jump, in3 */
7142871891
VdbeCursor *pC;
@@ -71433,10 +71896,13 @@
7143371896
pIn3 = &aMem[pOp->p3];
7143471897
assert( pIn3->flags & MEM_Int );
7143571898
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
7143671899
pC = p->apCsr[pOp->p1];
7143771900
assert( pC!=0 );
71901
+#ifdef SQLITE_DEBUG
71902
+ pC->seekOp = 0;
71903
+#endif
7143871904
assert( pC->isTable );
7143971905
assert( pC->pseudoTableReg==0 );
7144071906
pCrsr = pC->pCursor;
7144171907
assert( pCrsr!=0 );
7144271908
res = 0;
@@ -71735,11 +72201,11 @@
7173572201
** Delete the record at which the P1 cursor is currently pointing.
7173672202
**
7173772203
** The cursor will be left pointing at either the next or the previous
7173872204
** record in the table. If it is left pointing at the next record, then
7173972205
** the next Next instruction will be a no-op. Hence it is OK to delete
71740
-** a record from within an Next loop.
72206
+** a record from within a Next loop.
7174172207
**
7174272208
** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is
7174372209
** incremented (otherwise not).
7174472210
**
7174572211
** P1 must not be pseudo-table. It has to be a real table with
@@ -71795,16 +72261,16 @@
7179572261
p->nChange = 0;
7179672262
break;
7179772263
}
7179872264
7179972265
/* Opcode: SorterCompare P1 P2 P3 P4
71800
-** Synopsis: if key(P1)!=rtrim(r[P3],P4) goto P2
72266
+** Synopsis: if key(P1)!=trim(r[P3],P4) goto P2
7180172267
**
7180272268
** P1 is a sorter cursor. This instruction compares a prefix of the
71803
-** the record blob in register P3 against a prefix of the entry that
71804
-** the sorter cursor currently points to. The final P4 fields of both
71805
-** the P3 and sorter record are ignored.
72269
+** record blob in register P3 against a prefix of the entry that
72270
+** the sorter cursor currently points to. Only the first P4 fields
72271
+** of r[P3] and the sorter record are compared.
7180672272
**
7180772273
** If either P3 or the sorter contains a NULL in one of their significant
7180872274
** fields (not counting the P4 fields at the end which are ignored) then
7180972275
** the comparison is assumed to be equal.
7181072276
**
@@ -71812,18 +72278,18 @@
7181272278
** each other. Jump to P2 if they are different.
7181372279
*/
7181472280
case OP_SorterCompare: {
7181572281
VdbeCursor *pC;
7181672282
int res;
71817
- int nIgnore;
72283
+ int nKeyCol;
7181872284
7181972285
pC = p->apCsr[pOp->p1];
7182072286
assert( isSorter(pC) );
7182172287
assert( pOp->p4type==P4_INT32 );
7182272288
pIn3 = &aMem[pOp->p3];
71823
- nIgnore = pOp->p4.i;
71824
- rc = sqlite3VdbeSorterCompare(pC, pIn3, nIgnore, &res);
72289
+ nKeyCol = pOp->p4.i;
72290
+ rc = sqlite3VdbeSorterCompare(pC, pIn3, nKeyCol, &res);
7182572291
VdbeBranchTaken(res!=0,2);
7182672292
if( res ){
7182772293
pc = pOp->p2-1;
7182872294
}
7182972295
break;
@@ -71999,15 +72465,19 @@
7199972465
break;
7200072466
}
7200172467
7200272468
/* Opcode: Last P1 P2 * * *
7200372469
**
72004
-** The next use of the Rowid or Column or Next instruction for P1
72470
+** The next use of the Rowid or Column or Prev instruction for P1
7200572471
** will refer to the last entry in the database table or index.
7200672472
** If the table or index is empty and P2>0, then jump immediately to P2.
7200772473
** If P2 is 0 or if the table or index is not empty, fall through
7200872474
** to the following instruction.
72475
+**
72476
+** This opcode leaves the cursor configured to move in reverse order,
72477
+** from the end toward the beginning. In other words, the cursor is
72478
+** configured to use Prev, not Next.
7200972479
*/
7201072480
case OP_Last: { /* jump */
7201172481
VdbeCursor *pC;
7201272482
BtCursor *pCrsr;
7201372483
int res;
@@ -72021,10 +72491,13 @@
7202172491
rc = sqlite3BtreeLast(pCrsr, &res);
7202272492
pC->nullRow = (u8)res;
7202372493
pC->deferredMoveto = 0;
7202472494
pC->rowidIsValid = 0;
7202572495
pC->cacheStatus = CACHE_STALE;
72496
+#ifdef SQLITE_DEBUG
72497
+ pC->seekOp = OP_Last;
72498
+#endif
7202672499
if( pOp->p2>0 ){
7202772500
VdbeBranchTaken(res!=0,2);
7202872501
if( res ) pc = pOp->p2 - 1;
7202972502
}
7203072503
break;
@@ -72057,10 +72530,14 @@
7205772530
** The next use of the Rowid or Column or Next instruction for P1
7205872531
** will refer to the first entry in the database table or index.
7205972532
** If the table or index is empty and P2>0, then jump immediately to P2.
7206072533
** If P2 is 0 or if the table or index is not empty, fall through
7206172534
** to the following instruction.
72535
+**
72536
+** This opcode leaves the cursor configured to move in forward order,
72537
+** from the begining toward the end. In other words, the cursor is
72538
+** configured to use Next, not Prev.
7206272539
*/
7206372540
case OP_Rewind: { /* jump */
7206472541
VdbeCursor *pC;
7206572542
BtCursor *pCrsr;
7206672543
int res;
@@ -72068,10 +72545,13 @@
7206872545
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
7206972546
pC = p->apCsr[pOp->p1];
7207072547
assert( pC!=0 );
7207172548
assert( isSorter(pC)==(pOp->opcode==OP_SorterSort) );
7207272549
res = 1;
72550
+#ifdef SQLITE_DEBUG
72551
+ pC->seekOp = OP_Rewind;
72552
+#endif
7207372553
if( isSorter(pC) ){
7207472554
rc = sqlite3VdbeSorterRewind(db, pC, &res);
7207572555
}else{
7207672556
pCrsr = pC->pCursor;
7207772557
assert( pCrsr );
@@ -72093,10 +72573,14 @@
7209372573
**
7209472574
** Advance cursor P1 so that it points to the next key/data pair in its
7209572575
** table or index. If there are no more key/value pairs then fall through
7209672576
** to the following instruction. But if the cursor advance was successful,
7209772577
** jump immediately to P2.
72578
+**
72579
+** The Next opcode is only valid following an SeekGT, SeekGE, or
72580
+** OP_Rewind opcode used to position the cursor. Next is not allowed
72581
+** to follow SeekLT, SeekLE, or OP_Last.
7209872582
**
7209972583
** The P1 cursor must be for a real table, not a pseudo-table. P1 must have
7210072584
** been opened prior to this opcode or the program will segfault.
7210172585
**
7210272586
** The P3 value is a hint to the btree implementation. If P3==1, that
@@ -72112,20 +72596,25 @@
7211272596
**
7211372597
** See also: Prev, NextIfOpen
7211472598
*/
7211572599
/* Opcode: NextIfOpen P1 P2 P3 P4 P5
7211672600
**
72117
-** This opcode works just like OP_Next except that if cursor P1 is not
72601
+** This opcode works just like Next except that if cursor P1 is not
7211872602
** open it behaves a no-op.
7211972603
*/
7212072604
/* Opcode: Prev P1 P2 P3 P4 P5
7212172605
**
7212272606
** Back up cursor P1 so that it points to the previous key/data pair in its
7212372607
** table or index. If there is no previous key/value pairs then fall through
7212472608
** to the following instruction. But if the cursor backup was successful,
7212572609
** jump immediately to P2.
7212672610
**
72611
+**
72612
+** The Prev opcode is only valid following an SeekLT, SeekLE, or
72613
+** OP_Last opcode used to position the cursor. Prev is not allowed
72614
+** to follow SeekGT, SeekGE, or OP_Rewind.
72615
+**
7212772616
** The P1 cursor must be for a real table, not a pseudo-table. If P1 is
7212872617
** not open then the behavior is undefined.
7212972618
**
7213072619
** The P3 value is a hint to the btree implementation. If P3==1, that
7213172620
** means P1 is an SQL index and that this instruction could have been
@@ -72138,11 +72627,11 @@
7213872627
** If P5 is positive and the jump is taken, then event counter
7213972628
** number P5-1 in the prepared statement is incremented.
7214072629
*/
7214172630
/* Opcode: PrevIfOpen P1 P2 P3 P4 P5
7214272631
**
72143
-** This opcode works just like OP_Prev except that if cursor P1 is not
72632
+** This opcode works just like Prev except that if cursor P1 is not
7214472633
** open it behaves a no-op.
7214572634
*/
7214672635
case OP_SorterNext: { /* jump */
7214772636
VdbeCursor *pC;
7214872637
int res;
@@ -72169,10 +72658,20 @@
7216972658
testcase( res==1 );
7217072659
assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
7217172660
assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
7217272661
assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext );
7217372662
assert( pOp->opcode!=OP_PrevIfOpen || pOp->p4.xAdvance==sqlite3BtreePrevious);
72663
+
72664
+ /* The Next opcode is only used after SeekGT, SeekGE, and Rewind.
72665
+ ** The Prev opcode is only used after SeekLT, SeekLE, and Last. */
72666
+ assert( pOp->opcode!=OP_Next || pOp->opcode!=OP_NextIfOpen
72667
+ || pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE
72668
+ || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found);
72669
+ assert( pOp->opcode!=OP_Prev || pOp->opcode!=OP_PrevIfOpen
72670
+ || pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
72671
+ || pC->seekOp==OP_Last );
72672
+
7217472673
rc = pOp->p4.xAdvance(pC->pCursor, &res);
7217572674
next_tail:
7217672675
pC->cacheStatus = CACHE_STALE;
7217772676
VdbeBranchTaken(res==0,2);
7217872677
if( res==0 ){
@@ -72451,11 +72950,11 @@
7245172950
rc = SQLITE_LOCKED;
7245272951
p->errorAction = OE_Abort;
7245372952
}else{
7245472953
iDb = pOp->p3;
7245572954
assert( iCnt==1 );
72456
- assert( (p->btreeMask & (((yDbMask)1)<<iDb))!=0 );
72955
+ assert( DbMaskTest(p->btreeMask, iDb) );
7245772956
iMoved = 0; /* Not needed. Only to silence a warning. */
7245872957
rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved);
7245972958
pOut->flags = MEM_Int;
7246072959
pOut->u.i = iMoved;
7246172960
#ifndef SQLITE_OMIT_AUTOVACUUM
@@ -72491,11 +72990,11 @@
7249172990
case OP_Clear: {
7249272991
int nChange;
7249372992
7249472993
nChange = 0;
7249572994
assert( p->readOnly==0 );
72496
- assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 );
72995
+ assert( DbMaskTest(p->btreeMask, pOp->p2) );
7249772996
rc = sqlite3BtreeClearTable(
7249872997
db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0)
7249972998
);
7250072999
if( pOp->p3 ){
7250173000
p->nChange += nChange;
@@ -72561,11 +73060,11 @@
7256173060
int flags;
7256273061
Db *pDb;
7256373062
7256473063
pgno = 0;
7256573064
assert( pOp->p1>=0 && pOp->p1<db->nDb );
72566
- assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
73065
+ assert( DbMaskTest(p->btreeMask, pOp->p1) );
7256773066
assert( p->readOnly==0 );
7256873067
pDb = &db->aDb[pOp->p1];
7256973068
assert( pDb->pBt!=0 );
7257073069
if( pOp->opcode==OP_CreateTable ){
7257173070
/* flags = BTREE_INTKEY; */
@@ -72649,11 +73148,12 @@
7264973148
7265073149
/* Opcode: DropTable P1 * * P4 *
7265173150
**
7265273151
** Remove the internal (in-memory) data structures that describe
7265373152
** the table named P4 in database P1. This is called after a table
72654
-** is dropped in order to keep the internal representation of the
73153
+** is dropped from disk (using the Destroy opcode) in order to keep
73154
+** the internal representation of the
7265573155
** schema consistent with what is on disk.
7265673156
*/
7265773157
case OP_DropTable: {
7265873158
sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p4.z);
7265973159
break;
@@ -72661,11 +73161,12 @@
7266173161
7266273162
/* Opcode: DropIndex P1 * * P4 *
7266373163
**
7266473164
** Remove the internal (in-memory) data structures that describe
7266573165
** the index named P4 in database P1. This is called after an index
72666
-** is dropped in order to keep the internal representation of the
73166
+** is dropped from disk (using the Destroy opcode)
73167
+** in order to keep the internal representation of the
7266773168
** schema consistent with what is on disk.
7266873169
*/
7266973170
case OP_DropIndex: {
7267073171
sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p4.z);
7267173172
break;
@@ -72673,11 +73174,12 @@
7267373174
7267473175
/* Opcode: DropTrigger P1 * * P4 *
7267573176
**
7267673177
** Remove the internal (in-memory) data structures that describe
7267773178
** the trigger named P4 in database P1. This is called after a trigger
72678
-** is dropped in order to keep the internal representation of the
73179
+** is dropped from disk (using the Destroy opcode) in order to keep
73180
+** the internal representation of the
7267973181
** schema consistent with what is on disk.
7268073182
*/
7268173183
case OP_DropTrigger: {
7268273184
sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p4.z);
7268373185
break;
@@ -72726,11 +73228,11 @@
7272673228
for(j=0; j<nRoot; j++){
7272773229
aRoot[j] = (int)sqlite3VdbeIntValue(&pIn1[j]);
7272873230
}
7272973231
aRoot[j] = 0;
7273073232
assert( pOp->p5<db->nDb );
72731
- assert( (p->btreeMask & (((yDbMask)1)<<pOp->p5))!=0 );
73233
+ assert( DbMaskTest(p->btreeMask, pOp->p5) );
7273273234
z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot,
7273373235
(int)pnErr->u.i, &nErr);
7273473236
sqlite3DbFree(db, aRoot);
7273573237
pnErr->u.i -= nErr;
7273673238
sqlite3VdbeMemSetNull(pIn1);
@@ -73088,21 +73590,20 @@
7308873590
pc = pOp->p2 - 1;
7308973591
}
7309073592
break;
7309173593
}
7309273594
73093
-/* Opcode: IfNeg P1 P2 * * *
73094
-** Synopsis: if r[P1]<0 goto P2
73595
+/* Opcode: IfNeg P1 P2 P3 * *
73596
+** Synopsis: r[P1]+=P3, if r[P1]<0 goto P2
7309573597
**
73096
-** If the value of register P1 is less than zero, jump to P2.
73097
-**
73098
-** It is illegal to use this instruction on a register that does
73099
-** not contain an integer. An assertion fault will result if you try.
73598
+** Register P1 must contain an integer. Add literal P3 to the value in
73599
+** register P1 then if the value of register P1 is less than zero, jump to P2.
7310073600
*/
7310173601
case OP_IfNeg: { /* jump, in1 */
7310273602
pIn1 = &aMem[pOp->p1];
7310373603
assert( pIn1->flags&MEM_Int );
73604
+ pIn1->u.i += pOp->p3;
7310473605
VdbeBranchTaken(pIn1->u.i<0, 2);
7310573606
if( pIn1->u.i<0 ){
7310673607
pc = pOp->p2 - 1;
7310773608
}
7310873609
break;
@@ -73111,13 +73612,10 @@
7311173612
/* Opcode: IfZero P1 P2 P3 * *
7311273613
** Synopsis: r[P1]+=P3, if r[P1]==0 goto P2
7311373614
**
7311473615
** The register P1 must contain an integer. Add literal P3 to the
7311573616
** value in register P1. If the result is exactly 0, jump to P2.
73116
-**
73117
-** It is illegal to use this instruction on a register that does
73118
-** not contain an integer. An assertion fault will result if you try.
7311973617
*/
7312073618
case OP_IfZero: { /* jump, in1 */
7312173619
pIn1 = &aMem[pOp->p1];
7312273620
assert( pIn1->flags&MEM_Int );
7312373621
pIn1->u.i += pOp->p3;
@@ -73386,11 +73884,11 @@
7338673884
*/
7338773885
case OP_IncrVacuum: { /* jump */
7338873886
Btree *pBt;
7338973887
7339073888
assert( pOp->p1>=0 && pOp->p1<db->nDb );
73391
- assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
73889
+ assert( DbMaskTest(p->btreeMask, pOp->p1) );
7339273890
assert( p->readOnly==0 );
7339373891
pBt = db->aDb[pOp->p1].pBt;
7339473892
rc = sqlite3BtreeIncrVacuum(pBt);
7339573893
VdbeBranchTaken(rc==SQLITE_DONE,2);
7339673894
if( rc==SQLITE_DONE ){
@@ -73401,16 +73899,17 @@
7340173899
}
7340273900
#endif
7340373901
7340473902
/* Opcode: Expire P1 * * * *
7340573903
**
73406
-** Cause precompiled statements to become expired. An expired statement
73407
-** fails with an error code of SQLITE_SCHEMA if it is ever executed
73408
-** (via sqlite3_step()).
73904
+** Cause precompiled statements to expire. When an expired statement
73905
+** is executed using sqlite3_step() it will either automatically
73906
+** reprepare itself (if it was originally created using sqlite3_prepare_v2())
73907
+** or it will fail with SQLITE_SCHEMA.
7340973908
**
7341073909
** If P1 is 0, then all SQL statements become expired. If P1 is non-zero,
73411
-** then only the currently executing statement is affected.
73910
+** then only the currently executing statement is expired.
7341273911
*/
7341373912
case OP_Expire: {
7341473913
if( !pOp->p1 ){
7341573914
sqlite3ExpirePreparedStatements(db);
7341673915
}else{
@@ -73438,11 +73937,11 @@
7343873937
case OP_TableLock: {
7343973938
u8 isWriteLock = (u8)pOp->p3;
7344073939
if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){
7344173940
int p1 = pOp->p1;
7344273941
assert( p1>=0 && p1<db->nDb );
73443
- assert( (p->btreeMask & (((yDbMask)1)<<p1))!=0 );
73942
+ assert( DbMaskTest(p->btreeMask, p1) );
7344473943
assert( isWriteLock==0 || isWriteLock==1 );
7344573944
rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock);
7344673945
if( (rc&0xFF)==SQLITE_LOCKED ){
7344773946
const char *z = pOp->p4.z;
7344873947
sqlite3SetString(&p->zErrMsg, db, "database table is locked: %s", z);
@@ -73888,11 +74387,11 @@
7388874387
#ifdef SQLITE_USE_FCNTL_TRACE
7388974388
zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
7389074389
if( zTrace ){
7389174390
int i;
7389274391
for(i=0; i<db->nDb; i++){
73893
- if( (MASKBIT(i) & p->btreeMask)==0 ) continue;
74392
+ if( DbMaskTest(p->btreeMask, i)==0 ) continue;
7389474393
sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace);
7389574394
}
7389674395
}
7389774396
#endif /* SQLITE_USE_FCNTL_TRACE */
7389874397
#ifdef SQLITE_DEBUG
@@ -74878,11 +75377,11 @@
7487875377
** If pKey2 is passed a NULL pointer, then it is assumed that the pCsr->aSpace
7487975378
** has been allocated and contains an unpacked record that is used as key2.
7488075379
*/
7488175380
static void vdbeSorterCompare(
7488275381
const VdbeCursor *pCsr, /* Cursor object (for pKeyInfo) */
74883
- int nIgnore, /* Ignore the last nIgnore fields */
75382
+ int nKeyCol, /* Num of columns. 0 means "all" */
7488475383
const void *pKey1, int nKey1, /* Left side of comparison */
7488575384
const void *pKey2, int nKey2, /* Right side of comparison */
7488675385
int *pRes /* OUT: Result of comparison */
7488775386
){
7488875387
KeyInfo *pKeyInfo = pCsr->pKeyInfo;
@@ -74892,14 +75391,13 @@
7489275391
7489375392
if( pKey2 ){
7489475393
sqlite3VdbeRecordUnpack(pKeyInfo, nKey2, pKey2, r2);
7489575394
}
7489675395
74897
- if( nIgnore ){
74898
- r2->nField = pKeyInfo->nField - nIgnore;
74899
- assert( r2->nField>0 );
74900
- for(i=0; i<r2->nField; i++){
75396
+ if( nKeyCol ){
75397
+ r2->nField = nKeyCol;
75398
+ for(i=0; i<nKeyCol; i++){
7490175399
if( r2->aMem[i].flags & MEM_Null ){
7490275400
*pRes = -1;
7490375401
return;
7490475402
}
7490575403
}
@@ -75577,18 +76075,18 @@
7557776075
** key.
7557876076
*/
7557976077
SQLITE_PRIVATE int sqlite3VdbeSorterCompare(
7558076078
const VdbeCursor *pCsr, /* Sorter cursor */
7558176079
Mem *pVal, /* Value to compare to current sorter key */
75582
- int nIgnore, /* Ignore this many fields at the end */
76080
+ int nKeyCol, /* Only compare this many fields */
7558376081
int *pRes /* OUT: Result of comparison */
7558476082
){
7558576083
VdbeSorter *pSorter = pCsr->pSorter;
7558676084
void *pKey; int nKey; /* Sorter key to compare pVal with */
7558776085
7558876086
pKey = vdbeSorterRowkey(pSorter, &nKey);
75589
- vdbeSorterCompare(pCsr, nIgnore, pVal->z, pVal->n, pKey, nKey, pRes);
76087
+ vdbeSorterCompare(pCsr, nKeyCol, pVal->z, pVal->n, pKey, nKey, pRes);
7559076088
return SQLITE_OK;
7559176089
}
7559276090
7559376091
/************** End of vdbesort.c ********************************************/
7559476092
/************** Begin file journal.c *****************************************/
@@ -76616,11 +77114,11 @@
7661677114
}
7661777115
break;
7661877116
}
7661977117
}
7662077118
if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && HasRowid(pTab) ){
76621
- /* IMP: R-24309-18625 */
77119
+ /* IMP: R-51414-32910 */
7662277120
/* IMP: R-44911-55124 */
7662377121
iCol = -1;
7662477122
}
7662577123
if( iCol<pTab->nCol ){
7662677124
cnt++;
@@ -76972,11 +77470,15 @@
7697277470
}
7697377471
}else{
7697477472
/* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is equivalent to
7697577473
** likelihood(X, 0.0625).
7697677474
** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is short-hand for
76977
- ** likelihood(X,0.0625). */
77475
+ ** likelihood(X,0.0625).
77476
+ ** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand for
77477
+ ** likelihood(X,0.9375).
77478
+ ** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent to
77479
+ ** likelihood(X,0.9375). */
7697877480
/* TUNING: unlikely() probability is 0.0625. likely() is 0.9375 */
7697977481
pExpr->iTable = pDef->zName[0]=='u' ? 62 : 938;
7698077482
}
7698177483
}
7698277484
}
@@ -79085,10 +79587,13 @@
7908579587
case TK_INTEGER:
7908679588
case TK_STRING:
7908779589
case TK_FLOAT:
7908879590
case TK_BLOB:
7908979591
return 0;
79592
+ case TK_COLUMN:
79593
+ assert( p->pTab!=0 );
79594
+ return p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0;
7909079595
default:
7909179596
return 1;
7909279597
}
7909379598
}
7909479599
@@ -79192,83 +79697,124 @@
7919279697
SQLITE_PRIVATE int sqlite3CodeOnce(Parse *pParse){
7919379698
Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
7919479699
return sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++);
7919579700
}
7919679701
79702
+/*
79703
+** Generate code that checks the left-most column of index table iCur to see if
79704
+** it contains any NULL entries. Cause the register at regHasNull to be set
79705
+** to a non-NULL value if iCur contains no NULLs. Cause register regHasNull
79706
+** to be set to NULL if iCur contains one or more NULL values.
79707
+*/
79708
+static void sqlite3SetHasNullFlag(Vdbe *v, int iCur, int regHasNull){
79709
+ int j1;
79710
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regHasNull);
79711
+ j1 = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
79712
+ sqlite3VdbeAddOp3(v, OP_Column, iCur, 0, regHasNull);
79713
+ sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
79714
+ VdbeComment((v, "first_entry_in(%d)", iCur));
79715
+ sqlite3VdbeJumpHere(v, j1);
79716
+}
79717
+
79718
+
79719
+#ifndef SQLITE_OMIT_SUBQUERY
79720
+/*
79721
+** The argument is an IN operator with a list (not a subquery) on the
79722
+** right-hand side. Return TRUE if that list is constant.
79723
+*/
79724
+static int sqlite3InRhsIsConstant(Expr *pIn){
79725
+ Expr *pLHS;
79726
+ int res;
79727
+ assert( !ExprHasProperty(pIn, EP_xIsSelect) );
79728
+ pLHS = pIn->pLeft;
79729
+ pIn->pLeft = 0;
79730
+ res = sqlite3ExprIsConstant(pIn);
79731
+ pIn->pLeft = pLHS;
79732
+ return res;
79733
+}
79734
+#endif
79735
+
7919779736
/*
7919879737
** This function is used by the implementation of the IN (...) operator.
7919979738
** The pX parameter is the expression on the RHS of the IN operator, which
7920079739
** might be either a list of expressions or a subquery.
7920179740
**
7920279741
** The job of this routine is to find or create a b-tree object that can
7920379742
** be used either to test for membership in the RHS set or to iterate through
7920479743
** all members of the RHS set, skipping duplicates.
7920579744
**
79206
-** A cursor is opened on the b-tree object that the RHS of the IN operator
79745
+** A cursor is opened on the b-tree object that is the RHS of the IN operator
7920779746
** and pX->iTable is set to the index of that cursor.
7920879747
**
7920979748
** The returned value of this function indicates the b-tree type, as follows:
7921079749
**
7921179750
** IN_INDEX_ROWID - The cursor was opened on a database table.
7921279751
** IN_INDEX_INDEX_ASC - The cursor was opened on an ascending index.
7921379752
** IN_INDEX_INDEX_DESC - The cursor was opened on a descending index.
7921479753
** IN_INDEX_EPH - The cursor was opened on a specially created and
7921579754
** populated epheremal table.
79755
+** IN_INDEX_NOOP - No cursor was allocated. The IN operator must be
79756
+** implemented as a sequence of comparisons.
7921679757
**
7921779758
** An existing b-tree might be used if the RHS expression pX is a simple
7921879759
** subquery such as:
7921979760
**
7922079761
** SELECT <column> FROM <table>
7922179762
**
7922279763
** If the RHS of the IN operator is a list or a more complex subquery, then
7922379764
** an ephemeral table might need to be generated from the RHS and then
7922479765
** pX->iTable made to point to the ephermeral table instead of an
79225
-** existing table.
79766
+** existing table.
7922679767
**
79227
-** If the prNotFound parameter is 0, then the b-tree will be used to iterate
79228
-** through the set members, skipping any duplicates. In this case an
79229
-** epheremal table must be used unless the selected <column> is guaranteed
79768
+** The inFlags parameter must contain exactly one of the bits
79769
+** IN_INDEX_MEMBERSHIP or IN_INDEX_LOOP. If inFlags contains
79770
+** IN_INDEX_MEMBERSHIP, then the generated table will be used for a
79771
+** fast membership test. When the IN_INDEX_LOOP bit is set, the
79772
+** IN index will be used to loop over all values of the RHS of the
79773
+** IN operator.
79774
+**
79775
+** When IN_INDEX_LOOP is used (and the b-tree will be used to iterate
79776
+** through the set members) then the b-tree must not contain duplicates.
79777
+** An epheremal table must be used unless the selected <column> is guaranteed
7923079778
** to be unique - either because it is an INTEGER PRIMARY KEY or it
7923179779
** has a UNIQUE constraint or UNIQUE index.
7923279780
**
79233
-** If the prNotFound parameter is not 0, then the b-tree will be used
79234
-** for fast set membership tests. In this case an epheremal table must
79781
+** When IN_INDEX_MEMBERSHIP is used (and the b-tree will be used
79782
+** for fast set membership tests) then an epheremal table must
7923579783
** be used unless <column> is an INTEGER PRIMARY KEY or an index can
7923679784
** be found with <column> as its left-most column.
79785
+**
79786
+** If the IN_INDEX_NOOP_OK and IN_INDEX_MEMBERSHIP are both set and
79787
+** if the RHS of the IN operator is a list (not a subquery) then this
79788
+** routine might decide that creating an ephemeral b-tree for membership
79789
+** testing is too expensive and return IN_INDEX_NOOP. In that case, the
79790
+** calling routine should implement the IN operator using a sequence
79791
+** of Eq or Ne comparison operations.
7923779792
**
7923879793
** When the b-tree is being used for membership tests, the calling function
79239
-** needs to know whether or not the structure contains an SQL NULL
79240
-** value in order to correctly evaluate expressions like "X IN (Y, Z)".
79241
-** If there is any chance that the (...) might contain a NULL value at
79794
+** might need to know whether or not the RHS side of the IN operator
79795
+** contains a NULL. If prRhsHasNull is not a NULL pointer and
79796
+** if there is any chance that the (...) might contain a NULL value at
7924279797
** runtime, then a register is allocated and the register number written
79243
-** to *prNotFound. If there is no chance that the (...) contains a
79244
-** NULL value, then *prNotFound is left unchanged.
79245
-**
79246
-** If a register is allocated and its location stored in *prNotFound, then
79247
-** its initial value is NULL. If the (...) does not remain constant
79248
-** for the duration of the query (i.e. the SELECT within the (...)
79249
-** is a correlated subquery) then the value of the allocated register is
79250
-** reset to NULL each time the subquery is rerun. This allows the
79251
-** caller to use vdbe code equivalent to the following:
79252
-**
79253
-** if( register==NULL ){
79254
-** has_null = <test if data structure contains null>
79255
-** register = 1
79256
-** }
79257
-**
79258
-** in order to avoid running the <test if data structure contains null>
79259
-** test more often than is necessary.
79798
+** to *prRhsHasNull. If there is no chance that the (...) contains a
79799
+** NULL value, then *prRhsHasNull is left unchanged.
79800
+**
79801
+** If a register is allocated and its location stored in *prRhsHasNull, then
79802
+** the value in that register will be NULL if the b-tree contains one or more
79803
+** NULL values, and it will be some non-NULL value if the b-tree contains no
79804
+** NULL values.
7926079805
*/
7926179806
#ifndef SQLITE_OMIT_SUBQUERY
79262
-SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
79807
+SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){
7926379808
Select *p; /* SELECT to the right of IN operator */
7926479809
int eType = 0; /* Type of RHS table. IN_INDEX_* */
7926579810
int iTab = pParse->nTab++; /* Cursor of the RHS table */
79266
- int mustBeUnique = (prNotFound==0); /* True if RHS must be unique */
79811
+ int mustBeUnique; /* True if RHS must be unique */
7926779812
Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
7926879813
7926979814
assert( pX->op==TK_IN );
79815
+ mustBeUnique = (inFlags & IN_INDEX_LOOP)!=0;
7927079816
7927179817
/* Check to see if an existing table or index can be used to
7927279818
** satisfy the query. This is preferable to generating a new
7927379819
** ephemeral table.
7927479820
*/
@@ -79321,44 +79867,59 @@
7932179867
int affinity_ok = sqlite3IndexAffinityOk(pX, pTab->aCol[iCol].affinity);
7932279868
7932379869
for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){
7932479870
if( (pIdx->aiColumn[0]==iCol)
7932579871
&& sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq
79326
- && (!mustBeUnique || (pIdx->nKeyCol==1 && pIdx->onError!=OE_None))
79872
+ && (!mustBeUnique || (pIdx->nKeyCol==1 && IsUniqueIndex(pIdx)))
7932779873
){
7932879874
int iAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
7932979875
sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb);
7933079876
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
7933179877
VdbeComment((v, "%s", pIdx->zName));
7933279878
assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 );
7933379879
eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0];
7933479880
79335
- if( prNotFound && !pTab->aCol[iCol].notNull ){
79336
- *prNotFound = ++pParse->nMem;
79337
- sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound);
79881
+ if( prRhsHasNull && !pTab->aCol[iCol].notNull ){
79882
+ *prRhsHasNull = ++pParse->nMem;
79883
+ sqlite3SetHasNullFlag(v, iTab, *prRhsHasNull);
7933879884
}
7933979885
sqlite3VdbeJumpHere(v, iAddr);
7934079886
}
7934179887
}
7934279888
}
7934379889
}
79890
+
79891
+ /* If no preexisting index is available for the IN clause
79892
+ ** and IN_INDEX_NOOP is an allowed reply
79893
+ ** and the RHS of the IN operator is a list, not a subquery
79894
+ ** and the RHS is not contant or has two or fewer terms,
79895
+ ** then it is not worth creating an ephermeral table to evaluate
79896
+ ** the IN operator so return IN_INDEX_NOOP.
79897
+ */
79898
+ if( eType==0
79899
+ && (inFlags & IN_INDEX_NOOP_OK)
79900
+ && !ExprHasProperty(pX, EP_xIsSelect)
79901
+ && (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2)
79902
+ ){
79903
+ eType = IN_INDEX_NOOP;
79904
+ }
79905
+
7934479906
7934579907
if( eType==0 ){
79346
- /* Could not found an existing table or index to use as the RHS b-tree.
79908
+ /* Could not find an existing table or index to use as the RHS b-tree.
7934779909
** We will have to generate an ephemeral table to do the job.
7934879910
*/
7934979911
u32 savedNQueryLoop = pParse->nQueryLoop;
7935079912
int rMayHaveNull = 0;
7935179913
eType = IN_INDEX_EPH;
79352
- if( prNotFound ){
79353
- *prNotFound = rMayHaveNull = ++pParse->nMem;
79354
- sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound);
79355
- }else{
79914
+ if( inFlags & IN_INDEX_LOOP ){
7935679915
pParse->nQueryLoop = 0;
7935779916
if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){
7935879917
eType = IN_INDEX_ROWID;
7935979918
}
79919
+ }else if( prRhsHasNull ){
79920
+ *prRhsHasNull = rMayHaveNull = ++pParse->nMem;
7936079921
}
7936179922
sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID);
7936279923
pParse->nQueryLoop = savedNQueryLoop;
7936379924
}else{
7936479925
pX->iTable = iTab;
@@ -79385,31 +79946,25 @@
7938579946
** intkey B-Tree to store the set of IN(...) values instead of the usual
7938679947
** (slower) variable length keys B-Tree.
7938779948
**
7938879949
** If rMayHaveNull is non-zero, that means that the operation is an IN
7938979950
** (not a SELECT or EXISTS) and that the RHS might contains NULLs.
79390
-** Furthermore, the IN is in a WHERE clause and that we really want
79391
-** to iterate over the RHS of the IN operator in order to quickly locate
79392
-** all corresponding LHS elements. All this routine does is initialize
79393
-** the register given by rMayHaveNull to NULL. Calling routines will take
79394
-** care of changing this register value to non-NULL if the RHS is NULL-free.
79395
-**
79396
-** If rMayHaveNull is zero, that means that the subquery is being used
79397
-** for membership testing only. There is no need to initialize any
79398
-** registers to indicate the presence or absence of NULLs on the RHS.
79951
+** All this routine does is initialize the register given by rMayHaveNull
79952
+** to NULL. Calling routines will take care of changing this register
79953
+** value to non-NULL if the RHS is NULL-free.
7939979954
**
7940079955
** For a SELECT or EXISTS operator, return the register that holds the
7940179956
** result. For IN operators or if an error occurs, the return value is 0.
7940279957
*/
7940379958
#ifndef SQLITE_OMIT_SUBQUERY
7940479959
SQLITE_PRIVATE int sqlite3CodeSubselect(
7940579960
Parse *pParse, /* Parsing context */
7940679961
Expr *pExpr, /* The IN, SELECT, or EXISTS operator */
79407
- int rMayHaveNull, /* Register that records whether NULLs exist in RHS */
79962
+ int rHasNullFlag, /* Register that records whether NULLs exist in RHS */
7940879963
int isRowid /* If true, LHS of IN operator is a rowid */
7940979964
){
79410
- int testAddr = -1; /* One-time test address */
79965
+ int jmpIfDynamic = -1; /* One-time test address */
7941179966
int rReg = 0; /* Register storing resulting */
7941279967
Vdbe *v = sqlite3GetVdbe(pParse);
7941379968
if( NEVER(v==0) ) return 0;
7941479969
sqlite3ExprCachePush(pParse);
7941579970
@@ -79422,17 +79977,17 @@
7942279977
**
7942379978
** If all of the above are false, then we can run this code just once
7942479979
** save the results, and reuse the same result on subsequent invocations.
7942579980
*/
7942679981
if( !ExprHasProperty(pExpr, EP_VarSelect) ){
79427
- testAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
79982
+ jmpIfDynamic = sqlite3CodeOnce(pParse); VdbeCoverage(v);
7942879983
}
7942979984
7943079985
#ifndef SQLITE_OMIT_EXPLAIN
7943179986
if( pParse->explain==2 ){
7943279987
char *zMsg = sqlite3MPrintf(
79433
- pParse->db, "EXECUTE %s%s SUBQUERY %d", testAddr>=0?"":"CORRELATED ",
79988
+ pParse->db, "EXECUTE %s%s SUBQUERY %d", jmpIfDynamic>=0?"":"CORRELATED ",
7943479989
pExpr->op==TK_IN?"LIST":"SCALAR", pParse->iNextSelectId
7943579990
);
7943679991
sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
7943779992
}
7943879993
#endif
@@ -79442,14 +79997,10 @@
7944279997
char affinity; /* Affinity of the LHS of the IN */
7944379998
int addr; /* Address of OP_OpenEphemeral instruction */
7944479999
Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */
7944580000
KeyInfo *pKeyInfo = 0; /* Key information */
7944680001
79447
- if( rMayHaveNull ){
79448
- sqlite3VdbeAddOp2(v, OP_Null, 0, rMayHaveNull);
79449
- }
79450
-
7945180002
affinity = sqlite3ExprAffinity(pLeft);
7945280003
7945380004
/* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
7945480005
** expression it is handled the same way. An ephemeral table is
7945580006
** filled with single-field index keys representing the results
@@ -79471,24 +80022,27 @@
7947180022
/* Case 1: expr IN (SELECT ...)
7947280023
**
7947380024
** Generate code to write the results of the select into the temporary
7947480025
** table allocated and opened above.
7947580026
*/
80027
+ Select *pSelect = pExpr->x.pSelect;
7947680028
SelectDest dest;
7947780029
ExprList *pEList;
7947880030
7947980031
assert( !isRowid );
7948080032
sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
7948180033
dest.affSdst = (u8)affinity;
7948280034
assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
79483
- pExpr->x.pSelect->iLimit = 0;
80035
+ pSelect->iLimit = 0;
80036
+ testcase( pSelect->selFlags & SF_Distinct );
80037
+ pSelect->selFlags &= ~SF_Distinct;
7948480038
testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
79485
- if( sqlite3Select(pParse, pExpr->x.pSelect, &dest) ){
80039
+ if( sqlite3Select(pParse, pSelect, &dest) ){
7948680040
sqlite3KeyInfoUnref(pKeyInfo);
7948780041
return 0;
7948880042
}
79489
- pEList = pExpr->x.pSelect->pEList;
80043
+ pEList = pSelect->pEList;
7949080044
assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
7949180045
assert( pEList!=0 );
7949280046
assert( pEList->nExpr>0 );
7949380047
assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
7949480048
pKeyInfo->aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
@@ -79515,23 +80069,23 @@
7951580069
}
7951680070
7951780071
/* Loop through each expression in <exprlist>. */
7951880072
r1 = sqlite3GetTempReg(pParse);
7951980073
r2 = sqlite3GetTempReg(pParse);
79520
- sqlite3VdbeAddOp2(v, OP_Null, 0, r2);
80074
+ if( isRowid ) sqlite3VdbeAddOp2(v, OP_Null, 0, r2);
7952180075
for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
7952280076
Expr *pE2 = pItem->pExpr;
7952380077
int iValToIns;
7952480078
7952580079
/* If the expression is not constant then we will need to
7952680080
** disable the test that was generated above that makes sure
7952780081
** this code only executes once. Because for a non-constant
7952880082
** expression we need to rerun this code each time.
7952980083
*/
79530
- if( testAddr>=0 && !sqlite3ExprIsConstant(pE2) ){
79531
- sqlite3VdbeChangeToNoop(v, testAddr);
79532
- testAddr = -1;
80084
+ if( jmpIfDynamic>=0 && !sqlite3ExprIsConstant(pE2) ){
80085
+ sqlite3VdbeChangeToNoop(v, jmpIfDynamic);
80086
+ jmpIfDynamic = -1;
7953380087
}
7953480088
7953580089
/* Evaluate the expression and insert it into the temp table */
7953680090
if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){
7953780091
sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns);
@@ -79597,12 +80151,16 @@
7959780151
ExprSetVVAProperty(pExpr, EP_NoReduce);
7959880152
break;
7959980153
}
7960080154
}
7960180155
79602
- if( testAddr>=0 ){
79603
- sqlite3VdbeJumpHere(v, testAddr);
80156
+ if( rHasNullFlag ){
80157
+ sqlite3SetHasNullFlag(v, pExpr->iTable, rHasNullFlag);
80158
+ }
80159
+
80160
+ if( jmpIfDynamic>=0 ){
80161
+ sqlite3VdbeJumpHere(v, jmpIfDynamic);
7960480162
}
7960580163
sqlite3ExprCachePop(pParse);
7960680164
7960780165
return rReg;
7960880166
}
@@ -79619,11 +80177,11 @@
7961980177
** is an array of zero or more values. The expression is true if the LHS is
7962080178
** contained within the RHS. The value of the expression is unknown (NULL)
7962180179
** if the LHS is NULL or if the LHS is not contained within the RHS and the
7962280180
** RHS contains one or more NULL values.
7962380181
**
79624
-** This routine generates code will jump to destIfFalse if the LHS is not
80182
+** This routine generates code that jumps to destIfFalse if the LHS is not
7962580183
** contained within the RHS. If due to NULLs we cannot determine if the LHS
7962680184
** is contained in the RHS then jump to destIfNull. If the LHS is contained
7962780185
** within the RHS then fall through.
7962880186
*/
7962980187
static void sqlite3ExprCodeIN(
@@ -79642,11 +80200,13 @@
7964280200
** pExpr->iTable will contains the values that make up the RHS.
7964380201
*/
7964480202
v = pParse->pVdbe;
7964580203
assert( v!=0 ); /* OOM detected prior to this routine */
7964680204
VdbeNoopComment((v, "begin IN expr"));
79647
- eType = sqlite3FindInIndex(pParse, pExpr, &rRhsHasNull);
80205
+ eType = sqlite3FindInIndex(pParse, pExpr,
80206
+ IN_INDEX_MEMBERSHIP | IN_INDEX_NOOP_OK,
80207
+ destIfFalse==destIfNull ? 0 : &rRhsHasNull);
7964880208
7964980209
/* Figure out the affinity to use to create a key from the results
7965080210
** of the expression. affinityStr stores a static string suitable for
7965180211
** P4 of OP_MakeRecord.
7965280212
*/
@@ -79656,86 +80216,118 @@
7965680216
*/
7965780217
sqlite3ExprCachePush(pParse);
7965880218
r1 = sqlite3GetTempReg(pParse);
7965980219
sqlite3ExprCode(pParse, pExpr->pLeft, r1);
7966080220
79661
- /* If the LHS is NULL, then the result is either false or NULL depending
79662
- ** on whether the RHS is empty or not, respectively.
79663
- */
79664
- if( destIfNull==destIfFalse ){
79665
- /* Shortcut for the common case where the false and NULL outcomes are
79666
- ** the same. */
79667
- sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull); VdbeCoverage(v);
79668
- }else{
79669
- int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); VdbeCoverage(v);
79670
- sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse);
79671
- VdbeCoverage(v);
79672
- sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull);
79673
- sqlite3VdbeJumpHere(v, addr1);
79674
- }
79675
-
79676
- if( eType==IN_INDEX_ROWID ){
79677
- /* In this case, the RHS is the ROWID of table b-tree
79678
- */
79679
- sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse); VdbeCoverage(v);
79680
- sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1);
79681
- VdbeCoverage(v);
79682
- }else{
79683
- /* In this case, the RHS is an index b-tree.
79684
- */
79685
- sqlite3VdbeAddOp4(v, OP_Affinity, r1, 1, 0, &affinity, 1);
79686
-
79687
- /* If the set membership test fails, then the result of the
79688
- ** "x IN (...)" expression must be either 0 or NULL. If the set
79689
- ** contains no NULL values, then the result is 0. If the set
79690
- ** contains one or more NULL values, then the result of the
79691
- ** expression is also NULL.
79692
- */
79693
- if( rRhsHasNull==0 || destIfFalse==destIfNull ){
79694
- /* This branch runs if it is known at compile time that the RHS
79695
- ** cannot contain NULL values. This happens as the result
79696
- ** of a "NOT NULL" constraint in the database schema.
79697
- **
79698
- ** Also run this branch if NULL is equivalent to FALSE
79699
- ** for this particular IN operator.
79700
- */
79701
- sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, r1, 1);
79702
- VdbeCoverage(v);
79703
- }else{
79704
- /* In this branch, the RHS of the IN might contain a NULL and
79705
- ** the presence of a NULL on the RHS makes a difference in the
79706
- ** outcome.
79707
- */
79708
- int j1, j2;
79709
-
79710
- /* First check to see if the LHS is contained in the RHS. If so,
79711
- ** then the presence of NULLs in the RHS does not matter, so jump
79712
- ** over all of the code that follows.
79713
- */
79714
- j1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1);
79715
- VdbeCoverage(v);
79716
-
79717
- /* Here we begin generating code that runs if the LHS is not
79718
- ** contained within the RHS. Generate additional code that
79719
- ** tests the RHS for NULLs. If the RHS contains a NULL then
79720
- ** jump to destIfNull. If there are no NULLs in the RHS then
79721
- ** jump to destIfFalse.
79722
- */
79723
- sqlite3VdbeAddOp2(v, OP_If, rRhsHasNull, destIfNull); VdbeCoverage(v);
79724
- sqlite3VdbeAddOp2(v, OP_IfNot, rRhsHasNull, destIfFalse); VdbeCoverage(v);
79725
- j2 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, rRhsHasNull, 1);
79726
- VdbeCoverage(v);
79727
- sqlite3VdbeAddOp2(v, OP_Integer, 0, rRhsHasNull);
80221
+ /* If sqlite3FindInIndex() did not find or create an index that is
80222
+ ** suitable for evaluating the IN operator, then evaluate using a
80223
+ ** sequence of comparisons.
80224
+ */
80225
+ if( eType==IN_INDEX_NOOP ){
80226
+ ExprList *pList = pExpr->x.pList;
80227
+ CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
80228
+ int labelOk = sqlite3VdbeMakeLabel(v);
80229
+ int r2, regToFree;
80230
+ int regCkNull = 0;
80231
+ int ii;
80232
+ assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
80233
+ if( destIfNull!=destIfFalse ){
80234
+ regCkNull = sqlite3GetTempReg(pParse);
80235
+ sqlite3VdbeAddOp3(v, OP_BitAnd, r1, r1, regCkNull);
80236
+ }
80237
+ for(ii=0; ii<pList->nExpr; ii++){
80238
+ r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr, &regToFree);
80239
+ if( regCkNull && sqlite3ExprCanBeNull(pList->a[ii].pExpr) ){
80240
+ sqlite3VdbeAddOp3(v, OP_BitAnd, regCkNull, r2, regCkNull);
80241
+ }
80242
+ if( ii<pList->nExpr-1 || destIfNull!=destIfFalse ){
80243
+ sqlite3VdbeAddOp4(v, OP_Eq, r1, labelOk, r2,
80244
+ (void*)pColl, P4_COLLSEQ);
80245
+ VdbeCoverageIf(v, ii<pList->nExpr-1);
80246
+ VdbeCoverageIf(v, ii==pList->nExpr-1);
80247
+ sqlite3VdbeChangeP5(v, affinity);
80248
+ }else{
80249
+ assert( destIfNull==destIfFalse );
80250
+ sqlite3VdbeAddOp4(v, OP_Ne, r1, destIfFalse, r2,
80251
+ (void*)pColl, P4_COLLSEQ); VdbeCoverage(v);
80252
+ sqlite3VdbeChangeP5(v, affinity | SQLITE_JUMPIFNULL);
80253
+ }
80254
+ sqlite3ReleaseTempReg(pParse, regToFree);
80255
+ }
80256
+ if( regCkNull ){
80257
+ sqlite3VdbeAddOp2(v, OP_IsNull, regCkNull, destIfNull); VdbeCoverage(v);
7972880258
sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse);
79729
- sqlite3VdbeJumpHere(v, j2);
79730
- sqlite3VdbeAddOp2(v, OP_Integer, 1, rRhsHasNull);
79731
- sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull);
79732
-
79733
- /* The OP_Found at the top of this branch jumps here when true,
79734
- ** causing the overall IN expression evaluation to fall through.
80259
+ }
80260
+ sqlite3VdbeResolveLabel(v, labelOk);
80261
+ sqlite3ReleaseTempReg(pParse, regCkNull);
80262
+ }else{
80263
+
80264
+ /* If the LHS is NULL, then the result is either false or NULL depending
80265
+ ** on whether the RHS is empty or not, respectively.
80266
+ */
80267
+ if( sqlite3ExprCanBeNull(pExpr->pLeft) ){
80268
+ if( destIfNull==destIfFalse ){
80269
+ /* Shortcut for the common case where the false and NULL outcomes are
80270
+ ** the same. */
80271
+ sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull); VdbeCoverage(v);
80272
+ }else{
80273
+ int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); VdbeCoverage(v);
80274
+ sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse);
80275
+ VdbeCoverage(v);
80276
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull);
80277
+ sqlite3VdbeJumpHere(v, addr1);
80278
+ }
80279
+ }
80280
+
80281
+ if( eType==IN_INDEX_ROWID ){
80282
+ /* In this case, the RHS is the ROWID of table b-tree
7973580283
*/
79736
- sqlite3VdbeJumpHere(v, j1);
80284
+ sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse); VdbeCoverage(v);
80285
+ sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1);
80286
+ VdbeCoverage(v);
80287
+ }else{
80288
+ /* In this case, the RHS is an index b-tree.
80289
+ */
80290
+ sqlite3VdbeAddOp4(v, OP_Affinity, r1, 1, 0, &affinity, 1);
80291
+
80292
+ /* If the set membership test fails, then the result of the
80293
+ ** "x IN (...)" expression must be either 0 or NULL. If the set
80294
+ ** contains no NULL values, then the result is 0. If the set
80295
+ ** contains one or more NULL values, then the result of the
80296
+ ** expression is also NULL.
80297
+ */
80298
+ assert( destIfFalse!=destIfNull || rRhsHasNull==0 );
80299
+ if( rRhsHasNull==0 ){
80300
+ /* This branch runs if it is known at compile time that the RHS
80301
+ ** cannot contain NULL values. This happens as the result
80302
+ ** of a "NOT NULL" constraint in the database schema.
80303
+ **
80304
+ ** Also run this branch if NULL is equivalent to FALSE
80305
+ ** for this particular IN operator.
80306
+ */
80307
+ sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, r1, 1);
80308
+ VdbeCoverage(v);
80309
+ }else{
80310
+ /* In this branch, the RHS of the IN might contain a NULL and
80311
+ ** the presence of a NULL on the RHS makes a difference in the
80312
+ ** outcome.
80313
+ */
80314
+ int j1;
80315
+
80316
+ /* First check to see if the LHS is contained in the RHS. If so,
80317
+ ** then the answer is TRUE the presence of NULLs in the RHS does
80318
+ ** not matter. If the LHS is not contained in the RHS, then the
80319
+ ** answer is NULL if the RHS contains NULLs and the answer is
80320
+ ** FALSE if the RHS is NULL-free.
80321
+ */
80322
+ j1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1);
80323
+ VdbeCoverage(v);
80324
+ sqlite3VdbeAddOp2(v, OP_IsNull, rRhsHasNull, destIfNull);
80325
+ VdbeCoverage(v);
80326
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse);
80327
+ sqlite3VdbeJumpHere(v, j1);
80328
+ }
7973780329
}
7973880330
}
7973980331
sqlite3ReleaseTempReg(pParse, r1);
7974080332
sqlite3ExprCachePop(pParse);
7974180333
VdbeComment((v, "end IN expr"));
@@ -79792,21 +80384,28 @@
7979280384
}else{
7979380385
int c;
7979480386
i64 value;
7979580387
const char *z = pExpr->u.zToken;
7979680388
assert( z!=0 );
79797
- c = sqlite3Atoi64(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
80389
+ c = sqlite3DecOrHexToI64(z, &value);
7979880390
if( c==0 || (c==2 && negFlag) ){
7979980391
char *zV;
7980080392
if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; }
7980180393
zV = dup8bytes(v, (char*)&value);
7980280394
sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64);
7980380395
}else{
7980480396
#ifdef SQLITE_OMIT_FLOATING_POINT
7980580397
sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
7980680398
#else
79807
- codeReal(v, z, negFlag, iMem);
80399
+#ifndef SQLITE_OMIT_HEX_INTEGER
80400
+ if( sqlite3_strnicmp(z,"0x",2)==0 ){
80401
+ sqlite3ErrorMsg(pParse, "hex literal too big: %s", z);
80402
+ }else
80403
+#endif
80404
+ {
80405
+ codeReal(v, z, negFlag, iMem);
80406
+ }
7980880407
#endif
7980980408
}
7981080409
}
7981180410
}
7981280411
@@ -80348,11 +80947,11 @@
8034880947
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
8034980948
testcase( regFree1==0 );
8035080949
addr = sqlite3VdbeAddOp1(v, op, r1);
8035180950
VdbeCoverageIf(v, op==TK_ISNULL);
8035280951
VdbeCoverageIf(v, op==TK_NOTNULL);
80353
- sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
80952
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, target);
8035480953
sqlite3VdbeJumpHere(v, addr);
8035580954
break;
8035680955
}
8035780956
case TK_AGG_FUNCTION: {
8035880957
AggInfo *pInfo = pExpr->pAggInfo;
@@ -80384,11 +80983,11 @@
8038480983
nFarg = pFarg ? pFarg->nExpr : 0;
8038580984
assert( !ExprHasProperty(pExpr, EP_IntValue) );
8038680985
zId = pExpr->u.zToken;
8038780986
nId = sqlite3Strlen30(zId);
8038880987
pDef = sqlite3FindFunction(db, zId, nId, nFarg, enc, 0);
80389
- if( pDef==0 ){
80988
+ if( pDef==0 || pDef->xFunc==0 ){
8039080989
sqlite3ErrorMsg(pParse, "unknown function: %.*s()", nId, zId);
8039180990
break;
8039280991
}
8039380992
8039480993
/* Attempt a direct implementation of the built-in COALESCE() and
@@ -83175,19 +83774,24 @@
8317583774
}
8317683775
8317783776
/*
8317883777
** Implementation of the stat_init(N,K,C) SQL function. The three parameters
8317983778
** are:
83180
-** N: The number of columns in the index including the rowid/pk
83181
-** K: The number of columns in the index excluding the rowid/pk
83182
-** C: The number of rows in the index
83183
-**
83184
-** C is only used for STAT3 and STAT4.
83185
-**
83186
-** For ordinary rowid tables, N==K+1. But for WITHOUT ROWID tables,
83187
-** N=K+P where P is the number of columns in the primary key. For the
83188
-** covering index that implements the original WITHOUT ROWID table, N==K.
83779
+** N: The number of columns in the index including the rowid/pk (note 1)
83780
+** K: The number of columns in the index excluding the rowid/pk.
83781
+** C: The number of rows in the index (note 2)
83782
+**
83783
+** Note 1: In the special case of the covering index that implements a
83784
+** WITHOUT ROWID table, N is the number of PRIMARY KEY columns, not the
83785
+** total number of columns in the table.
83786
+**
83787
+** Note 2: C is only used for STAT3 and STAT4.
83788
+**
83789
+** For indexes on ordinary rowid tables, N==K+1. But for indexes on
83790
+** WITHOUT ROWID tables, N=K+P where P is the number of columns in the
83791
+** PRIMARY KEY of the table. The covering index that implements the
83792
+** original WITHOUT ROWID table as N==K as a special case.
8318983793
**
8319083794
** This routine allocates the Stat4Accum object in heap memory. The return
8319183795
** value is a pointer to the the Stat4Accum object encoded as a blob (i.e.
8319283796
** the size of the blob is sizeof(void*) bytes).
8319383797
*/
@@ -83493,11 +84097,14 @@
8349384097
** P Pointer to the Stat4Accum object created by stat_init()
8349484098
** C Index of left-most column to differ from previous row
8349584099
** R Rowid for the current row. Might be a key record for
8349684100
** WITHOUT ROWID tables.
8349784101
**
83498
-** The SQL function always returns NULL.
84102
+** This SQL function always returns NULL. It's purpose it to accumulate
84103
+** statistical data and/or samples in the Stat4Accum object about the
84104
+** index being analyzed. The stat_get() SQL function will later be used to
84105
+** extract relevant information for constructing the sqlite_statN tables.
8349984106
**
8350084107
** The R parameter is only used for STAT3 and STAT4
8350184108
*/
8350284109
static void statPush(
8350384110
sqlite3_context *context,
@@ -83587,11 +84194,14 @@
8358784194
#define STAT_GET_NLT 3 /* "nlt" column of stat[34] entry */
8358884195
#define STAT_GET_NDLT 4 /* "ndlt" column of stat[34] entry */
8358984196
8359084197
/*
8359184198
** Implementation of the stat_get(P,J) SQL function. This routine is
83592
-** used to query the results. Content is returned for parameter J
84199
+** used to query statistical information that has been gathered into
84200
+** the Stat4Accum object by prior calls to stat_push(). The P parameter
84201
+** is a BLOB which is decoded into a pointer to the Stat4Accum objects.
84202
+** The content to returned is determined by the parameter J
8359384203
** which is one of the STAT_GET_xxxx values defined above.
8359484204
**
8359584205
** If neither STAT3 nor STAT4 are enabled, then J is always
8359684206
** STAT_GET_STAT1 and is hence omitted and this routine becomes
8359784207
** a one-parameter function, stat_get(P), that always returns the
@@ -83806,28 +84416,27 @@
8380684416
pParse->nTab = MAX(pParse->nTab, iTab);
8380784417
sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
8380884418
sqlite3VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0);
8380984419
8381084420
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
83811
- int nCol; /* Number of columns indexed by pIdx */
83812
- int *aGotoChng; /* Array of jump instruction addresses */
84421
+ int nCol; /* Number of columns in pIdx. "N" */
8381384422
int addrRewind; /* Address of "OP_Rewind iIdxCur" */
83814
- int addrGotoChng0; /* Address of "Goto addr_chng_0" */
8381584423
int addrNextRow; /* Address of "next_row:" */
8381684424
const char *zIdxName; /* Name of the index */
84425
+ int nColTest; /* Number of columns to test for changes */
8381784426
8381884427
if( pOnlyIdx && pOnlyIdx!=pIdx ) continue;
8381984428
if( pIdx->pPartIdxWhere==0 ) needTableCnt = 0;
8382084429
if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIdx) ){
8382184430
nCol = pIdx->nKeyCol;
8382284431
zIdxName = pTab->zName;
84432
+ nColTest = nCol - 1;
8382384433
}else{
8382484434
nCol = pIdx->nColumn;
8382584435
zIdxName = pIdx->zName;
84436
+ nColTest = pIdx->uniqNotNull ? pIdx->nKeyCol-1 : nCol-1;
8382684437
}
83827
- aGotoChng = sqlite3DbMallocRaw(db, sizeof(int)*(nCol+1));
83828
- if( aGotoChng==0 ) continue;
8382984438
8383084439
/* Populate the register containing the index name. */
8383184440
sqlite3VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, zIdxName, 0);
8383284441
VdbeComment((v, "Analysis for %s.%s", pTab->zName, zIdxName));
8383384442
@@ -83852,11 +84461,11 @@
8385284461
** regPrev(0) = idx(0)
8385384462
** chng_addr_1:
8385484463
** regPrev(1) = idx(1)
8385584464
** ...
8385684465
**
83857
- ** chng_addr_N:
84466
+ ** endDistinctTest:
8385884467
** regRowid = idx(rowid)
8385984468
** stat_push(P, regChng, regRowid)
8386084469
** Next csr
8386184470
** if !eof(csr) goto next_row;
8386284471
**
@@ -83865,24 +84474,27 @@
8386584474
8386684475
/* Make sure there are enough memory cells allocated to accommodate
8386784476
** the regPrev array and a trailing rowid (the rowid slot is required
8386884477
** when building a record to insert into the sample column of
8386984478
** the sqlite_stat4 table. */
83870
- pParse->nMem = MAX(pParse->nMem, regPrev+nCol);
84479
+ pParse->nMem = MAX(pParse->nMem, regPrev+nColTest);
8387184480
8387284481
/* Open a read-only cursor on the index being analyzed. */
8387384482
assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) );
8387484483
sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb);
8387584484
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
8387684485
VdbeComment((v, "%s", pIdx->zName));
8387784486
8387884487
/* Invoke the stat_init() function. The arguments are:
8387984488
**
83880
- ** (1) the number of columns in the index including the rowid,
83881
- ** (2) the number of rows in the index,
84489
+ ** (1) the number of columns in the index including the rowid
84490
+ ** (or for a WITHOUT ROWID table, the number of PK columns),
84491
+ ** (2) the number of columns in the key without the rowid/pk
84492
+ ** (3) the number of rows in the index,
8388284493
**
83883
- ** The second argument is only used for STAT3 and STAT4
84494
+ **
84495
+ ** The third argument is only used for STAT3 and STAT4
8388484496
*/
8388584497
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
8388684498
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+3);
8388784499
#endif
8388884500
sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat4+1);
@@ -83900,56 +84512,73 @@
8390084512
**
8390184513
*/
8390284514
addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
8390384515
VdbeCoverage(v);
8390484516
sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng);
83905
- addrGotoChng0 = sqlite3VdbeAddOp0(v, OP_Goto);
83906
-
83907
- /*
83908
- ** next_row:
83909
- ** regChng = 0
83910
- ** if( idx(0) != regPrev(0) ) goto chng_addr_0
83911
- ** regChng = 1
83912
- ** if( idx(1) != regPrev(1) ) goto chng_addr_1
83913
- ** ...
83914
- ** regChng = N
83915
- ** goto chng_addr_N
83916
- */
8391784517
addrNextRow = sqlite3VdbeCurrentAddr(v);
83918
- for(i=0; i<nCol; i++){
83919
- char *pColl = (char*)sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
83920
- sqlite3VdbeAddOp2(v, OP_Integer, i, regChng);
83921
- sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp);
83922
- aGotoChng[i] =
83923
- sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ);
83924
- sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
83925
- VdbeCoverage(v);
83926
- }
83927
- sqlite3VdbeAddOp2(v, OP_Integer, nCol, regChng);
83928
- aGotoChng[nCol] = sqlite3VdbeAddOp0(v, OP_Goto);
83929
-
83930
- /*
83931
- ** chng_addr_0:
83932
- ** regPrev(0) = idx(0)
83933
- ** chng_addr_1:
83934
- ** regPrev(1) = idx(1)
83935
- ** ...
83936
- */
83937
- sqlite3VdbeJumpHere(v, addrGotoChng0);
83938
- for(i=0; i<nCol; i++){
83939
- sqlite3VdbeJumpHere(v, aGotoChng[i]);
83940
- sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regPrev+i);
83941
- }
83942
-
84518
+
84519
+ if( nColTest>0 ){
84520
+ int endDistinctTest = sqlite3VdbeMakeLabel(v);
84521
+ int *aGotoChng; /* Array of jump instruction addresses */
84522
+ aGotoChng = sqlite3DbMallocRaw(db, sizeof(int)*nColTest);
84523
+ if( aGotoChng==0 ) continue;
84524
+
84525
+ /*
84526
+ ** next_row:
84527
+ ** regChng = 0
84528
+ ** if( idx(0) != regPrev(0) ) goto chng_addr_0
84529
+ ** regChng = 1
84530
+ ** if( idx(1) != regPrev(1) ) goto chng_addr_1
84531
+ ** ...
84532
+ ** regChng = N
84533
+ ** goto endDistinctTest
84534
+ */
84535
+ sqlite3VdbeAddOp0(v, OP_Goto);
84536
+ addrNextRow = sqlite3VdbeCurrentAddr(v);
84537
+ if( nColTest==1 && pIdx->nKeyCol==1 && IsUniqueIndex(pIdx) ){
84538
+ /* For a single-column UNIQUE index, once we have found a non-NULL
84539
+ ** row, we know that all the rest will be distinct, so skip
84540
+ ** subsequent distinctness tests. */
84541
+ sqlite3VdbeAddOp2(v, OP_NotNull, regPrev, endDistinctTest);
84542
+ VdbeCoverage(v);
84543
+ }
84544
+ for(i=0; i<nColTest; i++){
84545
+ char *pColl = (char*)sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
84546
+ sqlite3VdbeAddOp2(v, OP_Integer, i, regChng);
84547
+ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp);
84548
+ aGotoChng[i] =
84549
+ sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ);
84550
+ sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
84551
+ VdbeCoverage(v);
84552
+ }
84553
+ sqlite3VdbeAddOp2(v, OP_Integer, nColTest, regChng);
84554
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, endDistinctTest);
84555
+
84556
+
84557
+ /*
84558
+ ** chng_addr_0:
84559
+ ** regPrev(0) = idx(0)
84560
+ ** chng_addr_1:
84561
+ ** regPrev(1) = idx(1)
84562
+ ** ...
84563
+ */
84564
+ sqlite3VdbeJumpHere(v, addrNextRow-1);
84565
+ for(i=0; i<nColTest; i++){
84566
+ sqlite3VdbeJumpHere(v, aGotoChng[i]);
84567
+ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regPrev+i);
84568
+ }
84569
+ sqlite3VdbeResolveLabel(v, endDistinctTest);
84570
+ sqlite3DbFree(db, aGotoChng);
84571
+ }
84572
+
8394384573
/*
8394484574
** chng_addr_N:
8394584575
** regRowid = idx(rowid) // STAT34 only
8394684576
** stat_push(P, regChng, regRowid) // 3rd parameter STAT34 only
8394784577
** Next csr
8394884578
** if !eof(csr) goto next_row;
8394984579
*/
83950
- sqlite3VdbeJumpHere(v, aGotoChng[nCol]);
8395184580
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
8395284581
assert( regRowid==(regStat4+2) );
8395384582
if( HasRowid(pTab) ){
8395484583
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, regRowid);
8395584584
}else{
@@ -84023,11 +84652,10 @@
8402384652
}
8402484653
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
8402584654
8402684655
/* End of analysis */
8402784656
sqlite3VdbeJumpHere(v, addrRewind);
84028
- sqlite3DbFree(db, aGotoChng);
8402984657
}
8403084658
8403184659
8403284660
/* Create a single sqlite_stat1 entry containing NULL as the index
8403384661
** name and the row count as the content.
@@ -84124,10 +84752,11 @@
8412484752
int i;
8412584753
char *z, *zDb;
8412684754
Table *pTab;
8412784755
Index *pIdx;
8412884756
Token *pTableName;
84757
+ Vdbe *v;
8412984758
8413084759
/* Read the database schema. If an error occurs, leave an error message
8413184760
** and code in pParse and return NULL. */
8413284761
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
8413384762
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
@@ -84171,10 +84800,12 @@
8417184800
}
8417284801
sqlite3DbFree(db, z);
8417384802
}
8417484803
}
8417584804
}
84805
+ v = sqlite3GetVdbe(pParse);
84806
+ if( v ) sqlite3VdbeAddOp0(v, OP_Expire);
8417684807
}
8417784808
8417884809
/*
8417984810
** Used to pass information from the analyzer reader through to the
8418084811
** callback routine.
@@ -84229,18 +84860,23 @@
8422984860
#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
8423084861
assert( pIndex!=0 );
8423184862
#else
8423284863
if( pIndex )
8423384864
#endif
84234
- {
84235
- if( strcmp(z, "unordered")==0 ){
84865
+ while( z[0] ){
84866
+ if( sqlite3_strglob("unordered*", z)==0 ){
8423684867
pIndex->bUnordered = 1;
8423784868
}else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
84238
- int v32 = 0;
84239
- sqlite3GetInt32(z+3, &v32);
84240
- pIndex->szIdxRow = sqlite3LogEst(v32);
84869
+ pIndex->szIdxRow = sqlite3LogEst(sqlite3Atoi(z+3));
8424184870
}
84871
+#ifdef SQLITE_ENABLE_COSTMULT
84872
+ else if( sqlite3_strglob("costmult=[0-9]*",z)==0 ){
84873
+ pIndex->pTable->costMult = sqlite3LogEst(sqlite3Atoi(z+9));
84874
+ }
84875
+#endif
84876
+ while( z[0]!=0 && z[0]!=' ' ) z++;
84877
+ while( z[0]==' ' ) z++;
8424284878
}
8424384879
}
8424484880
8424584881
/*
8424684882
** This callback is invoked once for each index when reading the
@@ -84277,15 +84913,19 @@
8427784913
pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase);
8427884914
}
8427984915
z = argv[2];
8428084916
8428184917
if( pIndex ){
84918
+ pIndex->bUnordered = 0;
8428284919
decodeIntArray((char*)z, pIndex->nKeyCol+1, 0, pIndex->aiRowLogEst, pIndex);
8428384920
if( pIndex->pPartIdxWhere==0 ) pTable->nRowLogEst = pIndex->aiRowLogEst[0];
8428484921
}else{
8428584922
Index fakeIdx;
8428684923
fakeIdx.szIdxRow = pTable->szTabRow;
84924
+#ifdef SQLITE_ENABLE_COSTMULT
84925
+ fakeIdx.pTable = pTable;
84926
+#endif
8428784927
decodeIntArray((char*)z, 1, 0, &pTable->nRowLogEst, &fakeIdx);
8428884928
pTable->szTabRow = fakeIdx.szIdxRow;
8428984929
}
8429084930
8429184931
return 0;
@@ -85557,10 +86197,23 @@
8555786197
}
8555886198
#else
8555986199
#define codeTableLocks(x)
8556086200
#endif
8556186201
86202
+/*
86203
+** Return TRUE if the given yDbMask object is empty - if it contains no
86204
+** 1 bits. This routine is used by the DbMaskAllZero() and DbMaskNotZero()
86205
+** macros when SQLITE_MAX_ATTACHED is greater than 30.
86206
+*/
86207
+#if SQLITE_MAX_ATTACHED>30
86208
+SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask m){
86209
+ int i;
86210
+ for(i=0; i<sizeof(yDbMask); i++) if( m[i] ) return 0;
86211
+ return 1;
86212
+}
86213
+#endif
86214
+
8556286215
/*
8556386216
** This routine is called after a single SQL statement has been
8556486217
** parsed and a VDBE program to execute that statement has been
8556586218
** prepared. This routine puts the finishing touches on the
8556686219
** VDBE program and resets the pParse structure for the next
@@ -85593,22 +86246,23 @@
8559386246
** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are
8559486247
** set for each database that is used. Generate code to start a
8559586248
** transaction on each used database and to verify the schema cookie
8559686249
** on each used database.
8559786250
*/
85598
- if( db->mallocFailed==0 && (pParse->cookieMask || pParse->pConstExpr) ){
85599
- yDbMask mask;
86251
+ if( db->mallocFailed==0
86252
+ && (DbMaskNonZero(pParse->cookieMask) || pParse->pConstExpr)
86253
+ ){
8560086254
int iDb, i;
8560186255
assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init );
8560286256
sqlite3VdbeJumpHere(v, 0);
85603
- for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){
85604
- if( (mask & pParse->cookieMask)==0 ) continue;
86257
+ for(iDb=0; iDb<db->nDb; iDb++){
86258
+ if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue;
8560586259
sqlite3VdbeUsesBtree(v, iDb);
8560686260
sqlite3VdbeAddOp4Int(v,
8560786261
OP_Transaction, /* Opcode */
8560886262
iDb, /* P1 */
85609
- (mask & pParse->writeMask)!=0, /* P2 */
86263
+ DbMaskTest(pParse->writeMask,iDb), /* P2 */
8561086264
pParse->cookieValue[iDb], /* P3 */
8561186265
db->aDb[iDb].pSchema->iGeneration /* P4 */
8561286266
);
8561386267
if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1);
8561486268
}
@@ -85660,11 +86314,11 @@
8566086314
}
8566186315
pParse->nTab = 0;
8566286316
pParse->nMem = 0;
8566386317
pParse->nSet = 0;
8566486318
pParse->nVar = 0;
85665
- pParse->cookieMask = 0;
86319
+ DbMaskZero(pParse->cookieMask);
8566686320
}
8566786321
8566886322
/*
8566986323
** Run the parser and code generator recursively in order to generate
8567086324
** code for the SQL statement given onto the end of the pParse context
@@ -87560,11 +88214,11 @@
8756088214
pTable->aCol = pSelTab->aCol;
8756188215
pSelTab->nCol = 0;
8756288216
pSelTab->aCol = 0;
8756388217
sqlite3DeleteTable(db, pSelTab);
8756488218
assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) );
87565
- pTable->pSchema->flags |= DB_UnresetViews;
88219
+ pTable->pSchema->schemaFlags |= DB_UnresetViews;
8756688220
}else{
8756788221
pTable->nCol = 0;
8756888222
nErr++;
8756988223
}
8757088224
sqlite3SelectDelete(db, pSel);
@@ -88137,16 +88791,16 @@
8813788791
(char *)pKey, P4_KEYINFO);
8813888792
sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
8813988793
8814088794
addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v);
8814188795
assert( pKey!=0 || db->mallocFailed || pParse->nErr );
88142
- if( pIndex->onError!=OE_None && pKey!=0 ){
88796
+ if( IsUniqueIndex(pIndex) && pKey!=0 ){
8814388797
int j2 = sqlite3VdbeCurrentAddr(v) + 3;
8814488798
sqlite3VdbeAddOp2(v, OP_Goto, 0, j2);
8814588799
addr2 = sqlite3VdbeCurrentAddr(v);
8814688800
sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord,
88147
- pKey->nField - pIndex->nKeyCol); VdbeCoverage(v);
88801
+ pIndex->nKeyCol); VdbeCoverage(v);
8814888802
sqlite3UniqueConstraint(pParse, OE_Abort, pIndex);
8814988803
}else{
8815088804
addr2 = sqlite3VdbeCurrentAddr(v);
8815188805
}
8815288806
sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord);
@@ -88534,13 +89188,13 @@
8853489188
** considered distinct and both result in separate indices.
8853589189
*/
8853689190
Index *pIdx;
8853789191
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
8853889192
int k;
88539
- assert( pIdx->onError!=OE_None );
89193
+ assert( IsUniqueIndex(pIdx) );
8854089194
assert( pIdx->idxType!=SQLITE_IDXTYPE_APPDEF );
88541
- assert( pIndex->onError!=OE_None );
89195
+ assert( IsUniqueIndex(pIndex) );
8854289196
8854389197
if( pIdx->nKeyCol!=pIndex->nKeyCol ) continue;
8854489198
for(k=0; k<pIdx->nKeyCol; k++){
8854589199
const char *z1;
8854689200
const char *z2;
@@ -88727,11 +89381,11 @@
8872789381
for(i=nCopy+1; i<=pIdx->nKeyCol; i++){
8872889382
a[i] = 23; assert( 23==sqlite3LogEst(5) );
8872989383
}
8873089384
8873189385
assert( 0==sqlite3LogEst(1) );
88732
- if( pIdx->onError!=OE_None ) a[pIdx->nKeyCol] = 0;
89386
+ if( IsUniqueIndex(pIdx) ) a[pIdx->nKeyCol] = 0;
8873389387
}
8873489388
8873589389
/*
8873689390
** This routine will drop an existing named index. This routine
8873789391
** implements the DROP INDEX statement.
@@ -89287,19 +89941,17 @@
8928789941
** later, by sqlite3FinishCoding().
8928889942
*/
8928989943
SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
8929089944
Parse *pToplevel = sqlite3ParseToplevel(pParse);
8929189945
sqlite3 *db = pToplevel->db;
89292
- yDbMask mask;
8929389946
8929489947
assert( iDb>=0 && iDb<db->nDb );
8929589948
assert( db->aDb[iDb].pBt!=0 || iDb==1 );
8929689949
assert( iDb<SQLITE_MAX_ATTACHED+2 );
8929789950
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
89298
- mask = ((yDbMask)1)<<iDb;
89299
- if( (pToplevel->cookieMask & mask)==0 ){
89300
- pToplevel->cookieMask |= mask;
89951
+ if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){
89952
+ DbMaskSet(pToplevel->cookieMask, iDb);
8930189953
pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie;
8930289954
if( !OMIT_TEMPDB && iDb==1 ){
8930389955
sqlite3OpenTempDatabase(pToplevel);
8930489956
}
8930589957
}
@@ -89334,11 +89986,11 @@
8933489986
** necessary to undo a write and the checkpoint should not be set.
8933589987
*/
8933689988
SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
8933789989
Parse *pToplevel = sqlite3ParseToplevel(pParse);
8933889990
sqlite3CodeVerifySchema(pParse, iDb);
89339
- pToplevel->writeMask |= ((yDbMask)1)<<iDb;
89991
+ DbMaskSet(pToplevel->writeMask, iDb);
8934089992
pToplevel->isMultiWrite |= setStatement;
8934189993
}
8934289994
8934389995
/*
8934489996
** Indicate that the statement currently under construction might write
@@ -90141,13 +90793,13 @@
9014190793
sqlite3DeleteTable(0, pTab);
9014290794
}
9014390795
sqlite3HashClear(&temp1);
9014490796
sqlite3HashClear(&pSchema->fkeyHash);
9014590797
pSchema->pSeqTab = 0;
90146
- if( pSchema->flags & DB_SchemaLoaded ){
90798
+ if( pSchema->schemaFlags & DB_SchemaLoaded ){
9014790799
pSchema->iGeneration++;
90148
- pSchema->flags &= ~DB_SchemaLoaded;
90800
+ pSchema->schemaFlags &= ~DB_SchemaLoaded;
9014990801
}
9015090802
}
9015190803
9015290804
/*
9015390805
** Find and return the schema associated with a BTree. Create
@@ -91022,16 +91674,13 @@
9102291674
** May you do good and not evil.
9102391675
** May you find forgiveness for yourself and forgive others.
9102491676
** May you share freely, never taking more than you give.
9102591677
**
9102691678
*************************************************************************
91027
-** This file contains the C functions that implement various SQL
91028
-** functions of SQLite.
91029
-**
91030
-** There is only one exported symbol in this file - the function
91031
-** sqliteRegisterBuildinFunctions() found at the bottom of the file.
91032
-** All other code has file scope.
91679
+** This file contains the C-language implementions for many of the SQL
91680
+** functions of SQLite. (Some function, and in particular the date and
91681
+** time functions, are implemented separately.)
9103391682
*/
9103491683
/* #include <stdlib.h> */
9103591684
/* #include <assert.h> */
9103691685
9103791686
/*
@@ -92989,11 +93638,11 @@
9298993638
if( !aiCol ) return 1;
9299093639
*paiCol = aiCol;
9299193640
}
9299293641
9299393642
for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){
92994
- if( pIdx->nKeyCol==nCol && pIdx->onError!=OE_None ){
93643
+ if( pIdx->nKeyCol==nCol && IsUniqueIndex(pIdx) ){
9299593644
/* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number
9299693645
** of columns. If each indexed column corresponds to a foreign key
9299793646
** column of pFKey, then this index is a winner. */
9299893647
9299993648
if( zKey==0 ){
@@ -96015,11 +96664,11 @@
9601596664
){
9601696665
return 0; /* Default values must be the same for all columns */
9601796666
}
9601896667
}
9601996668
for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
96020
- if( pDestIdx->onError!=OE_None ){
96669
+ if( IsUniqueIndex(pDestIdx) ){
9602196670
destHasUniqueIdx = 1;
9602296671
}
9602396672
for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){
9602496673
if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
9602596674
}
@@ -96245,10 +96894,13 @@
9624596894
goto exec_out;
9624696895
}
9624796896
}
9624896897
}
9624996898
if( xCallback(pArg, nCol, azVals, azCols) ){
96899
+ /* EVIDENCE-OF: R-38229-40159 If the callback function to
96900
+ ** sqlite3_exec() returns non-zero, then sqlite3_exec() will
96901
+ ** return SQLITE_ABORT. */
9625096902
rc = SQLITE_ABORT;
9625196903
sqlite3VdbeFinalize((Vdbe *)pStmt);
9625296904
pStmt = 0;
9625396905
sqlite3Error(db, SQLITE_ABORT, 0);
9625496906
goto exec_out;
@@ -98022,11 +98674,11 @@
9802298674
** Note that the values returned are one less that the values that
9802398675
** should be passed into sqlite3BtreeSetSafetyLevel(). The is done
9802498676
** to support legacy SQL code. The safety level used to be boolean
9802598677
** and older scripts may have used numbers 0 for OFF and 1 for ON.
9802698678
*/
98027
-static u8 getSafetyLevel(const char *z, int omitFull, int dflt){
98679
+static u8 getSafetyLevel(const char *z, int omitFull, u8 dflt){
9802898680
/* 123456789 123456789 */
9802998681
static const char zText[] = "onoffalseyestruefull";
9803098682
static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16};
9803198683
static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 4};
9803298684
static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 2};
@@ -98044,11 +98696,11 @@
9804498696
}
9804598697
9804698698
/*
9804798699
** Interpret the given string as a boolean value.
9804898700
*/
98049
-SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z, int dflt){
98701
+SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z, u8 dflt){
9805098702
return getSafetyLevel(z,1,dflt)!=0;
9805198703
}
9805298704
9805398705
/* The sqlite3GetBoolean() function is used by other modules but the
9805498706
** remainder of this file is specific to PRAGMA processing. So omit
@@ -98590,11 +99242,11 @@
9859099242
*/
9859199243
case PragTyp_JOURNAL_SIZE_LIMIT: {
9859299244
Pager *pPager = sqlite3BtreePager(pDb->pBt);
9859399245
i64 iLimit = -2;
9859499246
if( zRight ){
98595
- sqlite3Atoi64(zRight, &iLimit, sqlite3Strlen30(zRight), SQLITE_UTF8);
99247
+ sqlite3DecOrHexToI64(zRight, &iLimit);
9859699248
if( iLimit<-1 ) iLimit = -1;
9859799249
}
9859899250
iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit);
9859999251
returnSingleInt(pParse, "journal_size_limit", iLimit);
9860099252
break;
@@ -98718,11 +99370,11 @@
9871899370
sqlite3_int64 sz;
9871999371
#if SQLITE_MAX_MMAP_SIZE>0
9872099372
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
9872199373
if( zRight ){
9872299374
int ii;
98723
- sqlite3Atoi64(zRight, &sz, sqlite3Strlen30(zRight), SQLITE_UTF8);
99375
+ sqlite3DecOrHexToI64(zRight, &sz);
9872499376
if( sz<0 ) sz = sqlite3GlobalConfig.szMmap;
9872599377
if( pId2->n==0 ) db->szMmap = sz;
9872699378
for(ii=db->nDb-1; ii>=0; ii--){
9872799379
if( db->aDb[ii].pBt && (ii==iDb || pId2->n==0) ){
9872899380
sqlite3BtreeSetMmapLimit(db->aDb[ii].pBt, sz);
@@ -99086,11 +99738,11 @@
9908699738
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
9908799739
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
9908899740
for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){
9908999741
sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
9909099742
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
99091
- sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);
99743
+ sqlite3VdbeAddOp2(v, OP_Integer, IsUniqueIndex(pIdx), 3);
9909299744
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
9909399745
}
9909499746
}
9909599747
}
9909699748
break;
@@ -99336,13 +99988,12 @@
9933699988
** messages have been generated, output OK. Otherwise output the
9933799989
** error message
9933899990
*/
9933999991
static const int iLn = VDBE_OFFSET_LINENO(2);
9934099992
static const VdbeOpList endCode[] = {
99341
- { OP_AddImm, 1, 0, 0}, /* 0 */
99342
- { OP_IfNeg, 1, 0, 0}, /* 1 */
99343
- { OP_String8, 0, 3, 0}, /* 2 */
99993
+ { OP_IfNeg, 1, 0, 0}, /* 0 */
99994
+ { OP_String8, 0, 3, 0}, /* 1 */
9934499995
{ OP_ResultRow, 3, 1, 0},
9934599996
};
9934699997
9934799998
int isQuick = (sqlite3Tolower(zLeft[0])=='q');
9934899999
@@ -99450,32 +100101,80 @@
99450100101
sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */
99451100102
}
99452100103
pParse->nMem = MAX(pParse->nMem, 8+j);
99453100104
sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v);
99454100105
loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1);
100106
+ /* Verify that all NOT NULL columns really are NOT NULL */
100107
+ for(j=0; j<pTab->nCol; j++){
100108
+ char *zErr;
100109
+ int jmp2, jmp3;
100110
+ if( j==pTab->iPKey ) continue;
100111
+ if( pTab->aCol[j].notNull==0 ) continue;
100112
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
100113
+ sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
100114
+ jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
100115
+ sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
100116
+ zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
100117
+ pTab->aCol[j].zName);
100118
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
100119
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
100120
+ jmp3 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v);
100121
+ sqlite3VdbeAddOp0(v, OP_Halt);
100122
+ sqlite3VdbeJumpHere(v, jmp2);
100123
+ sqlite3VdbeJumpHere(v, jmp3);
100124
+ }
100125
+ /* Validate index entries for the current row */
99455100126
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
99456
- int jmp2, jmp3, jmp4;
100127
+ int jmp2, jmp3, jmp4, jmp5;
100128
+ int ckUniq = sqlite3VdbeMakeLabel(v);
99457100129
if( pPk==pIdx ) continue;
99458100130
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
99459100131
pPrior, r1);
99460100132
pPrior = pIdx;
99461100133
sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */
99462
- jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, 0, r1,
100134
+ /* Verify that an index entry exists for the current table row */
100135
+ jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
99463100136
pIdx->nColumn); VdbeCoverage(v);
99464100137
sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
99465100138
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, "row ", P4_STATIC);
99466100139
sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
99467
- sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, " missing from index ",
99468
- P4_STATIC);
100140
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0,
100141
+ " missing from index ", P4_STATIC);
99469100142
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
99470
- sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, pIdx->zName, P4_TRANSIENT);
100143
+ jmp5 = sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0,
100144
+ pIdx->zName, P4_TRANSIENT);
99471100145
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
99472100146
sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
99473100147
jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v);
99474100148
sqlite3VdbeAddOp0(v, OP_Halt);
99475
- sqlite3VdbeJumpHere(v, jmp4);
99476100149
sqlite3VdbeJumpHere(v, jmp2);
100150
+ /* For UNIQUE indexes, verify that only one entry exists with the
100151
+ ** current key. The entry is unique if (1) any column is NULL
100152
+ ** or (2) the next entry has a different key */
100153
+ if( IsUniqueIndex(pIdx) ){
100154
+ int uniqOk = sqlite3VdbeMakeLabel(v);
100155
+ int jmp6;
100156
+ int kk;
100157
+ for(kk=0; kk<pIdx->nKeyCol; kk++){
100158
+ int iCol = pIdx->aiColumn[kk];
100159
+ assert( iCol>=0 && iCol<pTab->nCol );
100160
+ if( pTab->aCol[iCol].notNull ) continue;
100161
+ sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk);
100162
+ VdbeCoverage(v);
100163
+ }
100164
+ jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v);
100165
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, uniqOk);
100166
+ sqlite3VdbeJumpHere(v, jmp6);
100167
+ sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1,
100168
+ pIdx->nKeyCol); VdbeCoverage(v);
100169
+ sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
100170
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
100171
+ "non-unique entry in index ", P4_STATIC);
100172
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, jmp5);
100173
+ sqlite3VdbeResolveLabel(v, uniqOk);
100174
+ }
100175
+ sqlite3VdbeJumpHere(v, jmp4);
99477100176
sqlite3ResolvePartIdxLabel(pParse, jmp3);
99478100177
}
99479100178
sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
99480100179
sqlite3VdbeJumpHere(v, loopTop-1);
99481100180
#ifndef SQLITE_OMIT_BTREECOUNT
@@ -99496,13 +100195,13 @@
99496100195
}
99497100196
#endif /* SQLITE_OMIT_BTREECOUNT */
99498100197
}
99499100198
}
99500100199
addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
99501
- sqlite3VdbeChangeP2(v, addr, -mxErr);
99502
- sqlite3VdbeJumpHere(v, addr+1);
99503
- sqlite3VdbeChangeP4(v, addr+2, "ok", P4_STATIC);
100200
+ sqlite3VdbeChangeP3(v, addr, -mxErr);
100201
+ sqlite3VdbeJumpHere(v, addr);
100202
+ sqlite3VdbeChangeP4(v, addr+1, "ok", P4_STATIC);
99504100203
}
99505100204
break;
99506100205
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
99507100206
99508100207
#ifndef SQLITE_OMIT_UTF16
@@ -99761,11 +100460,11 @@
99761100460
** Call sqlite3_soft_heap_limit64(N). Return the result. If N is omitted,
99762100461
** use -1.
99763100462
*/
99764100463
case PragTyp_SOFT_HEAP_LIMIT: {
99765100464
sqlite3_int64 N;
99766
- if( zRight && sqlite3Atoi64(zRight, &N, 1000000, SQLITE_UTF8)==SQLITE_OK ){
100465
+ if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){
99767100466
sqlite3_soft_heap_limit64(N);
99768100467
}
99769100468
returnSingleInt(pParse, "soft_heap_limit", sqlite3_soft_heap_limit64(-1));
99770100469
break;
99771100470
}
@@ -101284,12 +101983,11 @@
101284101983
int iOffset, /* Register holding the offset counter */
101285101984
int iContinue /* Jump here to skip the current record */
101286101985
){
101287101986
if( iOffset>0 ){
101288101987
int addr;
101289
- sqlite3VdbeAddOp2(v, OP_AddImm, iOffset, -1);
101290
- addr = sqlite3VdbeAddOp1(v, OP_IfNeg, iOffset); VdbeCoverage(v);
101988
+ addr = sqlite3VdbeAddOp3(v, OP_IfNeg, iOffset, 0, -1); VdbeCoverage(v);
101291101989
sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue);
101292101990
VdbeComment((v, "skip OFFSET records"));
101293101991
sqlite3VdbeJumpHere(v, addr);
101294101992
}
101295101993
}
@@ -101450,11 +102148,11 @@
101450102148
VdbeCoverage(v);
101451102149
}
101452102150
sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
101453102151
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
101454102152
}
101455
- assert( sqlite3VdbeCurrentAddr(v)==iJump );
102153
+ assert( sqlite3VdbeCurrentAddr(v)==iJump || pParse->db->mallocFailed );
101456102154
sqlite3VdbeAddOp3(v, OP_Copy, regResult, regPrev, nResultCol-1);
101457102155
break;
101458102156
}
101459102157
101460102158
case WHERE_DISTINCT_UNIQUE: {
@@ -107917,11 +108615,12 @@
107917108615
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey);
107918108616
VdbeCoverageNeverTaken(v);
107919108617
}
107920108618
labelContinue = labelBreak;
107921108619
sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak);
107922
- VdbeCoverage(v);
108620
+ VdbeCoverageIf(v, pPk==0);
108621
+ VdbeCoverageIf(v, pPk!=0);
107923108622
}else if( pPk ){
107924108623
labelContinue = sqlite3VdbeMakeLabel(v);
107925108624
sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v);
107926108625
addrTop = sqlite3VdbeAddOp2(v, OP_RowKey, iEph, regKey);
107927108626
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0);
@@ -109927,10 +110626,11 @@
109927110626
struct WherePath {
109928110627
Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */
109929110628
Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */
109930110629
LogEst nRow; /* Estimated number of rows generated by this path */
109931110630
LogEst rCost; /* Total cost of this path */
110631
+ LogEst rUnsorted; /* Total cost of this path ignoring sorting costs */
109932110632
i8 isOrdered; /* No. of ORDER BY terms satisfied. -1 for unknown */
109933110633
WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */
109934110634
};
109935110635
109936110636
/*
@@ -111657,11 +112357,11 @@
111657112357
**
111658112358
** 3. All of those index columns for which the WHERE clause does not
111659112359
** contain a "col=X" term are subject to a NOT NULL constraint.
111660112360
*/
111661112361
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
111662
- if( pIdx->onError==OE_None ) continue;
112362
+ if( !IsUniqueIndex(pIdx) ) continue;
111663112363
for(i=0; i<pIdx->nKeyCol; i++){
111664112364
i16 iCol = pIdx->aiColumn[i];
111665112365
if( 0==findTerm(pWC, iBase, iCol, ~(Bitmask)0, WO_EQ, pIdx) ){
111666112366
int iIdxCol = findIndexCol(pParse, pDistinct, iBase, pIdx, i);
111667112367
if( iIdxCol<0 || pTab->aCol[iCol].notNull==0 ){
@@ -112234,11 +112934,12 @@
112234112934
int nEq = pLoop->u.btree.nEq;
112235112935
sqlite3 *db = pParse->db;
112236112936
int nLower = -1;
112237112937
int nUpper = p->nSample+1;
112238112938
int rc = SQLITE_OK;
112239
- u8 aff = p->pTable->aCol[ p->aiColumn[nEq] ].affinity;
112939
+ int iCol = p->aiColumn[nEq];
112940
+ u8 aff = iCol>=0 ? p->pTable->aCol[iCol].affinity : SQLITE_AFF_INTEGER;
112240112941
CollSeq *pColl;
112241112942
112242112943
sqlite3_value *p1 = 0; /* Value extracted from pLower */
112243112944
sqlite3_value *p2 = 0; /* Value extracted from pUpper */
112244112945
sqlite3_value *pVal = 0; /* Value extracted from record */
@@ -112708,11 +113409,11 @@
112708113409
testcase( bRev );
112709113410
bRev = !bRev;
112710113411
}
112711113412
assert( pX->op==TK_IN );
112712113413
iReg = iTarget;
112713
- eType = sqlite3FindInIndex(pParse, pX, 0);
113414
+ eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0);
112714113415
if( eType==IN_INDEX_INDEX_DESC ){
112715113416
testcase( bRev );
112716113417
bRev = !bRev;
112717113418
}
112718113419
iTab = pX->iTable;
@@ -113609,10 +114310,11 @@
113609114310
int regRowid = 0; /* Register holding rowid */
113610114311
int iLoopBody = sqlite3VdbeMakeLabel(v); /* Start of loop body */
113611114312
int iRetInit; /* Address of regReturn init */
113612114313
int untestedTerms = 0; /* Some terms not completely tested */
113613114314
int ii; /* Loop counter */
114315
+ u16 wctrlFlags; /* Flags for sub-WHERE clause */
113614114316
Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
113615114317
Table *pTab = pTabItem->pTab;
113616114318
113617114319
pTerm = pLoop->aLTerm[0];
113618114320
assert( pTerm!=0 );
@@ -113704,10 +114406,12 @@
113704114406
113705114407
/* Run a separate WHERE clause for each term of the OR clause. After
113706114408
** eliminating duplicates from other WHERE clauses, the action for each
113707114409
** sub-WHERE clause is to to invoke the main loop body as a subroutine.
113708114410
*/
114411
+ wctrlFlags = WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
114412
+ WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY;
113709114413
for(ii=0; ii<pOrWc->nTerm; ii++){
113710114414
WhereTerm *pOrTerm = &pOrWc->a[ii];
113711114415
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
113712114416
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
113713114417
Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
@@ -113716,12 +114420,11 @@
113716114420
pAndExpr->pLeft = pOrExpr;
113717114421
pOrExpr = pAndExpr;
113718114422
}
113719114423
/* Loop through table entries that match term pOrTerm. */
113720114424
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
113721
- WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
113722
- WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY, iCovCur);
114425
+ wctrlFlags, iCovCur);
113723114426
assert( pSubWInfo || pParse->nErr || db->mallocFailed );
113724114427
if( pSubWInfo ){
113725114428
WhereLoop *pSubLoop;
113726114429
explainOneScan(
113727114430
pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
@@ -113808,10 +114511,11 @@
113808114511
&& (ii==0 || pSubLoop->u.btree.pIndex==pCov)
113809114512
&& (HasRowid(pTab) || !IsPrimaryKeyIndex(pSubLoop->u.btree.pIndex))
113810114513
){
113811114514
assert( pSubWInfo->a[0].iIdxCur==iCovCur );
113812114515
pCov = pSubLoop->u.btree.pIndex;
114516
+ wctrlFlags |= WHERE_REOPEN_IDX;
113813114517
}else{
113814114518
pCov = 0;
113815114519
}
113816114520
113817114521
/* Finish the loop through table entries that match term pOrTerm. */
@@ -114414,10 +115118,20 @@
114414115118
pLoop->nOut += (pTerm->truthProb<=0 ? pTerm->truthProb : -1);
114415115119
}
114416115120
}
114417115121
}
114418115122
115123
+/*
115124
+** Adjust the cost C by the costMult facter T. This only occurs if
115125
+** compiled with -DSQLITE_ENABLE_COSTMULT
115126
+*/
115127
+#ifdef SQLITE_ENABLE_COSTMULT
115128
+# define ApplyCostMultiplier(C,T) C += T
115129
+#else
115130
+# define ApplyCostMultiplier(C,T)
115131
+#endif
115132
+
114419115133
/*
114420115134
** We have so far matched pBuilder->pNew->u.btree.nEq terms of the
114421115135
** index pIndex. Try to match one more.
114422115136
**
114423115137
** When this function is called, pBuilder->pNew->nOut contains the
@@ -114549,11 +115263,11 @@
114549115263
** changes "x IN (?)" into "x=?". */
114550115264
114551115265
}else if( eOp & (WO_EQ) ){
114552115266
pNew->wsFlags |= WHERE_COLUMN_EQ;
114553115267
if( iCol<0 || (nInMul==0 && pNew->u.btree.nEq==pProbe->nKeyCol-1) ){
114554
- if( iCol>=0 && pProbe->onError==OE_None ){
115268
+ if( iCol>=0 && !IsUniqueIndex(pProbe) ){
114555115269
pNew->wsFlags |= WHERE_UNQ_WANTED;
114556115270
}else{
114557115271
pNew->wsFlags |= WHERE_ONEROW;
114558115272
}
114559115273
}
@@ -114610,11 +115324,10 @@
114610115324
testcase( eOp & WO_ISNULL );
114611115325
rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut);
114612115326
}else{
114613115327
rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut);
114614115328
}
114615
- assert( rc!=SQLITE_OK || nOut>0 );
114616115329
if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
114617115330
if( rc!=SQLITE_OK ) break; /* Jump out of the pTerm loop */
114618115331
if( nOut ){
114619115332
pNew->nOut = sqlite3LogEst(nOut);
114620115333
if( pNew->nOut>saved_nOut ) pNew->nOut = saved_nOut;
@@ -114642,10 +115355,11 @@
114642115355
rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow;
114643115356
pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx);
114644115357
if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
114645115358
pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16);
114646115359
}
115360
+ ApplyCostMultiplier(pNew->rRun, pProbe->pTable->costMult);
114647115361
114648115362
nOutUnadjusted = pNew->nOut;
114649115363
pNew->rRun += nInMul + nIn;
114650115364
pNew->nOut += nInMul + nIn;
114651115365
whereLoopOutputAdjust(pBuilder->pWC, pNew);
@@ -114761,10 +115475,18 @@
114761115475
** cost = nSeek * (log(nRow) + (K+3.0) * nVisit) // non-covering index
114762115476
**
114763115477
** Normally, nSeek is 1. nSeek values greater than 1 come about if the
114764115478
** WHERE clause includes "x IN (....)" terms used in place of "x=?". Or when
114765115479
** implicit "x IN (SELECT x FROM tbl)" terms are added for skip-scans.
115480
+**
115481
+** The estimated values (nRow, nVisit, nSeek) often contain a large amount
115482
+** of uncertainty. For this reason, scoring is designed to pick plans that
115483
+** "do the least harm" if the estimates are inaccurate. For example, a
115484
+** log(nRow) factor is omitted from a non-covering index scan in order to
115485
+** bias the scoring in favor of using an index, since the worst-case
115486
+** performance of using an index is far better than the worst-case performance
115487
+** of a full table scan.
114766115488
*/
114767115489
static int whereLoopAddBtree(
114768115490
WhereLoopBuilder *pBuilder, /* WHERE clause information */
114769115491
Bitmask mExtra /* Extra prerequesites for using this table */
114770115492
){
@@ -114848,10 +115570,11 @@
114848115570
pNew->aLTerm[0] = pTerm;
114849115571
/* TUNING: One-time cost for computing the automatic index is
114850115572
** approximately 7*N*log2(N) where N is the number of rows in
114851115573
** the table being indexed. */
114852115574
pNew->rSetup = rLogSize + rSize + 28; assert( 28==sqlite3LogEst(7) );
115575
+ ApplyCostMultiplier(pNew->rSetup, pTab->costMult);
114853115576
/* TUNING: Each index lookup yields 20 rows in the table. This
114854115577
** is more than the usual guess of 10 rows, since we have no way
114855115578
** of knowning how selective the index will ultimately be. It would
114856115579
** not be unreasonable to make this value much larger. */
114857115580
pNew->nOut = 43; assert( 43==sqlite3LogEst(20) );
@@ -114889,10 +115612,11 @@
114889115612
114890115613
/* Full table scan */
114891115614
pNew->iSortIdx = b ? iSortIdx : 0;
114892115615
/* TUNING: Cost of full table scan is (N*3.0). */
114893115616
pNew->rRun = rSize + 16;
115617
+ ApplyCostMultiplier(pNew->rRun, pTab->costMult);
114894115618
whereLoopOutputAdjust(pWC, pNew);
114895115619
rc = whereLoopInsert(pBuilder, pNew);
114896115620
pNew->nOut = rSize;
114897115621
if( rc ) break;
114898115622
}else{
@@ -114924,11 +115648,11 @@
114924115648
** also add the cost of visiting table rows (N*3.0). */
114925115649
pNew->rRun = rSize + 1 + (15*pProbe->szIdxRow)/pTab->szTabRow;
114926115650
if( m!=0 ){
114927115651
pNew->rRun = sqlite3LogEstAdd(pNew->rRun, rSize+16);
114928115652
}
114929
-
115653
+ ApplyCostMultiplier(pNew->rRun, pTab->costMult);
114930115654
whereLoopOutputAdjust(pWC, pNew);
114931115655
rc = whereLoopInsert(pBuilder, pNew);
114932115656
pNew->nOut = rSize;
114933115657
if( rc ) break;
114934115658
}
@@ -115394,11 +116118,11 @@
115394116118
}else{
115395116119
nKeyCol = pIndex->nKeyCol;
115396116120
nColumn = pIndex->nColumn;
115397116121
assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) );
115398116122
assert( pIndex->aiColumn[nColumn-1]==(-1) || !HasRowid(pIndex->pTable));
115399
- isOrderDistinct = pIndex->onError!=OE_None;
116123
+ isOrderDistinct = IsUniqueIndex(pIndex);
115400116124
}
115401116125
115402116126
/* Loop through all columns of the index and deal with the ones
115403116127
** that are not constrained by == or IN.
115404116128
*/
@@ -115562,10 +116286,49 @@
115562116286
if( pLast ) zName[i++] = pLast->cId;
115563116287
zName[i] = 0;
115564116288
return zName;
115565116289
}
115566116290
#endif
116291
+
116292
+/*
116293
+** Return the cost of sorting nRow rows, assuming that the keys have
116294
+** nOrderby columns and that the first nSorted columns are already in
116295
+** order.
116296
+*/
116297
+static LogEst whereSortingCost(
116298
+ WhereInfo *pWInfo,
116299
+ LogEst nRow,
116300
+ int nOrderBy,
116301
+ int nSorted
116302
+){
116303
+ /* TUNING: Estimated cost of a full external sort, where N is
116304
+ ** the number of rows to sort is:
116305
+ **
116306
+ ** cost = (3.0 * N * log(N)).
116307
+ **
116308
+ ** Or, if the order-by clause has X terms but only the last Y
116309
+ ** terms are out of order, then block-sorting will reduce the
116310
+ ** sorting cost to:
116311
+ **
116312
+ ** cost = (3.0 * N * log(N)) * (Y/X)
116313
+ **
116314
+ ** The (Y/X) term is implemented using stack variable rScale
116315
+ ** below. */
116316
+ LogEst rScale, rSortCost;
116317
+ assert( nOrderBy>0 && 66==sqlite3LogEst(100) );
116318
+ rScale = sqlite3LogEst((nOrderBy-nSorted)*100/nOrderBy) - 66;
116319
+ rSortCost = nRow + estLog(nRow) + rScale + 16;
116320
+
116321
+ /* TUNING: The cost of implementing DISTINCT using a B-TREE is
116322
+ ** similar but with a larger constant of proportionality.
116323
+ ** Multiply by an additional factor of 3.0. */
116324
+ if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
116325
+ rSortCost += 16;
116326
+ }
116327
+
116328
+ return rSortCost;
116329
+}
115567116330
115568116331
/*
115569116332
** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
115570116333
** attempts to find the lowest cost path that visits each WhereLoop
115571116334
** once. This path is then loaded into the pWInfo->a[].pWLoop fields.
@@ -115584,139 +116347,170 @@
115584116347
sqlite3 *db; /* The database connection */
115585116348
int iLoop; /* Loop counter over the terms of the join */
115586116349
int ii, jj; /* Loop counters */
115587116350
int mxI = 0; /* Index of next entry to replace */
115588116351
int nOrderBy; /* Number of ORDER BY clause terms */
115589
- LogEst rCost; /* Cost of a path */
115590
- LogEst nOut; /* Number of outputs */
115591116352
LogEst mxCost = 0; /* Maximum cost of a set of paths */
116353
+ LogEst mxUnsorted = 0; /* Maximum unsorted cost of a set of path */
115592116354
int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
115593116355
WherePath *aFrom; /* All nFrom paths at the previous level */
115594116356
WherePath *aTo; /* The nTo best paths at the current level */
115595116357
WherePath *pFrom; /* An element of aFrom[] that we are working on */
115596116358
WherePath *pTo; /* An element of aTo[] that we are working on */
115597116359
WhereLoop *pWLoop; /* One of the WhereLoop objects */
115598116360
WhereLoop **pX; /* Used to divy up the pSpace memory */
116361
+ LogEst *aSortCost = 0; /* Sorting and partial sorting costs */
115599116362
char *pSpace; /* Temporary memory used by this routine */
116363
+ int nSpace; /* Bytes of space allocated at pSpace */
115600116364
115601116365
pParse = pWInfo->pParse;
115602116366
db = pParse->db;
115603116367
nLoop = pWInfo->nLevel;
115604116368
/* TUNING: For simple queries, only the best path is tracked.
115605116369
** For 2-way joins, the 5 best paths are followed.
115606116370
** For joins of 3 or more tables, track the 10 best paths */
115607116371
mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10);
115608116372
assert( nLoop<=pWInfo->pTabList->nSrc );
115609
- WHERETRACE(0x002, ("---- begin solver\n"));
116373
+ WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d)\n", nRowEst));
115610116374
115611
- /* Allocate and initialize space for aTo and aFrom */
115612
- ii = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
115613
- pSpace = sqlite3DbMallocRaw(db, ii);
116375
+ /* If nRowEst is zero and there is an ORDER BY clause, ignore it. In this
116376
+ ** case the purpose of this call is to estimate the number of rows returned
116377
+ ** by the overall query. Once this estimate has been obtained, the caller
116378
+ ** will invoke this function a second time, passing the estimate as the
116379
+ ** nRowEst parameter. */
116380
+ if( pWInfo->pOrderBy==0 || nRowEst==0 ){
116381
+ nOrderBy = 0;
116382
+ }else{
116383
+ nOrderBy = pWInfo->pOrderBy->nExpr;
116384
+ }
116385
+
116386
+ /* Allocate and initialize space for aTo, aFrom and aSortCost[] */
116387
+ nSpace = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
116388
+ nSpace += sizeof(LogEst) * nOrderBy;
116389
+ pSpace = sqlite3DbMallocRaw(db, nSpace);
115614116390
if( pSpace==0 ) return SQLITE_NOMEM;
115615116391
aTo = (WherePath*)pSpace;
115616116392
aFrom = aTo+mxChoice;
115617116393
memset(aFrom, 0, sizeof(aFrom[0]));
115618116394
pX = (WhereLoop**)(aFrom+mxChoice);
115619116395
for(ii=mxChoice*2, pFrom=aTo; ii>0; ii--, pFrom++, pX += nLoop){
115620116396
pFrom->aLoop = pX;
115621116397
}
116398
+ if( nOrderBy ){
116399
+ /* If there is an ORDER BY clause and it is not being ignored, set up
116400
+ ** space for the aSortCost[] array. Each element of the aSortCost array
116401
+ ** is either zero - meaning it has not yet been initialized - or the
116402
+ ** cost of sorting nRowEst rows of data where the first X terms of
116403
+ ** the ORDER BY clause are already in order, where X is the array
116404
+ ** index. */
116405
+ aSortCost = (LogEst*)pX;
116406
+ memset(aSortCost, 0, sizeof(LogEst) * nOrderBy);
116407
+ }
116408
+ assert( aSortCost==0 || &pSpace[nSpace]==(char*)&aSortCost[nOrderBy] );
116409
+ assert( aSortCost!=0 || &pSpace[nSpace]==(char*)pX );
115622116410
115623116411
/* Seed the search with a single WherePath containing zero WhereLoops.
115624116412
**
115625116413
** TUNING: Do not let the number of iterations go above 25. If the cost
115626116414
** of computing an automatic index is not paid back within the first 25
115627116415
** rows, then do not use the automatic index. */
115628116416
aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==sqlite3LogEst(25) );
115629116417
nFrom = 1;
115630
-
115631
- /* Precompute the cost of sorting the final result set, if the caller
115632
- ** to sqlite3WhereBegin() was concerned about sorting */
115633
- if( pWInfo->pOrderBy==0 || nRowEst==0 ){
115634
- aFrom[0].isOrdered = 0;
115635
- nOrderBy = 0;
115636
- }else{
115637
- aFrom[0].isOrdered = nLoop>0 ? -1 : 1;
115638
- nOrderBy = pWInfo->pOrderBy->nExpr;
116418
+ assert( aFrom[0].isOrdered==0 );
116419
+ if( nOrderBy ){
116420
+ /* If nLoop is zero, then there are no FROM terms in the query. Since
116421
+ ** in this case the query may return a maximum of one row, the results
116422
+ ** are already in the requested order. Set isOrdered to nOrderBy to
116423
+ ** indicate this. Or, if nLoop is greater than zero, set isOrdered to
116424
+ ** -1, indicating that the result set may or may not be ordered,
116425
+ ** depending on the loops added to the current plan. */
116426
+ aFrom[0].isOrdered = nLoop>0 ? -1 : nOrderBy;
115639116427
}
115640116428
115641116429
/* Compute successively longer WherePaths using the previous generation
115642116430
** of WherePaths as the basis for the next. Keep track of the mxChoice
115643116431
** best paths at each generation */
115644116432
for(iLoop=0; iLoop<nLoop; iLoop++){
115645116433
nTo = 0;
115646116434
for(ii=0, pFrom=aFrom; ii<nFrom; ii++, pFrom++){
115647116435
for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
115648
- Bitmask maskNew;
115649
- Bitmask revMask = 0;
115650
- i8 isOrdered = pFrom->isOrdered;
116436
+ LogEst nOut; /* Rows visited by (pFrom+pWLoop) */
116437
+ LogEst rCost; /* Cost of path (pFrom+pWLoop) */
116438
+ LogEst rUnsorted; /* Unsorted cost of (pFrom+pWLoop) */
116439
+ i8 isOrdered = pFrom->isOrdered; /* isOrdered for (pFrom+pWLoop) */
116440
+ Bitmask maskNew; /* Mask of src visited by (..) */
116441
+ Bitmask revMask = 0; /* Mask of rev-order loops for (..) */
116442
+
115651116443
if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
115652116444
if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
115653116445
/* At this point, pWLoop is a candidate to be the next loop.
115654116446
** Compute its cost */
115655
- rCost = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
115656
- rCost = sqlite3LogEstAdd(rCost, pFrom->rCost);
116447
+ rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
116448
+ rUnsorted = sqlite3LogEstAdd(rUnsorted, pFrom->rUnsorted);
115657116449
nOut = pFrom->nRow + pWLoop->nOut;
115658116450
maskNew = pFrom->maskLoop | pWLoop->maskSelf;
115659116451
if( isOrdered<0 ){
115660116452
isOrdered = wherePathSatisfiesOrderBy(pWInfo,
115661116453
pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
115662116454
iLoop, pWLoop, &revMask);
115663
- if( isOrdered>=0 && isOrdered<nOrderBy ){
115664
- /* TUNING: Estimated cost of a full external sort, where N is
115665
- ** the number of rows to sort is:
115666
- **
115667
- ** cost = (3.0 * N * log(N)).
115668
- **
115669
- ** Or, if the order-by clause has X terms but only the last Y
115670
- ** terms are out of order, then block-sorting will reduce the
115671
- ** sorting cost to:
115672
- **
115673
- ** cost = (3.0 * N * log(N)) * (Y/X)
115674
- **
115675
- ** The (Y/X) term is implemented using stack variable rScale
115676
- ** below. */
115677
- LogEst rScale, rSortCost;
115678
- assert( nOrderBy>0 && 66==sqlite3LogEst(100) );
115679
- rScale = sqlite3LogEst((nOrderBy-isOrdered)*100/nOrderBy) - 66;
115680
- rSortCost = nRowEst + estLog(nRowEst) + rScale + 16;
115681
-
115682
- /* TUNING: The cost of implementing DISTINCT using a B-TREE is
115683
- ** similar but with a larger constant of proportionality.
115684
- ** Multiply by an additional factor of 3.0. */
115685
- if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
115686
- rSortCost += 16;
115687
- }
115688
- WHERETRACE(0x002,
115689
- ("---- sort cost=%-3d (%d/%d) increases cost %3d to %-3d\n",
115690
- rSortCost, (nOrderBy-isOrdered), nOrderBy, rCost,
115691
- sqlite3LogEstAdd(rCost,rSortCost)));
115692
- rCost = sqlite3LogEstAdd(rCost, rSortCost);
115693
- }
115694116455
}else{
115695116456
revMask = pFrom->revLoop;
115696116457
}
115697
- /* Check to see if pWLoop should be added to the mxChoice best so far */
116458
+ if( isOrdered>=0 && isOrdered<nOrderBy ){
116459
+ if( aSortCost[isOrdered]==0 ){
116460
+ aSortCost[isOrdered] = whereSortingCost(
116461
+ pWInfo, nRowEst, nOrderBy, isOrdered
116462
+ );
116463
+ }
116464
+ rCost = sqlite3LogEstAdd(rUnsorted, aSortCost[isOrdered]);
116465
+
116466
+ WHERETRACE(0x002,
116467
+ ("---- sort cost=%-3d (%d/%d) increases cost %3d to %-3d\n",
116468
+ aSortCost[isOrdered], (nOrderBy-isOrdered), nOrderBy,
116469
+ rUnsorted, rCost));
116470
+ }else{
116471
+ rCost = rUnsorted;
116472
+ }
116473
+
116474
+ /* Check to see if pWLoop should be added to the set of
116475
+ ** mxChoice best-so-far paths.
116476
+ **
116477
+ ** First look for an existing path among best-so-far paths
116478
+ ** that covers the same set of loops and has the same isOrdered
116479
+ ** setting as the current path candidate.
116480
+ **
116481
+ ** The term "((pTo->isOrdered^isOrdered)&0x80)==0" is equivalent
116482
+ ** to (pTo->isOrdered==(-1))==(isOrdered==(-1))" for the range
116483
+ ** of legal values for isOrdered, -1..64.
116484
+ */
115698116485
for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
115699116486
if( pTo->maskLoop==maskNew
115700
- && ((pTo->isOrdered^isOrdered)&80)==0
116487
+ && ((pTo->isOrdered^isOrdered)&0x80)==0
115701116488
){
115702116489
testcase( jj==nTo-1 );
115703116490
break;
115704116491
}
115705116492
}
115706116493
if( jj>=nTo ){
115707
- if( nTo>=mxChoice && rCost>=mxCost ){
116494
+ /* None of the existing best-so-far paths match the candidate. */
116495
+ if( nTo>=mxChoice
116496
+ && (rCost>mxCost || (rCost==mxCost && rUnsorted>=mxUnsorted))
116497
+ ){
116498
+ /* The current candidate is no better than any of the mxChoice
116499
+ ** paths currently in the best-so-far buffer. So discard
116500
+ ** this candidate as not viable. */
115708116501
#ifdef WHERETRACE_ENABLED /* 0x4 */
115709116502
if( sqlite3WhereTrace&0x4 ){
115710116503
sqlite3DebugPrintf("Skip %s cost=%-3d,%3d order=%c\n",
115711116504
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
115712116505
isOrdered>=0 ? isOrdered+'0' : '?');
115713116506
}
115714116507
#endif
115715116508
continue;
115716116509
}
115717
- /* Add a new Path to the aTo[] set */
116510
+ /* If we reach this points it means that the new candidate path
116511
+ ** needs to be added to the set of best-so-far paths. */
115718116512
if( nTo<mxChoice ){
115719116513
/* Increase the size of the aTo set by one */
115720116514
jj = nTo++;
115721116515
}else{
115722116516
/* New path replaces the prior worst to keep count below mxChoice */
@@ -115729,11 +116523,15 @@
115729116523
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
115730116524
isOrdered>=0 ? isOrdered+'0' : '?');
115731116525
}
115732116526
#endif
115733116527
}else{
115734
- if( pTo->rCost<=rCost ){
116528
+ /* Control reaches here if best-so-far path pTo=aTo[jj] covers the
116529
+ ** same set of loops and has the sam isOrdered setting as the
116530
+ ** candidate path. Check to see if the candidate should replace
116531
+ ** pTo or if the candidate should be skipped */
116532
+ if( pTo->rCost<rCost || (pTo->rCost==rCost && pTo->nRow<=nOut) ){
115735116533
#ifdef WHERETRACE_ENABLED /* 0x4 */
115736116534
if( sqlite3WhereTrace&0x4 ){
115737116535
sqlite3DebugPrintf(
115738116536
"Skip %s cost=%-3d,%3d order=%c",
115739116537
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
@@ -115741,15 +116539,17 @@
115741116539
sqlite3DebugPrintf(" vs %s cost=%-3d,%d order=%c\n",
115742116540
wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
115743116541
pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
115744116542
}
115745116543
#endif
116544
+ /* Discard the candidate path from further consideration */
115746116545
testcase( pTo->rCost==rCost );
115747116546
continue;
115748116547
}
115749116548
testcase( pTo->rCost==rCost+1 );
115750
- /* A new and better score for a previously created equivalent path */
116549
+ /* Control reaches here if the candidate path is better than the
116550
+ ** pTo path. Replace pTo with the candidate. */
115751116551
#ifdef WHERETRACE_ENABLED /* 0x4 */
115752116552
if( sqlite3WhereTrace&0x4 ){
115753116553
sqlite3DebugPrintf(
115754116554
"Update %s cost=%-3d,%3d order=%c",
115755116555
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
@@ -115763,19 +116563,24 @@
115763116563
/* pWLoop is a winner. Add it to the set of best so far */
115764116564
pTo->maskLoop = pFrom->maskLoop | pWLoop->maskSelf;
115765116565
pTo->revLoop = revMask;
115766116566
pTo->nRow = nOut;
115767116567
pTo->rCost = rCost;
116568
+ pTo->rUnsorted = rUnsorted;
115768116569
pTo->isOrdered = isOrdered;
115769116570
memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop);
115770116571
pTo->aLoop[iLoop] = pWLoop;
115771116572
if( nTo>=mxChoice ){
115772116573
mxI = 0;
115773116574
mxCost = aTo[0].rCost;
116575
+ mxUnsorted = aTo[0].nRow;
115774116576
for(jj=1, pTo=&aTo[1]; jj<mxChoice; jj++, pTo++){
115775
- if( pTo->rCost>mxCost ){
116577
+ if( pTo->rCost>mxCost
116578
+ || (pTo->rCost==mxCost && pTo->rUnsorted>mxUnsorted)
116579
+ ){
115776116580
mxCost = pTo->rCost;
116581
+ mxUnsorted = pTo->rUnsorted;
115777116582
mxI = jj;
115778116583
}
115779116584
}
115780116585
}
115781116586
}
@@ -115909,11 +116714,11 @@
115909116714
pLoop->rRun = 33; /* 33==sqlite3LogEst(10) */
115910116715
}else{
115911116716
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
115912116717
assert( pLoop->aLTermSpace==pLoop->aLTerm );
115913116718
assert( ArraySize(pLoop->aLTermSpace)==4 );
115914
- if( pIdx->onError==OE_None
116719
+ if( !IsUniqueIndex(pIdx)
115915116720
|| pIdx->pPartIdxWhere!=0
115916116721
|| pIdx->nKeyCol>ArraySize(pLoop->aLTermSpace)
115917116722
) continue;
115918116723
for(j=0; j<pIdx->nKeyCol; j++){
115919116724
pTerm = findTerm(pWC, iCur, pIdx->aiColumn[j], 0, WO_EQ, pIdx);
@@ -116399,10 +117204,11 @@
116399117204
}
116400117205
op = OP_OpenWrite;
116401117206
pWInfo->aiCurOnePass[1] = iIndexCur;
116402117207
}else if( iIdxCur && (wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ){
116403117208
iIndexCur = iIdxCur;
117209
+ if( wctrlFlags & WHERE_REOPEN_IDX ) op = OP_ReopenIdx;
116404117210
}else{
116405117211
iIndexCur = pParse->nTab++;
116406117212
}
116407117213
pLevel->iIdxCur = iIndexCur;
116408117214
assert( pIx->pSchema==pTab->pSchema );
@@ -120723,10 +121529,16 @@
120723121529
testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' );
120724121530
testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' );
120725121531
testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' );
120726121532
testcase( z[0]=='9' );
120727121533
*tokenType = TK_INTEGER;
121534
+#ifndef SQLITE_OMIT_HEX_INTEGER
121535
+ if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){
121536
+ for(i=3; sqlite3Isxdigit(z[i]); i++){}
121537
+ return i;
121538
+ }
121539
+#endif
120728121540
for(i=0; sqlite3Isdigit(z[i]); i++){}
120729121541
#ifndef SQLITE_OMIT_FLOATING_POINT
120730121542
if( z[i]=='.' ){
120731121543
i++;
120732121544
while( sqlite3Isdigit(z[i]) ){ i++; }
@@ -122170,10 +122982,12 @@
122170122982
/*
122171122983
** Close an existing SQLite database
122172122984
*/
122173122985
static int sqlite3Close(sqlite3 *db, int forceZombie){
122174122986
if( !db ){
122987
+ /* EVIDENCE-OF: R-63257-11740 Calling sqlite3_close() or
122988
+ ** sqlite3_close_v2() with a NULL pointer argument is a harmless no-op. */
122175122989
return SQLITE_OK;
122176122990
}
122177122991
if( !sqlite3SafetyCheckSickOrOk(db) ){
122178122992
return SQLITE_MISUSE_BKPT;
122179122993
}
@@ -122399,11 +123213,11 @@
122399123213
122400123214
/*
122401123215
** Return a static string containing the name corresponding to the error code
122402123216
** specified in the argument.
122403123217
*/
122404
-#if defined(SQLITE_TEST)
123218
+#if (defined(SQLITE_DEBUG) && SQLITE_OS_WIN) || defined(SQLITE_TEST)
122405123219
SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
122406123220
const char *zName = 0;
122407123221
int i, origRc = rc;
122408123222
for(i=0; i<2 && zName==0; i++, rc &= 0xff){
122409123223
switch( rc ){
@@ -122434,11 +123248,10 @@
122434123248
case SQLITE_IOERR_TRUNCATE: zName = "SQLITE_IOERR_TRUNCATE"; break;
122435123249
case SQLITE_IOERR_FSTAT: zName = "SQLITE_IOERR_FSTAT"; break;
122436123250
case SQLITE_IOERR_UNLOCK: zName = "SQLITE_IOERR_UNLOCK"; break;
122437123251
case SQLITE_IOERR_RDLOCK: zName = "SQLITE_IOERR_RDLOCK"; break;
122438123252
case SQLITE_IOERR_DELETE: zName = "SQLITE_IOERR_DELETE"; break;
122439
- case SQLITE_IOERR_BLOCKED: zName = "SQLITE_IOERR_BLOCKED"; break;
122440123253
case SQLITE_IOERR_NOMEM: zName = "SQLITE_IOERR_NOMEM"; break;
122441123254
case SQLITE_IOERR_ACCESS: zName = "SQLITE_IOERR_ACCESS"; break;
122442123255
case SQLITE_IOERR_CHECKRESERVEDLOCK:
122443123256
zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
122444123257
case SQLITE_IOERR_LOCK: zName = "SQLITE_IOERR_LOCK"; break;
@@ -123419,11 +124232,11 @@
123419124232
SQLITE_MAX_COMPOUND_SELECT,
123420124233
SQLITE_MAX_VDBE_OP,
123421124234
SQLITE_MAX_FUNCTION_ARG,
123422124235
SQLITE_MAX_ATTACHED,
123423124236
SQLITE_MAX_LIKE_PATTERN_LENGTH,
123424
- SQLITE_MAX_VARIABLE_NUMBER,
124237
+ SQLITE_MAX_VARIABLE_NUMBER, /* IMP: R-38091-32352 */
123425124238
SQLITE_MAX_TRIGGER_DEPTH,
123426124239
};
123427124240
123428124241
/*
123429124242
** Make sure the hard limits are set to reasonable values
@@ -123444,12 +124257,12 @@
123444124257
# error SQLITE_MAX_VDBE_OP must be at least 40
123445124258
#endif
123446124259
#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>1000
123447124260
# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 1000
123448124261
#endif
123449
-#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>62
123450
-# error SQLITE_MAX_ATTACHED must be between 0 and 62
124262
+#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>125
124263
+# error SQLITE_MAX_ATTACHED must be between 0 and 125
123451124264
#endif
123452124265
#if SQLITE_MAX_LIKE_PATTERN_LENGTH<1
123453124266
# error SQLITE_MAX_LIKE_PATTERN_LENGTH must be at least 1
123454124267
#endif
123455124268
#if SQLITE_MAX_COLUMN>32767
@@ -124704,10 +125517,20 @@
124704125517
sqlite3GlobalConfig.pVdbeBranchArg = va_arg(ap,void*);
124705125518
#endif
124706125519
break;
124707125520
}
124708125521
125522
+ /* sqlite3_test_control(SQLITE_TESTCTRL_ISINIT);
125523
+ **
125524
+ ** Return SQLITE_OK if SQLite has been initialized and SQLITE_ERROR if
125525
+ ** not.
125526
+ */
125527
+ case SQLITE_TESTCTRL_ISINIT: {
125528
+ if( sqlite3GlobalConfig.isInit==0 ) rc = SQLITE_ERROR;
125529
+ break;
125530
+ }
125531
+
124709125532
}
124710125533
va_end(ap);
124711125534
#endif /* SQLITE_OMIT_BUILTIN_TEST */
124712125535
return rc;
124713125536
}
@@ -124752,11 +125575,11 @@
124752125575
const char *zParam, /* URI parameter sought */
124753125576
sqlite3_int64 bDflt /* return if parameter is missing */
124754125577
){
124755125578
const char *z = sqlite3_uri_parameter(zFilename, zParam);
124756125579
sqlite3_int64 v;
124757
- if( z && sqlite3Atoi64(z, &v, sqlite3Strlen30(z), SQLITE_UTF8)==SQLITE_OK ){
125580
+ if( z && sqlite3DecOrHexToI64(z, &v)==SQLITE_OK ){
124758125581
bDflt = v;
124759125582
}
124760125583
return bDflt;
124761125584
}
124762125585
@@ -126283,11 +127106,11 @@
126283127106
126284127107
/* fts3_tokenize_vtab.c */
126285127108
SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *);
126286127109
126287127110
/* fts3_unicode2.c (functions generated by parsing unicode text files) */
126288
-#ifdef SQLITE_ENABLE_FTS4_UNICODE61
127111
+#ifndef SQLITE_DISABLE_FTS3_UNICODE
126289127112
SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int, int);
126290127113
SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int);
126291127114
SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int);
126292127115
#endif
126293127116
@@ -129753,11 +130576,11 @@
129753130576
** to by the argument to point to the "simple" tokenizer implementation.
129754130577
** And so on.
129755130578
*/
129756130579
SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule);
129757130580
SQLITE_PRIVATE void sqlite3Fts3PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule);
129758
-#ifdef SQLITE_ENABLE_FTS4_UNICODE61
130581
+#ifndef SQLITE_DISABLE_FTS3_UNICODE
129759130582
SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const**ppModule);
129760130583
#endif
129761130584
#ifdef SQLITE_ENABLE_ICU
129762130585
SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule);
129763130586
#endif
@@ -129771,20 +130594,20 @@
129771130594
SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){
129772130595
int rc = SQLITE_OK;
129773130596
Fts3Hash *pHash = 0;
129774130597
const sqlite3_tokenizer_module *pSimple = 0;
129775130598
const sqlite3_tokenizer_module *pPorter = 0;
129776
-#ifdef SQLITE_ENABLE_FTS4_UNICODE61
130599
+#ifndef SQLITE_DISABLE_FTS3_UNICODE
129777130600
const sqlite3_tokenizer_module *pUnicode = 0;
129778130601
#endif
129779130602
129780130603
#ifdef SQLITE_ENABLE_ICU
129781130604
const sqlite3_tokenizer_module *pIcu = 0;
129782130605
sqlite3Fts3IcuTokenizerModule(&pIcu);
129783130606
#endif
129784130607
129785
-#ifdef SQLITE_ENABLE_FTS4_UNICODE61
130608
+#ifndef SQLITE_DISABLE_FTS3_UNICODE
129786130609
sqlite3Fts3UnicodeTokenizer(&pUnicode);
129787130610
#endif
129788130611
129789130612
#ifdef SQLITE_TEST
129790130613
rc = sqlite3Fts3InitTerm(db);
@@ -129808,11 +130631,11 @@
129808130631
/* Load the built-in tokenizers into the hash table */
129809130632
if( rc==SQLITE_OK ){
129810130633
if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple)
129811130634
|| sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter)
129812130635
129813
-#ifdef SQLITE_ENABLE_FTS4_UNICODE61
130636
+#ifndef SQLITE_DISABLE_FTS3_UNICODE
129814130637
|| sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode)
129815130638
#endif
129816130639
#ifdef SQLITE_ENABLE_ICU
129817130640
|| (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu))
129818130641
#endif
@@ -143068,11 +143891,11 @@
143068143891
******************************************************************************
143069143892
**
143070143893
** Implementation of the "unicode" full-text-search tokenizer.
143071143894
*/
143072143895
143073
-#ifdef SQLITE_ENABLE_FTS4_UNICODE61
143896
+#ifndef SQLITE_DISABLE_FTS3_UNICODE
143074143897
143075143898
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
143076143899
143077143900
/* #include <assert.h> */
143078143901
/* #include <stdlib.h> */
@@ -143284,11 +144107,11 @@
143284144107
memset(pNew, 0, sizeof(unicode_tokenizer));
143285144108
pNew->bRemoveDiacritic = 1;
143286144109
143287144110
for(i=0; rc==SQLITE_OK && i<nArg; i++){
143288144111
const char *z = azArg[i];
143289
- int n = strlen(z);
144112
+ int n = (int)strlen(z);
143290144113
143291144114
if( n==19 && memcmp("remove_diacritics=1", z, 19)==0 ){
143292144115
pNew->bRemoveDiacritic = 1;
143293144116
}
143294144117
else if( n==19 && memcmp("remove_diacritics=0", z, 19)==0 ){
@@ -143371,11 +144194,11 @@
143371144194
int *piEnd, /* OUT: Ending offset of token */
143372144195
int *piPos /* OUT: Position integer of token */
143373144196
){
143374144197
unicode_cursor *pCsr = (unicode_cursor *)pC;
143375144198
unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer);
143376
- int iCode;
144199
+ int iCode = 0;
143377144200
char *zOut;
143378144201
const unsigned char *z = &pCsr->aInput[pCsr->iOff];
143379144202
const unsigned char *zStart = z;
143380144203
const unsigned char *zEnd;
143381144204
const unsigned char *zTerm = &pCsr->aInput[pCsr->nInput];
@@ -143416,15 +144239,15 @@
143416144239
}while( unicodeIsAlnum(p, iCode)
143417144240
|| sqlite3FtsUnicodeIsdiacritic(iCode)
143418144241
);
143419144242
143420144243
/* Set the output variables and return. */
143421
- pCsr->iOff = (z - pCsr->aInput);
144244
+ pCsr->iOff = (int)(z - pCsr->aInput);
143422144245
*paToken = pCsr->zToken;
143423
- *pnToken = zOut - pCsr->zToken;
143424
- *piStart = (zStart - pCsr->aInput);
143425
- *piEnd = (zEnd - pCsr->aInput);
144246
+ *pnToken = (int)(zOut - pCsr->zToken);
144247
+ *piStart = (int)(zStart - pCsr->aInput);
144248
+ *piEnd = (int)(zEnd - pCsr->aInput);
143426144249
*piPos = pCsr->iToken++;
143427144250
return SQLITE_OK;
143428144251
}
143429144252
143430144253
/*
@@ -143443,11 +144266,11 @@
143443144266
};
143444144267
*ppModule = &module;
143445144268
}
143446144269
143447144270
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
143448
-#endif /* ifndef SQLITE_ENABLE_FTS4_UNICODE61 */
144271
+#endif /* ifndef SQLITE_DISABLE_FTS3_UNICODE */
143449144272
143450144273
/************** End of fts3_unicode.c ****************************************/
143451144274
/************** Begin file fts3_unicode2.c ***********************************/
143452144275
/*
143453144276
** 2012 May 25
@@ -143464,11 +144287,11 @@
143464144287
143465144288
/*
143466144289
** DO NOT EDIT THIS MACHINE GENERATED FILE.
143467144290
*/
143468144291
143469
-#if defined(SQLITE_ENABLE_FTS4_UNICODE61)
144292
+#ifndef SQLITE_DISABLE_FTS3_UNICODE
143470144293
#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
143471144294
143472144295
/* #include <assert.h> */
143473144296
143474144297
/*
@@ -143488,11 +144311,11 @@
143488144311
** the size of the range (always at least 1). In other words, the value
143489144312
** ((C<<22) + N) represents a range of N codepoints starting with codepoint
143490144313
** C. It is not possible to represent a range larger than 1023 codepoints
143491144314
** using this format.
143492144315
*/
143493
- const static unsigned int aEntry[] = {
144316
+ static const unsigned int aEntry[] = {
143494144317
0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07,
143495144318
0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01,
143496144319
0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401,
143497144320
0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01,
143498144321
0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163C01,
@@ -143580,11 +144403,11 @@
143580144403
143581144404
if( c<128 ){
143582144405
return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
143583144406
}else if( c<(1<<22) ){
143584144407
unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
143585
- int iRes;
144408
+ int iRes = 0;
143586144409
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
143587144410
int iLo = 0;
143588144411
while( iHi>=iLo ){
143589144412
int iTest = (iHi + iLo) / 2;
143590144413
if( key >= aEntry[iTest] ){
@@ -143651,11 +144474,11 @@
143651144474
iHi = iTest-1;
143652144475
}
143653144476
}
143654144477
assert( key>=aDia[iRes] );
143655144478
return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
143656
-};
144479
+}
143657144480
143658144481
143659144482
/*
143660144483
** Return true if the argument interpreted as a unicode codepoint
143661144484
** is a diacritical modifier character.
@@ -143811,11 +144634,11 @@
143811144634
}
143812144635
143813144636
return ret;
143814144637
}
143815144638
#endif /* defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) */
143816
-#endif /* !defined(SQLITE_ENABLE_FTS4_UNICODE61) */
144639
+#endif /* !defined(SQLITE_DISABLE_FTS3_UNICODE) */
143817144640
143818144641
/************** End of fts3_unicode2.c ***************************************/
143819144642
/************** Begin file rtree.c *******************************************/
143820144643
/*
143821144644
** 2001 September 15
@@ -145348,13 +146171,17 @@
145348146171
int rc = SQLITE_OK;
145349146172
int iCell = 0;
145350146173
145351146174
rtreeReference(pRtree);
145352146175
146176
+ /* Reset the cursor to the same state as rtreeOpen() leaves it in. */
145353146177
freeCursorConstraints(pCsr);
146178
+ sqlite3_free(pCsr->aPoint);
146179
+ memset(pCsr, 0, sizeof(RtreeCursor));
146180
+ pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
146181
+
145354146182
pCsr->iStrategy = idxNum;
145355
-
145356146183
if( idxNum==1 ){
145357146184
/* Special case - lookup by rowid. */
145358146185
RtreeNode *pLeaf; /* Leaf on which the required cell resides */
145359146186
RtreeSearchPoint *p; /* Search point for the the leaf */
145360146187
i64 iRowid = sqlite3_value_int64(argv[0]);
145361146188
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -222,11 +222,11 @@
222 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
223 ** [sqlite_version()] and [sqlite_source_id()].
224 */
225 #define SQLITE_VERSION "3.8.6"
226 #define SQLITE_VERSION_NUMBER 3008006
227 #define SQLITE_SOURCE_ID "2014-07-01 11:54:02 21981e35062cc6b30e9576786cbf55265a7a4d41"
228
229 /*
230 ** CAPI3REF: Run-Time Library Version Numbers
231 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
232 **
@@ -382,19 +382,19 @@
382 /*
383 ** CAPI3REF: Closing A Database Connection
384 **
385 ** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
386 ** for the [sqlite3] object.
387 ** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if
388 ** the [sqlite3] object is successfully destroyed and all associated
389 ** resources are deallocated.
390 **
391 ** ^If the database connection is associated with unfinalized prepared
392 ** statements or unfinished sqlite3_backup objects then sqlite3_close()
393 ** will leave the database connection open and return [SQLITE_BUSY].
394 ** ^If sqlite3_close_v2() is called with unfinalized prepared statements
395 ** and unfinished sqlite3_backups, then the database connection becomes
396 ** an unusable "zombie" which will automatically be deallocated when the
397 ** last prepared statement is finalized or the last sqlite3_backup is
398 ** finished. The sqlite3_close_v2() interface is intended for use with
399 ** host languages that are garbage collected, and where the order in which
400 ** destructors are called is arbitrary.
@@ -403,11 +403,11 @@
403 ** [sqlite3_blob_close | close] all [BLOB handles], and
404 ** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
405 ** with the [sqlite3] object prior to attempting to close the object. ^If
406 ** sqlite3_close_v2() is called on a [database connection] that still has
407 ** outstanding [prepared statements], [BLOB handles], and/or
408 ** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation
409 ** of resources is deferred until all [prepared statements], [BLOB handles],
410 ** and [sqlite3_backup] objects are also destroyed.
411 **
412 ** ^If an [sqlite3] object is destroyed while a transaction is open,
413 ** the transaction is automatically rolled back.
@@ -499,20 +499,18 @@
499 char **errmsg /* Error msg written here */
500 );
501
502 /*
503 ** CAPI3REF: Result Codes
504 ** KEYWORDS: SQLITE_OK {error code} {error codes}
505 ** KEYWORDS: {result code} {result codes}
506 **
507 ** Many SQLite functions return an integer result code from the set shown
508 ** here in order to indicate success or failure.
509 **
510 ** New error codes may be added in future versions of SQLite.
511 **
512 ** See also: [SQLITE_IOERR_READ | extended result codes],
513 ** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
514 */
515 #define SQLITE_OK 0 /* Successful result */
516 /* beginning-of-error-codes */
517 #define SQLITE_ERROR 1 /* SQL error or missing database */
518 #define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
@@ -546,30 +544,23 @@
546 #define SQLITE_DONE 101 /* sqlite3_step() has finished executing */
547 /* end-of-error-codes */
548
549 /*
550 ** CAPI3REF: Extended Result Codes
551 ** KEYWORDS: {extended error code} {extended error codes}
552 ** KEYWORDS: {extended result code} {extended result codes}
553 **
554 ** In its default configuration, SQLite API routines return one of 26 integer
555 ** [SQLITE_OK | result codes]. However, experience has shown that many of
556 ** these result codes are too coarse-grained. They do not provide as
557 ** much information about problems as programmers might like. In an effort to
558 ** address this, newer versions of SQLite (version 3.3.8 and later) include
559 ** support for additional result codes that provide more detailed information
560 ** about errors. The extended result codes are enabled or disabled
561 ** on a per database connection basis using the
562 ** [sqlite3_extended_result_codes()] API.
563 **
564 ** Some of the available extended result codes are listed here.
565 ** One may expect the number of extended result codes will increase
566 ** over time. Software that uses extended result codes should expect
567 ** to see new result codes in future releases of SQLite.
568 **
569 ** The SQLITE_OK result code will never be extended. It will always
570 ** be exactly zero.
571 */
572 #define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
573 #define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
574 #define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8))
575 #define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8))
@@ -798,11 +789,11 @@
798 ** write return values. Potential uses for xFileControl() might be
799 ** functions to enable blocking locks with timeouts, to change the
800 ** locking strategy (for example to use dot-file locks), to inquire
801 ** about the status of a lock, or to break stale locks. The SQLite
802 ** core reserves all opcodes less than 100 for its own use.
803 ** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available.
804 ** Applications that define a custom xFileControl method should use opcodes
805 ** greater than 100 to avoid conflicts. VFS implementations should
806 ** return [SQLITE_NOTFOUND] for file control opcodes that they do not
807 ** recognize.
808 **
@@ -871,10 +862,11 @@
871 /* Additional methods may be added in future releases */
872 };
873
874 /*
875 ** CAPI3REF: Standard File Control Opcodes
 
876 **
877 ** These integer constants are opcodes for the xFileControl method
878 ** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
879 ** interface.
880 **
@@ -2150,31 +2142,37 @@
2150 SQLITE_API int sqlite3_complete16(const void *sql);
2151
2152 /*
2153 ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
2154 **
2155 ** ^This routine sets a callback function that might be invoked whenever
2156 ** an attempt is made to open a database table that another thread
2157 ** or process has locked.
 
 
 
 
2158 **
2159 ** ^If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]
2160 ** is returned immediately upon encountering the lock. ^If the busy callback
2161 ** is not NULL, then the callback might be invoked with two arguments.
2162 **
2163 ** ^The first argument to the busy handler is a copy of the void* pointer which
2164 ** is the third argument to sqlite3_busy_handler(). ^The second argument to
2165 ** the busy handler callback is the number of times that the busy handler has
2166 ** been invoked for this locking event. ^If the
2167 ** busy callback returns 0, then no additional attempts are made to
2168 ** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned.
 
2169 ** ^If the callback returns non-zero, then another attempt
2170 ** is made to open the database for reading and the cycle repeats.
2171 **
2172 ** The presence of a busy handler does not guarantee that it will be invoked
2173 ** when there is lock contention. ^If SQLite determines that invoking the busy
2174 ** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY]
2175 ** or [SQLITE_IOERR_BLOCKED] instead of invoking the busy handler.
 
2176 ** Consider a scenario where one process is holding a read lock that
2177 ** it is trying to promote to a reserved lock and
2178 ** a second process is holding a reserved lock that it is trying
2179 ** to promote to an exclusive lock. The first process cannot proceed
2180 ** because it is blocked by the second and the second process cannot
@@ -2184,32 +2182,19 @@
2184 ** will induce the first process to release its read lock and allow
2185 ** the second process to proceed.
2186 **
2187 ** ^The default busy callback is NULL.
2188 **
2189 ** ^The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED]
2190 ** when SQLite is in the middle of a large transaction where all the
2191 ** changes will not fit into the in-memory cache. SQLite will
2192 ** already hold a RESERVED lock on the database file, but it needs
2193 ** to promote this lock to EXCLUSIVE so that it can spill cache
2194 ** pages into the database file without harm to concurrent
2195 ** readers. ^If it is unable to promote the lock, then the in-memory
2196 ** cache will be left in an inconsistent state and so the error
2197 ** code is promoted from the relatively benign [SQLITE_BUSY] to
2198 ** the more severe [SQLITE_IOERR_BLOCKED]. ^This error code promotion
2199 ** forces an automatic rollback of the changes. See the
2200 ** <a href="/cvstrac/wiki?p=CorruptionFollowingBusyError">
2201 ** CorruptionFollowingBusyError</a> wiki page for a discussion of why
2202 ** this is important.
2203 **
2204 ** ^(There can only be a single busy handler defined for each
2205 ** [database connection]. Setting a new busy handler clears any
2206 ** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()]
2207 ** will also set or clear the busy handler.
 
2208 **
2209 ** The busy callback should not take any actions which modify the
2210 ** database connection that invoked the busy handler. Any such actions
 
2211 ** result in undefined behavior.
2212 **
2213 ** A busy handler must not close the database connection
2214 ** or [prepared statement] that invoked the busy handler.
2215 */
@@ -2221,19 +2206,21 @@
2221 ** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps
2222 ** for a specified amount of time when a table is locked. ^The handler
2223 ** will sleep multiple times until at least "ms" milliseconds of sleeping
2224 ** have accumulated. ^After at least "ms" milliseconds of sleeping,
2225 ** the handler returns 0 which causes [sqlite3_step()] to return
2226 ** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED].
2227 **
2228 ** ^Calling this routine with an argument less than or equal to zero
2229 ** turns off all busy handlers.
2230 **
2231 ** ^(There can only be a single busy handler for a particular
2232 ** [database connection] any any given moment. If another busy handler
2233 ** was defined (using [sqlite3_busy_handler()]) prior to calling
2234 ** this routine, that other busy handler is cleared.)^
 
 
2235 */
2236 SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
2237
2238 /*
2239 ** CAPI3REF: Convenience Routines For Running Queries
@@ -2631,12 +2618,12 @@
2631 ** return either [SQLITE_OK] or one of these two constants in order
2632 ** to signal SQLite whether or not the action is permitted. See the
2633 ** [sqlite3_set_authorizer | authorizer documentation] for additional
2634 ** information.
2635 **
2636 ** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
2637 ** from the [sqlite3_vtab_on_conflict()] interface.
2638 */
2639 #define SQLITE_DENY 1 /* Abort the SQL statement with an error */
2640 #define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
2641
2642 /*
@@ -4818,10 +4805,17 @@
4818 ** the name of a folder (a.k.a. directory), then all temporary files
4819 ** created by SQLite when using a built-in [sqlite3_vfs | VFS]
4820 ** will be placed in that directory.)^ ^If this variable
4821 ** is a NULL pointer, then SQLite performs a search for an appropriate
4822 ** temporary file directory.
 
 
 
 
 
 
 
4823 **
4824 ** It is not safe to read or modify this variable in more than one
4825 ** thread at a time. It is not safe to read or modify this variable
4826 ** if a [database connection] is being used at the same time in a separate
4827 ** thread.
@@ -4837,10 +4831,15 @@
4837 ** [sqlite3_malloc] and the pragma may attempt to free that memory
4838 ** using [sqlite3_free].
4839 ** Hence, if this variable is modified directly, either it should be
4840 ** made NULL or made to point to memory obtained from [sqlite3_malloc]
4841 ** or else the use of the [temp_store_directory pragma] should be avoided.
 
 
 
 
 
4842 **
4843 ** <b>Note to Windows Runtime users:</b> The temporary directory must be set
4844 ** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various
4845 ** features that require the use of temporary files may fail. Here is an
4846 ** example of how to do this using C++ with the Windows Runtime:
@@ -5971,14 +5970,16 @@
5971 ** <ul>
5972 ** <li> SQLITE_MUTEX_FAST
5973 ** <li> SQLITE_MUTEX_RECURSIVE
5974 ** <li> SQLITE_MUTEX_STATIC_MASTER
5975 ** <li> SQLITE_MUTEX_STATIC_MEM
5976 ** <li> SQLITE_MUTEX_STATIC_MEM2
5977 ** <li> SQLITE_MUTEX_STATIC_PRNG
5978 ** <li> SQLITE_MUTEX_STATIC_LRU
5979 ** <li> SQLITE_MUTEX_STATIC_LRU2
 
 
5980 ** </ul>)^
5981 **
5982 ** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
5983 ** cause sqlite3_mutex_alloc() to create
5984 ** a new mutex. ^The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
@@ -6178,10 +6179,13 @@
6178 #define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */
6179 #define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */
6180 #define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
6181 #define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */
6182 #define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */
 
 
 
6183
6184 /*
6185 ** CAPI3REF: Retrieve the mutex for a database connection
6186 **
6187 ** ^This interface returns a pointer the [sqlite3_mutex] object that
@@ -6273,11 +6277,12 @@
6273 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
6274 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19
6275 #define SQLITE_TESTCTRL_NEVER_CORRUPT 20
6276 #define SQLITE_TESTCTRL_VDBE_COVERAGE 21
6277 #define SQLITE_TESTCTRL_BYTEORDER 22
6278 #define SQLITE_TESTCTRL_LAST 22
 
6279
6280 /*
6281 ** CAPI3REF: SQLite Runtime Status
6282 **
6283 ** ^This interface is used to retrieve runtime status information
@@ -7256,10 +7261,13 @@
7256 ** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism
7257 ** configured by this function.
7258 **
7259 ** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
7260 ** from SQL.
 
 
 
7261 **
7262 ** ^Every new [database connection] defaults to having the auto-checkpoint
7263 ** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
7264 ** pages. The use of this interface
7265 ** is only necessary if the default setting is found to be suboptimal
@@ -7273,10 +7281,14 @@
7273 ** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X
7274 ** on [database connection] D to be [checkpointed]. ^If X is NULL or an
7275 ** empty string, then a checkpoint is run on all databases of
7276 ** connection D. ^If the database connection D is not in
7277 ** [WAL | write-ahead log mode] then this interface is a harmless no-op.
 
 
 
 
7278 **
7279 ** ^The [wal_checkpoint pragma] can be used to invoke this interface
7280 ** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the
7281 ** [wal_autocheckpoint pragma] can be used to cause this interface to be
7282 ** run whenever the WAL reaches a certain size threshold.
@@ -7295,22 +7307,25 @@
7295 ** <dl>
7296 ** <dt>SQLITE_CHECKPOINT_PASSIVE<dd>
7297 ** Checkpoint as many frames as possible without waiting for any database
7298 ** readers or writers to finish. Sync the db file if all frames in the log
7299 ** are checkpointed. This mode is the same as calling
7300 ** sqlite3_wal_checkpoint(). The busy-handler callback is never invoked.
 
7301 **
7302 ** <dt>SQLITE_CHECKPOINT_FULL<dd>
7303 ** This mode blocks (calls the busy-handler callback) until there is no
 
7304 ** database writer and all readers are reading from the most recent database
7305 ** snapshot. It then checkpoints all frames in the log file and syncs the
7306 ** database file. This call blocks database writers while it is running,
7307 ** but not database readers.
7308 **
7309 ** <dt>SQLITE_CHECKPOINT_RESTART<dd>
7310 ** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after
7311 ** checkpointing the log file it blocks (calls the busy-handler callback)
 
7312 ** until all readers are reading from the database file only. This ensures
7313 ** that the next client to write to the database file restarts the log file
7314 ** from the beginning. This call blocks database writers while it is running,
7315 ** but not database readers.
7316 ** </dl>
@@ -7444,10 +7459,11 @@
7444 */
7445 SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
7446
7447 /*
7448 ** CAPI3REF: Conflict resolution modes
 
7449 **
7450 ** These constants are returned by [sqlite3_vtab_on_conflict()] to
7451 ** inform a [virtual table] implementation what the [ON CONFLICT] mode
7452 ** is for the SQL statement being evaluated.
7453 **
@@ -9285,43 +9301,43 @@
9285 #define OP_Affinity 47 /* synopsis: affinity(r[P1@P2]) */
9286 #define OP_MakeRecord 48 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
9287 #define OP_Count 49 /* synopsis: r[P2]=count() */
9288 #define OP_ReadCookie 50
9289 #define OP_SetCookie 51
9290 #define OP_OpenRead 52 /* synopsis: root=P2 iDb=P3 */
9291 #define OP_OpenWrite 53 /* synopsis: root=P2 iDb=P3 */
9292 #define OP_OpenAutoindex 54 /* synopsis: nColumn=P2 */
9293 #define OP_OpenEphemeral 55 /* synopsis: nColumn=P2 */
9294 #define OP_SorterOpen 56
9295 #define OP_OpenPseudo 57 /* synopsis: P3 columns in r[P2] */
9296 #define OP_Close 58
9297 #define OP_SeekLT 59
9298 #define OP_SeekLE 60
9299 #define OP_SeekGE 61
9300 #define OP_SeekGT 62
9301 #define OP_Seek 63 /* synopsis: intkey=r[P2] */
9302 #define OP_NoConflict 64 /* synopsis: key=r[P3@P4] */
9303 #define OP_NotFound 65 /* synopsis: key=r[P3@P4] */
9304 #define OP_Found 66 /* synopsis: key=r[P3@P4] */
9305 #define OP_NotExists 67 /* synopsis: intkey=r[P3] */
9306 #define OP_Sequence 68 /* synopsis: r[P2]=cursor[P1].ctr++ */
9307 #define OP_NewRowid 69 /* synopsis: r[P2]=rowid */
9308 #define OP_Insert 70 /* synopsis: intkey=r[P3] data=r[P2] */
9309 #define OP_Or 71 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
9310 #define OP_And 72 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
9311 #define OP_InsertInt 73 /* synopsis: intkey=P3 data=r[P2] */
9312 #define OP_Delete 74
9313 #define OP_ResetCount 75
9314 #define OP_IsNull 76 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
9315 #define OP_NotNull 77 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
9316 #define OP_Ne 78 /* same as TK_NE, synopsis: if r[P1]!=r[P3] goto P2 */
9317 #define OP_Eq 79 /* same as TK_EQ, synopsis: if r[P1]==r[P3] goto P2 */
9318 #define OP_Gt 80 /* same as TK_GT, synopsis: if r[P1]>r[P3] goto P2 */
9319 #define OP_Le 81 /* same as TK_LE, synopsis: if r[P1]<=r[P3] goto P2 */
9320 #define OP_Lt 82 /* same as TK_LT, synopsis: if r[P1]<r[P3] goto P2 */
9321 #define OP_Ge 83 /* same as TK_GE, synopsis: if r[P1]>=r[P3] goto P2 */
9322 #define OP_SorterCompare 84 /* synopsis: if key(P1)!=rtrim(r[P3],P4) goto P2 */
9323 #define OP_BitAnd 85 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
9324 #define OP_BitOr 86 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
9325 #define OP_ShiftLeft 87 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
9326 #define OP_ShiftRight 88 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
9327 #define OP_Add 89 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
@@ -9328,73 +9344,74 @@
9328 #define OP_Subtract 90 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
9329 #define OP_Multiply 91 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
9330 #define OP_Divide 92 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
9331 #define OP_Remainder 93 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
9332 #define OP_Concat 94 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
9333 #define OP_SorterData 95 /* synopsis: r[P2]=data */
9334 #define OP_BitNot 96 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */
9335 #define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */
9336 #define OP_RowKey 98 /* synopsis: r[P2]=key */
9337 #define OP_RowData 99 /* synopsis: r[P2]=data */
9338 #define OP_Rowid 100 /* synopsis: r[P2]=rowid */
9339 #define OP_NullRow 101
9340 #define OP_Last 102
9341 #define OP_SorterSort 103
9342 #define OP_Sort 104
9343 #define OP_Rewind 105
9344 #define OP_SorterInsert 106
9345 #define OP_IdxInsert 107 /* synopsis: key=r[P2] */
9346 #define OP_IdxDelete 108 /* synopsis: key=r[P2@P3] */
9347 #define OP_IdxRowid 109 /* synopsis: r[P2]=rowid */
9348 #define OP_IdxLE 110 /* synopsis: key=r[P3@P4] */
9349 #define OP_IdxGT 111 /* synopsis: key=r[P3@P4] */
9350 #define OP_IdxLT 112 /* synopsis: key=r[P3@P4] */
9351 #define OP_IdxGE 113 /* synopsis: key=r[P3@P4] */
9352 #define OP_Destroy 114
9353 #define OP_Clear 115
9354 #define OP_ResetSorter 116
9355 #define OP_CreateIndex 117 /* synopsis: r[P2]=root iDb=P1 */
9356 #define OP_CreateTable 118 /* synopsis: r[P2]=root iDb=P1 */
9357 #define OP_ParseSchema 119
9358 #define OP_LoadAnalysis 120
9359 #define OP_DropTable 121
9360 #define OP_DropIndex 122
9361 #define OP_DropTrigger 123
9362 #define OP_IntegrityCk 124
9363 #define OP_RowSetAdd 125 /* synopsis: rowset(P1)=r[P2] */
9364 #define OP_RowSetRead 126 /* synopsis: r[P3]=rowset(P1) */
9365 #define OP_RowSetTest 127 /* synopsis: if r[P3] in rowset(P1) goto P2 */
9366 #define OP_Program 128
9367 #define OP_Param 129
9368 #define OP_FkCounter 130 /* synopsis: fkctr[P1]+=P2 */
9369 #define OP_FkIfZero 131 /* synopsis: if fkctr[P1]==0 goto P2 */
9370 #define OP_MemMax 132 /* synopsis: r[P1]=max(r[P1],r[P2]) */
9371 #define OP_Real 133 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
9372 #define OP_IfPos 134 /* synopsis: if r[P1]>0 goto P2 */
9373 #define OP_IfNeg 135 /* synopsis: if r[P1]<0 goto P2 */
9374 #define OP_IfZero 136 /* synopsis: r[P1]+=P3, if r[P1]==0 goto P2 */
9375 #define OP_AggFinal 137 /* synopsis: accum=r[P1] N=P2 */
9376 #define OP_IncrVacuum 138
9377 #define OP_Expire 139
9378 #define OP_TableLock 140 /* synopsis: iDb=P1 root=P2 write=P3 */
9379 #define OP_VBegin 141
9380 #define OP_VCreate 142
9381 #define OP_ToText 143 /* same as TK_TO_TEXT */
9382 #define OP_ToBlob 144 /* same as TK_TO_BLOB */
9383 #define OP_ToNumeric 145 /* same as TK_TO_NUMERIC */
9384 #define OP_ToInt 146 /* same as TK_TO_INT */
9385 #define OP_ToReal 147 /* same as TK_TO_REAL */
9386 #define OP_VDestroy 148
9387 #define OP_VOpen 149
9388 #define OP_VColumn 150 /* synopsis: r[P3]=vcolumn(P2) */
9389 #define OP_VNext 151
9390 #define OP_VRename 152
9391 #define OP_Pagecount 153
9392 #define OP_MaxPgcnt 154
9393 #define OP_Init 155 /* synopsis: Start at P2 */
9394 #define OP_Noop 156
9395 #define OP_Explain 157
 
9396
9397
9398 /* Properties such as "out2" or "jump" that are specified in
9399 ** comments following the "case" for each opcode in the vdbe.c
9400 ** are encoded into bitvectors as follows:
@@ -9412,23 +9429,23 @@
9412 /* 16 */ 0x01, 0x01, 0x04, 0x24, 0x01, 0x04, 0x05, 0x10,\
9413 /* 24 */ 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,\
9414 /* 32 */ 0x00, 0x00, 0x20, 0x00, 0x00, 0x04, 0x05, 0x04,\
9415 /* 40 */ 0x00, 0x00, 0x01, 0x01, 0x05, 0x05, 0x00, 0x00,\
9416 /* 48 */ 0x00, 0x02, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00,\
9417 /* 56 */ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x08,\
9418 /* 64 */ 0x11, 0x11, 0x11, 0x11, 0x02, 0x02, 0x00, 0x4c,\
9419 /* 72 */ 0x4c, 0x00, 0x00, 0x00, 0x05, 0x05, 0x15, 0x15,\
9420 /* 80 */ 0x15, 0x15, 0x15, 0x15, 0x00, 0x4c, 0x4c, 0x4c,\
9421 /* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00,\
9422 /* 96 */ 0x24, 0x02, 0x00, 0x00, 0x02, 0x00, 0x01, 0x01,\
9423 /* 104 */ 0x01, 0x01, 0x08, 0x08, 0x00, 0x02, 0x01, 0x01,\
9424 /* 112 */ 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00,\
9425 /* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x45, 0x15,\
9426 /* 128 */ 0x01, 0x02, 0x00, 0x01, 0x08, 0x02, 0x05, 0x05,\
9427 /* 136 */ 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04,\
9428 /* 144 */ 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x01,\
9429 /* 152 */ 0x00, 0x02, 0x02, 0x01, 0x00, 0x00,}
9430
9431 /************** End of opcodes.h *********************************************/
9432 /************** Continuing where we left off in vdbe.h ***********************/
9433
9434 /*
@@ -10331,22 +10348,22 @@
10331 Hash trigHash; /* All triggers indexed by name */
10332 Hash fkeyHash; /* All foreign keys by referenced table name */
10333 Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */
10334 u8 file_format; /* Schema format version for this file */
10335 u8 enc; /* Text encoding used by this database */
10336 u16 flags; /* Flags associated with this schema */
10337 int cache_size; /* Number of pages to use in the cache */
10338 };
10339
10340 /*
10341 ** These macros can be used to test, set, or clear bits in the
10342 ** Db.pSchema->flags field.
10343 */
10344 #define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))==(P))
10345 #define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))!=0)
10346 #define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->flags|=(P)
10347 #define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->flags&=~(P)
10348
10349 /*
10350 ** Allowed values for the DB.pSchema->flags field.
10351 **
10352 ** The DB_SchemaLoaded flag is set after the database schema has been
@@ -10932,10 +10949,13 @@
10932 int tnum; /* Root BTree node for this table (see note above) */
10933 i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */
10934 i16 nCol; /* Number of columns in this table */
10935 u16 nRef; /* Number of pointers to this Table */
10936 LogEst szTabRow; /* Estimated size of each table row in bytes */
 
 
 
10937 u8 tabFlags; /* Mask of TF_* values */
10938 u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
10939 #ifndef SQLITE_OMIT_ALTERTABLE
10940 int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
10941 #endif
@@ -11172,10 +11192,13 @@
11172 #define SQLITE_IDXTYPE_PRIMARYKEY 2 /* Is the PRIMARY KEY for the table */
11173
11174 /* Return true if index X is a PRIMARY KEY index */
11175 #define IsPrimaryKeyIndex(X) ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY)
11176
 
 
 
11177 /*
11178 ** Each sample stored in the sqlite_stat3 table is represented in memory
11179 ** using a structure of this type. See documentation at the top of the
11180 ** analyze.c source file for additional information.
11181 */
@@ -11591,10 +11614,11 @@
11591 #define WHERE_AND_ONLY 0x0080 /* Don't use indices for OR terms */
11592 #define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */
11593 #define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
11594 #define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
11595 #define WHERE_SORTBYGROUP 0x0800 /* Support sqlite3WhereIsSorted() */
 
11596
11597 /* Allowed return values from sqlite3WhereIsDistinct()
11598 */
11599 #define WHERE_DISTINCT_NOOP 0 /* DISTINCT keyword not used */
11600 #define WHERE_DISTINCT_UNIQUE 1 /* No duplicates */
@@ -11847,13 +11871,23 @@
11847
11848 /*
11849 ** The yDbMask datatype for the bitmask of all attached databases.
11850 */
11851 #if SQLITE_MAX_ATTACHED>30
11852 typedef sqlite3_uint64 yDbMask;
 
 
 
 
 
11853 #else
11854 typedef unsigned int yDbMask;
 
 
 
 
 
11855 #endif
11856
11857 /*
11858 ** An SQL parser context. A copy of this structure is passed through
11859 ** the parser and down into all the parser action routine in order to
@@ -12522,10 +12556,13 @@
12522 SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse*,Table*);
12523 #else
12524 # define sqlite3ViewGetColumnNames(A,B) 0
12525 #endif
12526
 
 
 
12527 SQLITE_PRIVATE void sqlite3DropTable(Parse*, SrcList*, int, int);
12528 SQLITE_PRIVATE void sqlite3CodeDropTable(Parse*, Table*, int, int);
12529 SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3*, Table*);
12530 #ifndef SQLITE_OMIT_AUTOINCREMENT
12531 SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse);
@@ -12772,10 +12809,11 @@
12772 SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe*, Table*, int);
12773 SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2);
12774 SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
12775 SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr);
12776 SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8);
 
12777 SQLITE_PRIVATE void sqlite3Error(sqlite3*, int, const char*,...);
12778 SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
12779 SQLITE_PRIVATE u8 sqlite3HexToInt(int h);
12780 SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
12781
@@ -12801,11 +12839,11 @@
12801 #ifdef SQLITE_ENABLE_8_3_NAMES
12802 SQLITE_PRIVATE void sqlite3FileSuffix3(const char*, char*);
12803 #else
12804 # define sqlite3FileSuffix3(X,Y)
12805 #endif
12806 SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z,int);
12807
12808 SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8);
12809 SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8);
12810 SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
12811 void(*)(void*));
@@ -13025,15 +13063,25 @@
13025 #else
13026 #define sqlite3BeginBenignMalloc()
13027 #define sqlite3EndBenignMalloc()
13028 #endif
13029
13030 #define IN_INDEX_ROWID 1
13031 #define IN_INDEX_EPH 2
13032 #define IN_INDEX_INDEX_ASC 3
13033 #define IN_INDEX_INDEX_DESC 4
13034 SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, int*);
 
 
 
 
 
 
 
 
 
 
13035
13036 #ifdef SQLITE_ENABLE_ATOMIC_WRITE
13037 SQLITE_PRIVATE int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
13038 SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *);
13039 SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *);
@@ -13876,18 +13924,22 @@
13876 KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
13877 int seekResult; /* Result of previous sqlite3BtreeMoveto() */
13878 int pseudoTableReg; /* Register holding pseudotable content. */
13879 i16 nField; /* Number of fields in the header */
13880 u16 nHdrParsed; /* Number of header fields parsed so far */
 
 
 
13881 i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */
13882 u8 nullRow; /* True if pointing to a row with no data */
13883 u8 rowidIsValid; /* True if lastRowid is valid */
13884 u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
13885 Bool isEphemeral:1; /* True for an ephemeral table */
13886 Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */
13887 Bool isTable:1; /* True if a table requiring integer keys */
13888 Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */
 
13889 sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
13890 i64 seqCount; /* Sequence counter */
13891 i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
13892 i64 lastRowid; /* Rowid being deleted by OP_Delete */
13893 VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */
@@ -18396,11 +18448,11 @@
18396 /*
18397 ** Retrieve a pointer to a static mutex or allocate a new dynamic one.
18398 */
18399 SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int id){
18400 #ifndef SQLITE_OMIT_AUTOINIT
18401 if( sqlite3_initialize() ) return 0;
18402 #endif
18403 return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
18404 }
18405
18406 SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int id){
@@ -18577,11 +18629,11 @@
18577 ** The sqlite3_mutex_alloc() routine allocates a new
18578 ** mutex and returns a pointer to it. If it returns NULL
18579 ** that means that a mutex could not be allocated.
18580 */
18581 static sqlite3_mutex *debugMutexAlloc(int id){
18582 static sqlite3_debug_mutex aStatic[6];
18583 sqlite3_debug_mutex *pNew = 0;
18584 switch( id ){
18585 case SQLITE_MUTEX_FAST:
18586 case SQLITE_MUTEX_RECURSIVE: {
18587 pNew = sqlite3Malloc(sizeof(*pNew));
@@ -18774,14 +18826,17 @@
18774 ** <ul>
18775 ** <li> SQLITE_MUTEX_FAST
18776 ** <li> SQLITE_MUTEX_RECURSIVE
18777 ** <li> SQLITE_MUTEX_STATIC_MASTER
18778 ** <li> SQLITE_MUTEX_STATIC_MEM
18779 ** <li> SQLITE_MUTEX_STATIC_MEM2
18780 ** <li> SQLITE_MUTEX_STATIC_PRNG
18781 ** <li> SQLITE_MUTEX_STATIC_LRU
18782 ** <li> SQLITE_MUTEX_STATIC_PMEM
 
 
 
18783 ** </ul>
18784 **
18785 ** The first two constants cause sqlite3_mutex_alloc() to create
18786 ** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
18787 ** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
@@ -18806,10 +18861,13 @@
18806 ** mutex types, the same mutex is returned on every call that has
18807 ** the same type number.
18808 */
18809 static sqlite3_mutex *pthreadMutexAlloc(int iType){
18810 static sqlite3_mutex staticMutexes[] = {
 
 
 
18811 SQLITE3_MUTEX_INITIALIZER,
18812 SQLITE3_MUTEX_INITIALIZER,
18813 SQLITE3_MUTEX_INITIALIZER,
18814 SQLITE3_MUTEX_INITIALIZER,
18815 SQLITE3_MUTEX_INITIALIZER,
@@ -19041,14 +19099,227 @@
19041 ** May you do good and not evil.
19042 ** May you find forgiveness for yourself and forgive others.
19043 ** May you share freely, never taking more than you give.
19044 **
19045 *************************************************************************
19046 ** This file contains the C functions that implement mutexes for win32
19047 */
19048
19049 #if SQLITE_OS_WIN
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19050 /*
19051 ** Include the header file for the Windows VFS.
19052 */
19053 /************** Include os_win.h in the middle of mutex_w32.c ****************/
19054 /************** Begin file os_win.h ******************************************/
@@ -19124,11 +19395,11 @@
19124 /************** Continuing where we left off in mutex_w32.c ******************/
19125 #endif
19126
19127 /*
19128 ** The code in this file is only used if we are compiling multithreaded
19129 ** on a win32 system.
19130 */
19131 #ifdef SQLITE_MUTEX_W32
19132
19133 /*
19134 ** Each recursive mutex is an instance of the following structure.
@@ -19137,94 +19408,75 @@
19137 CRITICAL_SECTION mutex; /* Mutex controlling the lock */
19138 int id; /* Mutex type */
19139 #ifdef SQLITE_DEBUG
19140 volatile int nRef; /* Number of enterances */
19141 volatile DWORD owner; /* Thread holding this mutex */
19142 int trace; /* True to trace changes */
19143 #endif
19144 };
 
 
 
 
 
 
19145 #define SQLITE_W32_MUTEX_INITIALIZER { 0 }
 
19146 #ifdef SQLITE_DEBUG
19147 #define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0, 0 }
 
19148 #else
19149 #define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 }
19150 #endif
19151
19152 /*
19153 ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
19154 ** or WinCE. Return false (zero) for Win95, Win98, or WinME.
19155 **
19156 ** Here is an interesting observation: Win95, Win98, and WinME lack
19157 ** the LockFileEx() API. But we can still statically link against that
19158 ** API as long as we don't call it win running Win95/98/ME. A call to
19159 ** this routine is used to determine if the host is Win95/98/ME or
19160 ** WinNT/2K/XP so that we will know whether or not we can safely call
19161 ** the LockFileEx() API.
19162 **
19163 ** mutexIsNT() is only used for the TryEnterCriticalSection() API call,
19164 ** which is only available if your application was compiled with
19165 ** _WIN32_WINNT defined to a value >= 0x0400. Currently, the only
19166 ** call to TryEnterCriticalSection() is #ifdef'ed out, so #ifdef
19167 ** this out as well.
19168 */
19169 #if 0
19170 #if SQLITE_OS_WINCE || SQLITE_OS_WINRT
19171 # define mutexIsNT() (1)
19172 #else
19173 static int mutexIsNT(void){
19174 static int osType = 0;
19175 if( osType==0 ){
19176 OSVERSIONINFO sInfo;
19177 sInfo.dwOSVersionInfoSize = sizeof(sInfo);
19178 GetVersionEx(&sInfo);
19179 osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
19180 }
19181 return osType==2;
19182 }
19183 #endif /* SQLITE_OS_WINCE || SQLITE_OS_WINRT */
19184 #endif
19185
19186 #ifdef SQLITE_DEBUG
19187 /*
19188 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
19189 ** intended for use only inside assert() statements.
19190 */
19191 static int winMutexHeld(sqlite3_mutex *p){
19192 return p->nRef!=0 && p->owner==GetCurrentThreadId();
19193 }
 
19194 static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){
19195 return p->nRef==0 || p->owner!=tid;
19196 }
 
19197 static int winMutexNotheld(sqlite3_mutex *p){
19198 DWORD tid = GetCurrentThreadId();
19199 return winMutexNotheld2(p, tid);
19200 }
19201 #endif
19202
19203
19204 /*
19205 ** Initialize and deinitialize the mutex subsystem.
19206 */
19207 static sqlite3_mutex winMutex_staticMutexes[6] = {
 
 
 
19208 SQLITE3_MUTEX_INITIALIZER,
19209 SQLITE3_MUTEX_INITIALIZER,
19210 SQLITE3_MUTEX_INITIALIZER,
19211 SQLITE3_MUTEX_INITIALIZER,
19212 SQLITE3_MUTEX_INITIALIZER,
19213 SQLITE3_MUTEX_INITIALIZER
19214 };
 
19215 static int winMutex_isInit = 0;
19216 /* As winMutexInit() and winMutexEnd() are called as part
19217 ** of the sqlite3_initialize and sqlite3_shutdown()
19218 ** processing, the "interlocked" magic is probably not
19219 ** strictly necessary.
 
19220 */
19221 static LONG winMutex_lock = 0;
19222
 
19223 SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
19224
19225 static int winMutexInit(void){
19226 /* The first to increment to 1 does actual initialization */
19227 if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
19228 int i;
19229 for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
19230 #if SQLITE_OS_WINRT
@@ -19233,20 +19485,21 @@
19233 InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);
19234 #endif
19235 }
19236 winMutex_isInit = 1;
19237 }else{
19238 /* Someone else is in the process of initing the static mutexes */
 
19239 while( !winMutex_isInit ){
19240 sqlite3_win32_sleep(1);
19241 }
19242 }
19243 return SQLITE_OK;
19244 }
19245
19246 static int winMutexEnd(void){
19247 /* The first to decrement to 0 does actual shutdown
19248 ** (which should be the last to shutdown.) */
19249 if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){
19250 if( winMutex_isInit==1 ){
19251 int i;
19252 for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
@@ -19253,11 +19506,11 @@
19253 DeleteCriticalSection(&winMutex_staticMutexes[i].mutex);
19254 }
19255 winMutex_isInit = 0;
19256 }
19257 }
19258 return SQLITE_OK;
19259 }
19260
19261 /*
19262 ** The sqlite3_mutex_alloc() routine allocates a new
19263 ** mutex and returns a pointer to it. If it returns NULL
@@ -19268,14 +19521,17 @@
19268 ** <ul>
19269 ** <li> SQLITE_MUTEX_FAST
19270 ** <li> SQLITE_MUTEX_RECURSIVE
19271 ** <li> SQLITE_MUTEX_STATIC_MASTER
19272 ** <li> SQLITE_MUTEX_STATIC_MEM
19273 ** <li> SQLITE_MUTEX_STATIC_MEM2
19274 ** <li> SQLITE_MUTEX_STATIC_PRNG
19275 ** <li> SQLITE_MUTEX_STATIC_LRU
19276 ** <li> SQLITE_MUTEX_STATIC_PMEM
 
 
 
19277 ** </ul>
19278 **
19279 ** The first two constants cause sqlite3_mutex_alloc() to create
19280 ** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
19281 ** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
@@ -19294,11 +19550,11 @@
19294 ** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
19295 ** SQLITE_MUTEX_RECURSIVE.
19296 **
19297 ** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
19298 ** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
19299 ** returns a different mutex on every call. But for the static
19300 ** mutex types, the same mutex is returned on every call that has
19301 ** the same type number.
19302 */
19303 static sqlite3_mutex *winMutexAlloc(int iType){
19304 sqlite3_mutex *p;
@@ -19305,13 +19561,16 @@
19305
19306 switch( iType ){
19307 case SQLITE_MUTEX_FAST:
19308 case SQLITE_MUTEX_RECURSIVE: {
19309 p = sqlite3MallocZero( sizeof(*p) );
19310 if( p ){
19311 #ifdef SQLITE_DEBUG
19312 p->id = iType;
 
 
 
19313 #endif
19314 #if SQLITE_OS_WINRT
19315 InitializeCriticalSectionEx(&p->mutex, 0, 0);
19316 #else
19317 InitializeCriticalSection(&p->mutex);
@@ -19318,16 +19577,19 @@
19318 #endif
19319 }
19320 break;
19321 }
19322 default: {
19323 assert( winMutex_isInit==1 );
19324 assert( iType-2 >= 0 );
19325 assert( iType-2 < ArraySize(winMutex_staticMutexes) );
 
19326 p = &winMutex_staticMutexes[iType-2];
19327 #ifdef SQLITE_DEBUG
19328 p->id = iType;
 
 
 
19329 #endif
19330 break;
19331 }
19332 }
19333 return p;
@@ -19339,12 +19601,15 @@
19339 ** allocated mutex. SQLite is careful to deallocate every
19340 ** mutex that it allocates.
19341 */
19342 static void winMutexFree(sqlite3_mutex *p){
19343 assert( p );
 
19344 assert( p->nRef==0 && p->owner==0 );
19345 assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
 
 
19346 DeleteCriticalSection(&p->mutex);
19347 sqlite3_free(p);
19348 }
19349
19350 /*
@@ -19357,53 +19622,71 @@
19357 ** mutex must be exited an equal number of times before another thread
19358 ** can enter. If the same thread tries to enter any other kind of mutex
19359 ** more than once, the behavior is undefined.
19360 */
19361 static void winMutexEnter(sqlite3_mutex *p){
 
 
 
19362 #ifdef SQLITE_DEBUG
19363 DWORD tid = GetCurrentThreadId();
19364 assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
 
 
19365 #endif
 
19366 EnterCriticalSection(&p->mutex);
19367 #ifdef SQLITE_DEBUG
19368 assert( p->nRef>0 || p->owner==0 );
19369 p->owner = tid;
19370 p->nRef++;
19371 if( p->trace ){
19372 printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
 
19373 }
19374 #endif
19375 }
 
19376 static int winMutexTry(sqlite3_mutex *p){
19377 #ifndef NDEBUG
19378 DWORD tid = GetCurrentThreadId();
19379 #endif
19380 int rc = SQLITE_BUSY;
 
19381 assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
19382 /*
19383 ** The sqlite3_mutex_try() routine is very rarely used, and when it
19384 ** is used it is merely an optimization. So it is OK for it to always
19385 ** fail.
19386 **
19387 ** The TryEnterCriticalSection() interface is only available on WinNT.
19388 ** And some windows compilers complain if you try to use it without
19389 ** first doing some #defines that prevent SQLite from building on Win98.
19390 ** For that reason, we will omit this optimization for now. See
19391 ** ticket #2685.
19392 */
19393 #if 0
19394 if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){
 
 
 
 
 
 
 
19395 p->owner = tid;
19396 p->nRef++;
 
19397 rc = SQLITE_OK;
19398 }
19399 #else
19400 UNUSED_PARAMETER(p);
19401 #endif
19402 #ifdef SQLITE_DEBUG
19403 if( rc==SQLITE_OK && p->trace ){
19404 printf("try mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
 
19405 }
19406 #endif
19407 return rc;
19408 }
19409
@@ -19412,22 +19695,27 @@
19412 ** previously entered by the same thread. The behavior
19413 ** is undefined if the mutex is not currently entered or
19414 ** is not currently allocated. SQLite will never do either.
19415 */
19416 static void winMutexLeave(sqlite3_mutex *p){
19417 #ifndef NDEBUG
19418 DWORD tid = GetCurrentThreadId();
 
 
 
19419 assert( p->nRef>0 );
19420 assert( p->owner==tid );
19421 p->nRef--;
19422 if( p->nRef==0 ) p->owner = 0;
19423 assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
19424 #endif
 
19425 LeaveCriticalSection(&p->mutex);
19426 #ifdef SQLITE_DEBUG
19427 if( p->trace ){
19428 printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
 
19429 }
19430 #endif
19431 }
19432
19433 SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
@@ -19445,13 +19733,13 @@
19445 #else
19446 0,
19447 0
19448 #endif
19449 };
19450
19451 return &sMutex;
19452 }
 
19453 #endif /* SQLITE_MUTEX_W32 */
19454
19455 /************** End of mutex_w32.c *******************************************/
19456 /************** Begin file malloc.c ******************************************/
19457 /*
@@ -22422,13 +22710,13 @@
22422 testcase( c==(+1) );
22423 }
22424 return c;
22425 }
22426
22427
22428 /*
22429 ** Convert zNum to a 64-bit signed integer.
 
22430 **
22431 ** If the zNum value is representable as a 64-bit twos-complement
22432 ** integer, then write that value into *pNum and return 0.
22433 **
22434 ** If zNum is exactly 9223372036854775808, return 2. This special
@@ -22511,14 +22799,48 @@
22511 assert( u-1==LARGEST_INT64 );
22512 return neg ? 0 : 2;
22513 }
22514 }
22515 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22516
22517 /*
22518 ** If zNum represents an integer that will fit in 32-bits, then set
22519 ** *pValue to that integer and return true. Otherwise return false.
 
 
22520 **
22521 ** Any non-numeric characters that following zNum are ignored.
22522 ** This is different from sqlite3Atoi64() which requires the
22523 ** input number to be zero-terminated.
22524 */
@@ -22530,11 +22852,29 @@
22530 neg = 1;
22531 zNum++;
22532 }else if( zNum[0]=='+' ){
22533 zNum++;
22534 }
22535 while( zNum[0]=='0' ) zNum++;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22536 for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){
22537 v = v*10 + c;
22538 }
22539
22540 /* The longest decimal representation of a 32 bit integer is 10 digits:
@@ -23606,43 +23946,43 @@
23606 /* 47 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
23607 /* 48 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
23608 /* 49 */ "Count" OpHelp("r[P2]=count()"),
23609 /* 50 */ "ReadCookie" OpHelp(""),
23610 /* 51 */ "SetCookie" OpHelp(""),
23611 /* 52 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
23612 /* 53 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
23613 /* 54 */ "OpenAutoindex" OpHelp("nColumn=P2"),
23614 /* 55 */ "OpenEphemeral" OpHelp("nColumn=P2"),
23615 /* 56 */ "SorterOpen" OpHelp(""),
23616 /* 57 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
23617 /* 58 */ "Close" OpHelp(""),
23618 /* 59 */ "SeekLT" OpHelp(""),
23619 /* 60 */ "SeekLE" OpHelp(""),
23620 /* 61 */ "SeekGE" OpHelp(""),
23621 /* 62 */ "SeekGT" OpHelp(""),
23622 /* 63 */ "Seek" OpHelp("intkey=r[P2]"),
23623 /* 64 */ "NoConflict" OpHelp("key=r[P3@P4]"),
23624 /* 65 */ "NotFound" OpHelp("key=r[P3@P4]"),
23625 /* 66 */ "Found" OpHelp("key=r[P3@P4]"),
23626 /* 67 */ "NotExists" OpHelp("intkey=r[P3]"),
23627 /* 68 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
23628 /* 69 */ "NewRowid" OpHelp("r[P2]=rowid"),
23629 /* 70 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
23630 /* 71 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"),
23631 /* 72 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"),
23632 /* 73 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"),
23633 /* 74 */ "Delete" OpHelp(""),
23634 /* 75 */ "ResetCount" OpHelp(""),
23635 /* 76 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
23636 /* 77 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
23637 /* 78 */ "Ne" OpHelp("if r[P1]!=r[P3] goto P2"),
23638 /* 79 */ "Eq" OpHelp("if r[P1]==r[P3] goto P2"),
23639 /* 80 */ "Gt" OpHelp("if r[P1]>r[P3] goto P2"),
23640 /* 81 */ "Le" OpHelp("if r[P1]<=r[P3] goto P2"),
23641 /* 82 */ "Lt" OpHelp("if r[P1]<r[P3] goto P2"),
23642 /* 83 */ "Ge" OpHelp("if r[P1]>=r[P3] goto P2"),
23643 /* 84 */ "SorterCompare" OpHelp("if key(P1)!=rtrim(r[P3],P4) goto P2"),
23644 /* 85 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
23645 /* 86 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
23646 /* 87 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
23647 /* 88 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
23648 /* 89 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
@@ -23649,73 +23989,74 @@
23649 /* 90 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
23650 /* 91 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
23651 /* 92 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
23652 /* 93 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
23653 /* 94 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
23654 /* 95 */ "SorterData" OpHelp("r[P2]=data"),
23655 /* 96 */ "BitNot" OpHelp("r[P1]= ~r[P1]"),
23656 /* 97 */ "String8" OpHelp("r[P2]='P4'"),
23657 /* 98 */ "RowKey" OpHelp("r[P2]=key"),
23658 /* 99 */ "RowData" OpHelp("r[P2]=data"),
23659 /* 100 */ "Rowid" OpHelp("r[P2]=rowid"),
23660 /* 101 */ "NullRow" OpHelp(""),
23661 /* 102 */ "Last" OpHelp(""),
23662 /* 103 */ "SorterSort" OpHelp(""),
23663 /* 104 */ "Sort" OpHelp(""),
23664 /* 105 */ "Rewind" OpHelp(""),
23665 /* 106 */ "SorterInsert" OpHelp(""),
23666 /* 107 */ "IdxInsert" OpHelp("key=r[P2]"),
23667 /* 108 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
23668 /* 109 */ "IdxRowid" OpHelp("r[P2]=rowid"),
23669 /* 110 */ "IdxLE" OpHelp("key=r[P3@P4]"),
23670 /* 111 */ "IdxGT" OpHelp("key=r[P3@P4]"),
23671 /* 112 */ "IdxLT" OpHelp("key=r[P3@P4]"),
23672 /* 113 */ "IdxGE" OpHelp("key=r[P3@P4]"),
23673 /* 114 */ "Destroy" OpHelp(""),
23674 /* 115 */ "Clear" OpHelp(""),
23675 /* 116 */ "ResetSorter" OpHelp(""),
23676 /* 117 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"),
23677 /* 118 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"),
23678 /* 119 */ "ParseSchema" OpHelp(""),
23679 /* 120 */ "LoadAnalysis" OpHelp(""),
23680 /* 121 */ "DropTable" OpHelp(""),
23681 /* 122 */ "DropIndex" OpHelp(""),
23682 /* 123 */ "DropTrigger" OpHelp(""),
23683 /* 124 */ "IntegrityCk" OpHelp(""),
23684 /* 125 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
23685 /* 126 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
23686 /* 127 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
23687 /* 128 */ "Program" OpHelp(""),
23688 /* 129 */ "Param" OpHelp(""),
23689 /* 130 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
23690 /* 131 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
23691 /* 132 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
23692 /* 133 */ "Real" OpHelp("r[P2]=P4"),
23693 /* 134 */ "IfPos" OpHelp("if r[P1]>0 goto P2"),
23694 /* 135 */ "IfNeg" OpHelp("if r[P1]<0 goto P2"),
23695 /* 136 */ "IfZero" OpHelp("r[P1]+=P3, if r[P1]==0 goto P2"),
23696 /* 137 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
23697 /* 138 */ "IncrVacuum" OpHelp(""),
23698 /* 139 */ "Expire" OpHelp(""),
23699 /* 140 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
23700 /* 141 */ "VBegin" OpHelp(""),
23701 /* 142 */ "VCreate" OpHelp(""),
23702 /* 143 */ "ToText" OpHelp(""),
23703 /* 144 */ "ToBlob" OpHelp(""),
23704 /* 145 */ "ToNumeric" OpHelp(""),
23705 /* 146 */ "ToInt" OpHelp(""),
23706 /* 147 */ "ToReal" OpHelp(""),
23707 /* 148 */ "VDestroy" OpHelp(""),
23708 /* 149 */ "VOpen" OpHelp(""),
23709 /* 150 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
23710 /* 151 */ "VNext" OpHelp(""),
23711 /* 152 */ "VRename" OpHelp(""),
23712 /* 153 */ "Pagecount" OpHelp(""),
23713 /* 154 */ "MaxPgcnt" OpHelp(""),
23714 /* 155 */ "Init" OpHelp("Start at P2"),
23715 /* 156 */ "Noop" OpHelp(""),
23716 /* 157 */ "Explain" OpHelp(""),
 
23717 };
23718 return azName[i];
23719 }
23720 #endif
23721
@@ -23814,15 +24155,14 @@
23814 #include <unistd.h>
23815 /* #include <time.h> */
23816 #include <sys/time.h>
23817 #include <errno.h>
23818 #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
23819 #include <sys/mman.h>
23820 #endif
23821
23822
23823 #if SQLITE_ENABLE_LOCKING_STYLE
23824 # include <sys/ioctl.h>
23825 # if OS_VXWORKS
23826 # include <semaphore.h>
23827 # include <limits.h>
23828 # else
@@ -24246,11 +24586,15 @@
24246 ** On some systems, calls to fchown() will trigger a message in a security
24247 ** log if they come from non-root processes. So avoid calling fchown() if
24248 ** we are not running as root.
24249 */
24250 static int posixFchown(int fd, uid_t uid, gid_t gid){
 
 
 
24251 return geteuid() ? 0 : fchown(fd,uid,gid);
 
24252 }
24253
24254 /* Forward reference */
24255 static int openDirectory(const char*, int*);
24256 static int unixGetpagesize(void);
@@ -24302,11 +24646,11 @@
24302 #define osFcntl ((int(*)(int,int,...))aSyscall[7].pCurrent)
24303
24304 { "read", (sqlite3_syscall_ptr)read, 0 },
24305 #define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
24306
24307 #if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
24308 { "pread", (sqlite3_syscall_ptr)pread, 0 },
24309 #else
24310 { "pread", (sqlite3_syscall_ptr)0, 0 },
24311 #endif
24312 #define osPread ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].pCurrent)
@@ -24319,11 +24663,11 @@
24319 #define osPread64 ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].pCurrent)
24320
24321 { "write", (sqlite3_syscall_ptr)write, 0 },
24322 #define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
24323
24324 #if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
24325 { "pwrite", (sqlite3_syscall_ptr)pwrite, 0 },
24326 #else
24327 { "pwrite", (sqlite3_syscall_ptr)0, 0 },
24328 #endif
24329 #define osPwrite ((ssize_t(*)(int,const void*,size_t,off_t))\
@@ -24689,20 +25033,10 @@
24689 }
24690 /* else fall through */
24691 case EPERM:
24692 return SQLITE_PERM;
24693
24694 /* EDEADLK is only possible if a call to fcntl(F_SETLKW) is made. And
24695 ** this module never makes such a call. And the code in SQLite itself
24696 ** asserts that SQLITE_IOERR_BLOCKED is never returned. For these reasons
24697 ** this case is also commented out. If the system does set errno to EDEADLK,
24698 ** the default SQLITE_IOERR_XXX code will be returned. */
24699 #if 0
24700 case EDEADLK:
24701 return SQLITE_IOERR_BLOCKED;
24702 #endif
24703
24704 #if EOPNOTSUPP!=ENOTSUP
24705 case EOPNOTSUPP:
24706 /* something went terribly awry, unless during file system support
24707 * introspection, in which it actually means what it says */
24708 #endif
@@ -25231,13 +25565,17 @@
25231
25232 /*
25233 ** Return TRUE if pFile has been renamed or unlinked since it was first opened.
25234 */
25235 static int fileHasMoved(unixFile *pFile){
 
 
 
25236 struct stat buf;
25237 return pFile->pInode!=0 &&
25238 (osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino);
 
25239 }
25240
25241
25242 /*
25243 ** Check a unixFile that is a database. Verify the following:
@@ -26376,11 +26714,10 @@
26376 }
26377
26378 /* Otherwise see if some other process holds it. */
26379 if( !reserved ){
26380 sem_t *pSem = pFile->pInode->pSem;
26381 struct stat statBuf;
26382
26383 if( sem_trywait(pSem)==-1 ){
26384 int tErrno = errno;
26385 if( EAGAIN != tErrno ){
26386 rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
@@ -26429,11 +26766,10 @@
26429 ** This routine will only increase a lock. Use the sqlite3OsUnlock()
26430 ** routine to lower a locking level.
26431 */
26432 static int semLock(sqlite3_file *id, int eFileLock) {
26433 unixFile *pFile = (unixFile*)id;
26434 int fd;
26435 sem_t *pSem = pFile->pInode->pSem;
26436 int rc = SQLITE_OK;
26437
26438 /* if we already have a lock, it is exclusive.
26439 ** Just adjust level and punt on outta here. */
@@ -31713,22 +32049,18 @@
31713 #ifndef NTDDI_WINBLUE
31714 # define NTDDI_WINBLUE 0x06030000
31715 #endif
31716
31717 /*
31718 ** Check if the GetVersionEx[AW] functions should be considered deprecated
31719 ** and avoid using them in that case. It should be noted here that if the
31720 ** value of the SQLITE_WIN32_GETVERSIONEX pre-processor macro is zero
31721 ** (whether via this block or via being manually specified), that implies
31722 ** the underlying operating system will always be based on the Windows NT
31723 ** Kernel.
31724 */
31725 #ifndef SQLITE_WIN32_GETVERSIONEX
31726 # if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINBLUE
31727 # define SQLITE_WIN32_GETVERSIONEX 0
31728 # else
31729 # define SQLITE_WIN32_GETVERSIONEX 1
31730 # endif
31731 #endif
31732
31733 /*
31734 ** This constant should already be defined (in the "WinDef.h" SDK file).
@@ -31796,11 +32128,11 @@
31796 /*
31797 ** This macro is used when a local variable is set to a value that is
31798 ** [sometimes] not used by the code (e.g. via conditional compilation).
31799 */
31800 #ifndef UNUSED_VARIABLE_VALUE
31801 # define UNUSED_VARIABLE_VALUE(x) (void)(x)
31802 #endif
31803
31804 /*
31805 ** Returns the character that should be used as the directory separator.
31806 */
@@ -31845,11 +32177,11 @@
31845
31846 /*
31847 ** Some Microsoft compilers lack this definition.
31848 */
31849 #ifndef INVALID_FILE_ATTRIBUTES
31850 # define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
31851 #endif
31852
31853 #ifndef FILE_FLAG_MASK
31854 # define FILE_FLAG_MASK (0xFF3C0000)
31855 #endif
@@ -31895,11 +32227,11 @@
31895 #endif
31896 const char *zPath; /* Full pathname of this file */
31897 int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */
31898 #if SQLITE_OS_WINCE
31899 LPWSTR zDeleteOnClose; /* Name of file to delete when closing */
31900 HANDLE hMutex; /* Mutex used to control access to shared lock */
31901 HANDLE hShared; /* Shared memory segment used for locking */
31902 winceLock local; /* Locks obtained by this instance of winFile */
31903 winceLock *shared; /* Global shared lock memory for the file */
31904 #endif
31905 #if SQLITE_MAX_MMAP_SIZE>0
@@ -32055,14 +32387,13 @@
32055 **
32056 ** In order to facilitate testing on a WinNT system, the test fixture
32057 ** can manually set this value to 1 to emulate Win98 behavior.
32058 */
32059 #ifdef SQLITE_TEST
32060 SQLITE_API int sqlite3_os_type = 0;
32061 #elif !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \
32062 defined(SQLITE_WIN32_HAS_ANSI) && defined(SQLITE_WIN32_HAS_WIDE)
32063 static int sqlite3_os_type = 0;
32064 #endif
32065
32066 #ifndef SYSCALL
32067 # define SYSCALL sqlite3_syscall_ptr
32068 #endif
@@ -32689,10 +33020,26 @@
32689 #endif
32690
32691 #define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
32692 LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[75].pCurrent)
32693
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32694 }; /* End of the overrideable system calls */
32695
32696 /*
32697 ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
32698 ** "win32" VFSes. Return SQLITE_OK opon successfully updating the
@@ -32939,26 +33286,42 @@
32939 #elif SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI)
32940 # define osIsNT() (1)
32941 #elif !defined(SQLITE_WIN32_HAS_WIDE)
32942 # define osIsNT() (0)
32943 #else
32944 static int osIsNT(void){
32945 if( sqlite3_os_type==0 ){
32946 #if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WIN8
32947 OSVERSIONINFOW sInfo;
32948 sInfo.dwOSVersionInfoSize = sizeof(sInfo);
32949 osGetVersionExW(&sInfo);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32950 #else
32951 OSVERSIONINFOA sInfo;
32952 sInfo.dwOSVersionInfoSize = sizeof(sInfo);
32953 osGetVersionExA(&sInfo);
32954 #endif
32955 sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
32956 }
32957 return sqlite3_os_type==2;
32958 }
32959 #endif
32960
32961 #ifdef SQLITE_WIN32_MALLOC
32962 /*
32963 ** Allocate nBytes of memory.
32964 */
@@ -33162,11 +33525,11 @@
33162 sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32());
33163 }
33164 #endif /* SQLITE_WIN32_MALLOC */
33165
33166 /*
33167 ** Convert a UTF-8 string to Microsoft Unicode (UTF-16?).
33168 **
33169 ** Space to hold the returned string is obtained from malloc.
33170 */
33171 static LPWSTR winUtf8ToUnicode(const char *zFilename){
33172 int nChar;
@@ -33215,11 +33578,11 @@
33215 }
33216
33217 /*
33218 ** Convert an ANSI string to Microsoft Unicode, based on the
33219 ** current codepage settings for file apis.
33220 **
33221 ** Space to hold the returned string is obtained
33222 ** from sqlite3_malloc.
33223 */
33224 static LPWSTR winMbcsToUnicode(const char *zFilename){
33225 int nByte;
@@ -33289,11 +33652,11 @@
33289 sqlite3_free(zTmpWide);
33290 return zFilenameUtf8;
33291 }
33292
33293 /*
33294 ** Convert UTF-8 to multibyte character string. Space to hold the
33295 ** returned string is obtained from sqlite3_malloc().
33296 */
33297 SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
33298 char *zFilenameMbcs;
33299 LPWSTR zTmpWide;
@@ -33429,15 +33792,15 @@
33429 ** This function - winLogErrorAtLine() - is only ever called via the macro
33430 ** winLogError().
33431 **
33432 ** This routine is invoked after an error occurs in an OS function.
33433 ** It logs a message using sqlite3_log() containing the current value of
33434 ** error code and, if possible, the human-readable equivalent from
33435 ** FormatMessage.
33436 **
33437 ** The first argument passed to the macro should be the error code that
33438 ** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
33439 ** The two subsequent arguments should be the name of the OS function that
33440 ** failed and the associated file-system path, if any.
33441 */
33442 #define winLogError(a,b,c,d) winLogErrorAtLine(a,b,c,d,__LINE__)
33443 static int winLogErrorAtLine(
@@ -33464,11 +33827,11 @@
33464 return errcode;
33465 }
33466
33467 /*
33468 ** The number of times that a ReadFile(), WriteFile(), and DeleteFile()
33469 ** will be retried following a locking error - probably caused by
33470 ** antivirus software. Also the initial delay before the first retry.
33471 ** The delay increases linearly with each retry.
33472 */
33473 #ifndef SQLITE_WIN32_IOERR_RETRY
33474 # define SQLITE_WIN32_IOERR_RETRY 10
@@ -33539,11 +33902,11 @@
33539 /*
33540 ** Log a I/O error retry episode.
33541 */
33542 static void winLogIoerr(int nRetry){
33543 if( nRetry ){
33544 sqlite3_log(SQLITE_IOERR,
33545 "delayed %dms for lock/sharing conflict",
33546 winIoerrRetryDelay*nRetry*(nRetry+1)/2
33547 );
33548 }
33549 }
@@ -33633,21 +33996,21 @@
33633 "winceCreateLock1", zFilename);
33634 }
33635
33636 /* Acquire the mutex before continuing */
33637 winceMutexAcquire(pFile->hMutex);
33638
33639 /* Since the names of named mutexes, semaphores, file mappings etc are
33640 ** case-sensitive, take advantage of that by uppercasing the mutex name
33641 ** and using that as the shared filemapping name.
33642 */
33643 osCharUpperW(zName);
33644 pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
33645 PAGE_READWRITE, 0, sizeof(winceLock),
33646 zName);
33647
33648 /* Set a flag that indicates we're the first to create the memory so it
33649 ** must be zero-initialized */
33650 lastErrno = osGetLastError();
33651 if (lastErrno == ERROR_ALREADY_EXISTS){
33652 bInit = FALSE;
33653 }
@@ -33654,11 +34017,11 @@
33654
33655 sqlite3_free(zName);
33656
33657 /* If we succeeded in making the shared memory handle, map it. */
33658 if( pFile->hShared ){
33659 pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared,
33660 FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
33661 /* If mapping failed, close the shared memory handle and erase it */
33662 if( !pFile->shared ){
33663 pFile->lastErrno = osGetLastError();
33664 winLogError(SQLITE_IOERR, pFile->lastErrno,
@@ -33680,11 +34043,11 @@
33680 winceMutexRelease(pFile->hMutex);
33681 osCloseHandle(pFile->hMutex);
33682 pFile->hMutex = NULL;
33683 return SQLITE_IOERR;
33684 }
33685
33686 /* Initialize the shared memory if we're supposed to */
33687 if( bInit ){
33688 memset(pFile->shared, 0, sizeof(winceLock));
33689 }
33690
@@ -33718,17 +34081,17 @@
33718 /* De-reference and close our copy of the shared memory handle */
33719 osUnmapViewOfFile(pFile->shared);
33720 osCloseHandle(pFile->hShared);
33721
33722 /* Done with the mutex */
33723 winceMutexRelease(pFile->hMutex);
33724 osCloseHandle(pFile->hMutex);
33725 pFile->hMutex = NULL;
33726 }
33727 }
33728
33729 /*
33730 ** An implementation of the LockFile() API of Windows for CE
33731 */
33732 static BOOL winceLockFile(
33733 LPHANDLE phFile,
33734 DWORD dwFileOffsetLow,
@@ -33935,12 +34298,12 @@
33935 #ifndef INVALID_SET_FILE_POINTER
33936 # define INVALID_SET_FILE_POINTER ((DWORD)-1)
33937 #endif
33938
33939 /*
33940 ** Move the current position of the file handle passed as the first
33941 ** argument to offset iOffset within the file. If successful, return 0.
33942 ** Otherwise, set pFile->lastErrno and return non-zero.
33943 */
33944 static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){
33945 #if !SQLITE_OS_WINRT
33946 LONG upperBits; /* Most sig. 32 bits of new offset */
@@ -33951,15 +34314,15 @@
33951 OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset));
33952
33953 upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
33954 lowerBits = (LONG)(iOffset & 0xffffffff);
33955
33956 /* API oddity: If successful, SetFilePointer() returns a dword
33957 ** containing the lower 32-bits of the new file-offset. Or, if it fails,
33958 ** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
33959 ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
33960 ** whether an error has actually occurred, it is also necessary to call
33961 ** GetLastError().
33962 */
33963 dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
33964
33965 if( (dwRet==INVALID_SET_FILE_POINTER
@@ -34038,11 +34401,11 @@
34038 winceDestroyLock(pFile);
34039 if( pFile->zDeleteOnClose ){
34040 int cnt = 0;
34041 while(
34042 osDeleteFileW(pFile->zDeleteOnClose)==0
34043 && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
34044 && cnt++ < WINCE_DELETION_ATTEMPTS
34045 ){
34046 sqlite3_win32_sleep(100); /* Wait a little before trying again */
34047 }
34048 sqlite3_free(pFile->zDeleteOnClose);
@@ -34886,11 +35249,11 @@
34886 winFile *p = (winFile*)id;
34887 return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
34888 ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
34889 }
34890
34891 /*
34892 ** Windows will only let you create file view mappings
34893 ** on allocation size granularity boundaries.
34894 ** During sqlite3_os_init() we do a GetSystemInfo()
34895 ** to get the granularity size.
34896 */
@@ -34898,15 +35261,15 @@
34898
34899 #ifndef SQLITE_OMIT_WAL
34900
34901 /*
34902 ** Helper functions to obtain and relinquish the global mutex. The
34903 ** global mutex is used to protect the winLockInfo objects used by
34904 ** this file, all of which may be shared by multiple threads.
34905 **
34906 ** Function winShmMutexHeld() is used to assert() that the global mutex
34907 ** is held when required. This function is only used as part of assert()
34908 ** statements. e.g.
34909 **
34910 ** winShmEnterMutex()
34911 ** assert( winShmMutexHeld() );
34912 ** winShmLeaveMutex()
@@ -34932,14 +35295,14 @@
34932 **
34933 ** winShmMutexHeld() must be true when creating or destroying
34934 ** this object or while reading or writing the following fields:
34935 **
34936 ** nRef
34937 ** pNext
34938 **
34939 ** The following fields are read-only after the object is created:
34940 **
34941 ** fid
34942 ** zFilename
34943 **
34944 ** Either winShmNode.mutex must be held or winShmNode.nRef==0 and
34945 ** winShmMutexHeld() is true when reading or writing any other field
@@ -35031,11 +35394,11 @@
35031 /* Initialize the locking parameters */
35032 DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
35033 if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
35034 rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0);
35035 }
35036
35037 if( rc!= 0 ){
35038 rc = SQLITE_OK;
35039 }else{
35040 pFile->lastErrno = osGetLastError();
35041 rc = SQLITE_BUSY;
@@ -35127,11 +35490,11 @@
35127 sqlite3_free(p);
35128 return SQLITE_IOERR_NOMEM;
35129 }
35130 pNew->zFilename = (char*)&pNew[1];
35131 sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
35132 sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
35133
35134 /* Look to see if there is an existing winShmNode that can be used.
35135 ** If no matching winShmNode currently exists, create a new one.
35136 */
35137 winShmEnterMutex();
@@ -35164,11 +35527,11 @@
35164 if( SQLITE_OK!=rc ){
35165 goto shm_open_err;
35166 }
35167
35168 /* Check to see if another process is holding the dead-man switch.
35169 ** If not, truncate the file to zero length.
35170 */
35171 if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
35172 rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
35173 if( rc!=SQLITE_OK ){
35174 rc = winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
@@ -35193,11 +35556,11 @@
35193
35194 /* The reference count on pShmNode has already been incremented under
35195 ** the cover of the winShmEnterMutex() mutex and the pointer from the
35196 ** new (struct winShm) object to the pShmNode has been set. All that is
35197 ** left to do is to link the new object into the linked list starting
35198 ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
35199 ** mutex.
35200 */
35201 sqlite3_mutex_enter(pShmNode->mutex);
35202 p->pNext = pShmNode->pFirst;
35203 pShmNode->pFirst = p;
@@ -35213,11 +35576,11 @@
35213 winShmLeaveMutex();
35214 return rc;
35215 }
35216
35217 /*
35218 ** Close a connection to shared-memory. Delete the underlying
35219 ** storage if deleteFlag is true.
35220 */
35221 static int winShmUnmap(
35222 sqlite3_file *fd, /* Database holding shared memory */
35223 int deleteFlag /* Delete after closing if true */
@@ -35302,11 +35665,11 @@
35302
35303 /* Undo the local locks */
35304 if( rc==SQLITE_OK ){
35305 p->exclMask &= ~mask;
35306 p->sharedMask &= ~mask;
35307 }
35308 }else if( flags & SQLITE_SHM_SHARED ){
35309 u16 allShared = 0; /* Union of locks held by connections other than "p" */
35310
35311 /* Find out which shared locks are already held by sibling connections.
35312 ** If any sibling already holds an exclusive lock, go ahead and return
@@ -35341,11 +35704,11 @@
35341 if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
35342 rc = SQLITE_BUSY;
35343 break;
35344 }
35345 }
35346
35347 /* Get the exclusive locks at the system level. Then if successful
35348 ** also mark the local connection as being locked.
35349 */
35350 if( rc==SQLITE_OK ){
35351 rc = winShmSystemLock(pShmNode, _SHM_WRLCK, ofst+WIN_SHM_BASE, n);
@@ -35361,11 +35724,11 @@
35361 sqlite3ErrName(rc)));
35362 return rc;
35363 }
35364
35365 /*
35366 ** Implement a memory barrier or memory fence on shared memory.
35367 **
35368 ** All loads and stores begun before the barrier must complete before
35369 ** any load or store begun after the barrier.
35370 */
35371 static void winShmBarrier(
@@ -35376,26 +35739,26 @@
35376 winShmEnterMutex();
35377 winShmLeaveMutex();
35378 }
35379
35380 /*
35381 ** This function is called to obtain a pointer to region iRegion of the
35382 ** shared-memory associated with the database file fd. Shared-memory regions
35383 ** are numbered starting from zero. Each shared-memory region is szRegion
35384 ** bytes in size.
35385 **
35386 ** If an error occurs, an error code is returned and *pp is set to NULL.
35387 **
35388 ** Otherwise, if the isWrite parameter is 0 and the requested shared-memory
35389 ** region has not been allocated (by any client, including one running in a
35390 ** separate process), then *pp is set to NULL and SQLITE_OK returned. If
35391 ** isWrite is non-zero and the requested shared-memory region has not yet
35392 ** been allocated, it is allocated by this function.
35393 **
35394 ** If the shared-memory region has already been allocated or is allocated by
35395 ** this call as described above, then it is mapped into this processes
35396 ** address space (if it is not already), *pp is set to point to the mapped
35397 ** memory and SQLITE_OK returned.
35398 */
35399 static int winShmMap(
35400 sqlite3_file *fd, /* Handle open on database file */
35401 int iRegion, /* Region to retrieve */
@@ -35463,21 +35826,21 @@
35463 pShmNode->aRegion = apNew;
35464
35465 while( pShmNode->nRegion<=iRegion ){
35466 HANDLE hMap = NULL; /* file-mapping handle */
35467 void *pMap = 0; /* Mapped memory region */
35468
35469 #if SQLITE_OS_WINRT
35470 hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
35471 NULL, PAGE_READWRITE, nByte, NULL
35472 );
35473 #elif defined(SQLITE_WIN32_HAS_WIDE)
35474 hMap = osCreateFileMappingW(pShmNode->hFile.h,
35475 NULL, PAGE_READWRITE, 0, nByte, NULL
35476 );
35477 #elif defined(SQLITE_WIN32_HAS_ANSI)
35478 hMap = osCreateFileMappingA(pShmNode->hFile.h,
35479 NULL, PAGE_READWRITE, 0, nByte, NULL
35480 );
35481 #endif
35482 OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
35483 osGetCurrentProcessId(), pShmNode->nRegion, nByte,
@@ -35570,18 +35933,18 @@
35570 return SQLITE_OK;
35571 }
35572
35573 /*
35574 ** Memory map or remap the file opened by file-descriptor pFd (if the file
35575 ** is already mapped, the existing mapping is replaced by the new). Or, if
35576 ** there already exists a mapping for this file, and there are still
35577 ** outstanding xFetch() references to it, this function is a no-op.
35578 **
35579 ** If parameter nByte is non-negative, then it is the requested size of
35580 ** the mapping to create. Otherwise, if nByte is less than zero, then the
35581 ** requested size is the size of the file on disk. The actual size of the
35582 ** created mapping is either the requested size or the value configured
35583 ** using SQLITE_FCNTL_MMAP_SIZE, whichever is smaller.
35584 **
35585 ** SQLITE_OK is returned if no error occurs (even if the mapping is not
35586 ** recreated as a result of outstanding references) or an SQLite error
35587 ** code otherwise.
@@ -35606,11 +35969,11 @@
35606 }
35607 if( nMap>pFd->mmapSizeMax ){
35608 nMap = pFd->mmapSizeMax;
35609 }
35610 nMap &= ~(sqlite3_int64)(winSysInfo.dwPageSize - 1);
35611
35612 if( nMap==0 && pFd->mmapSize>0 ){
35613 winUnmapfile(pFd);
35614 }
35615 if( nMap!=pFd->mmapSize ){
35616 void *pNew = 0;
@@ -35678,11 +36041,11 @@
35678 ** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
35679 ** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
35680 ** Finally, if an error does occur, return an SQLite error code. The final
35681 ** value of *pp is undefined in this case.
35682 **
35683 ** If this function does return a pointer, the caller must eventually
35684 ** release the reference by calling winUnfetch().
35685 */
35686 static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
35687 #if SQLITE_MAX_MMAP_SIZE>0
35688 winFile *pFd = (winFile*)fd; /* The underlying database file */
@@ -35713,24 +36076,24 @@
35713 osGetCurrentProcessId(), fd, pp, *pp));
35714 return SQLITE_OK;
35715 }
35716
35717 /*
35718 ** If the third argument is non-NULL, then this function releases a
35719 ** reference obtained by an earlier call to winFetch(). The second
35720 ** argument passed to this function must be the same as the corresponding
35721 ** argument that was passed to the winFetch() invocation.
35722 **
35723 ** Or, if the third argument is NULL, then this function is being called
35724 ** to inform the VFS layer that, according to POSIX, any existing mapping
35725 ** may now be invalid and should be unmapped.
35726 */
35727 static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){
35728 #if SQLITE_MAX_MMAP_SIZE>0
35729 winFile *pFd = (winFile*)fd; /* The underlying database file */
35730
35731 /* If p==0 (unmap the entire file) then there must be no outstanding
35732 ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
35733 ** then there must be at least one outstanding. */
35734 assert( (p==0)==(pFd->nFetchOut==0) );
35735
35736 /* If p!=0, it must match the iOff value. */
@@ -35872,11 +36235,11 @@
35872 int nMax, nBuf, nDir, nLen;
35873 char *zBuf;
35874
35875 /* It's odd to simulate an io-error here, but really this is just
35876 ** using the io-error infrastructure to test that SQLite handles this
35877 ** function failing.
35878 */
35879 SimulateIOError( return SQLITE_IOERR );
35880
35881 /* Allocate a temporary buffer to store the fully qualified file
35882 ** name for the temporary file. If this fails, we cannot continue.
@@ -36054,11 +36417,11 @@
36054 OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
36055 return winLogError(SQLITE_ERROR, 0, "winGetTempname4", 0);
36056 }
36057
36058 /*
36059 ** Check that the output buffer is large enough for the temporary file
36060 ** name in the following format:
36061 **
36062 ** "<temporary_directory>/etilqs_XXXXXXXXXXXXXXX\0\0"
36063 **
36064 ** If not, return SQLITE_ERROR. The number 17 is used here in order to
@@ -36157,42 +36520,42 @@
36157 int isReadonly = (flags & SQLITE_OPEN_READONLY);
36158 int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
36159
36160 #ifndef NDEBUG
36161 int isOpenJournal = (isCreate && (
36162 eType==SQLITE_OPEN_MASTER_JOURNAL
36163 || eType==SQLITE_OPEN_MAIN_JOURNAL
36164 || eType==SQLITE_OPEN_WAL
36165 ));
36166 #endif
36167
36168 OSTRACE(("OPEN name=%s, pFile=%p, flags=%x, pOutFlags=%p\n",
36169 zUtf8Name, id, flags, pOutFlags));
36170
36171 /* Check the following statements are true:
36172 **
36173 ** (a) Exactly one of the READWRITE and READONLY flags must be set, and
36174 ** (b) if CREATE is set, then READWRITE must also be set, and
36175 ** (c) if EXCLUSIVE is set, then CREATE must also be set.
36176 ** (d) if DELETEONCLOSE is set, then CREATE must also be set.
36177 */
36178 assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
36179 assert(isCreate==0 || isReadWrite);
36180 assert(isExclusive==0 || isCreate);
36181 assert(isDelete==0 || isCreate);
36182
36183 /* The main DB, main journal, WAL file and master journal are never
36184 ** automatically deleted. Nor are they ever temporary files. */
36185 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
36186 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
36187 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
36188 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
36189
36190 /* Assert that the upper layer has set one of the "file-type" flags. */
36191 assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
36192 || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
36193 || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
36194 || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
36195 );
36196
36197 assert( pFile!=0 );
36198 memset(pFile, 0, sizeof(winFile));
@@ -36203,12 +36566,12 @@
36203 sqlite3_log(SQLITE_ERROR,
36204 "sqlite3_temp_directory variable should be set for WinRT");
36205 }
36206 #endif
36207
36208 /* If the second argument to this function is NULL, generate a
36209 ** temporary file name to use
36210 */
36211 if( !zUtf8Name ){
36212 assert( isDelete && !isOpenJournal );
36213 rc = winGetTempname(pVfs, &zTmpname);
36214 if( rc!=SQLITE_OK ){
@@ -36244,12 +36607,12 @@
36244 dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
36245 }else{
36246 dwDesiredAccess = GENERIC_READ;
36247 }
36248
36249 /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is
36250 ** created. SQLite doesn't use it to indicate "exclusive access"
36251 ** as it is usually understood.
36252 */
36253 if( isExclusive ){
36254 /* Creates a new file, only if it does not already exist. */
36255 /* If the file exists, it fails. */
@@ -36334,11 +36697,11 @@
36334 pFile->lastErrno = lastErrno;
36335 winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name);
36336 sqlite3_free(zConverted);
36337 sqlite3_free(zTmpname);
36338 if( isReadWrite && !isExclusive ){
36339 return winOpen(pVfs, zName, id,
36340 ((flags|SQLITE_OPEN_READONLY) &
36341 ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
36342 pOutFlags);
36343 }else{
36344 return SQLITE_CANTOPEN_BKPT;
@@ -36543,18 +36906,18 @@
36543 if( osIsNT() ){
36544 int cnt = 0;
36545 WIN32_FILE_ATTRIBUTE_DATA sAttrData;
36546 memset(&sAttrData, 0, sizeof(sAttrData));
36547 while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
36548 GetFileExInfoStandard,
36549 &sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){}
36550 if( rc ){
36551 /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
36552 ** as if it does not exist.
36553 */
36554 if( flags==SQLITE_ACCESS_EXISTS
36555 && sAttrData.nFileSizeHigh==0
36556 && sAttrData.nFileSizeLow==0 ){
36557 attr = INVALID_FILE_ATTRIBUTES;
36558 }else{
36559 attr = sAttrData.dwFileAttributes;
36560 }
@@ -36649,11 +37012,11 @@
36649 sqlite3_vfs *pVfs, /* Pointer to vfs object */
36650 const char *zRelative, /* Possibly relative input path */
36651 int nFull, /* Size of output buffer in bytes */
36652 char *zFull /* Output buffer */
36653 ){
36654
36655 #if defined(__CYGWIN__)
36656 SimulateIOError( return SQLITE_ERROR );
36657 UNUSED_PARAMETER(nFull);
36658 assert( nFull>=pVfs->mxPathname );
36659 if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
@@ -36962,24 +37325,24 @@
36962 ** the current time and date as a Julian Day number times 86_400_000. In
36963 ** other words, write into *piNow the number of milliseconds since the Julian
36964 ** epoch of noon in Greenwich on November 24, 4714 B.C according to the
36965 ** proleptic Gregorian calendar.
36966 **
36967 ** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
36968 ** cannot be found.
36969 */
36970 static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
36971 /* FILETIME structure is a 64-bit value representing the number of
36972 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
36973 */
36974 FILETIME ft;
36975 static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000;
36976 #ifdef SQLITE_TEST
36977 static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
36978 #endif
36979 /* 2^32 - to avoid use of LL and warnings in gcc */
36980 static const sqlite3_int64 max32BitValue =
36981 (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 +
36982 (sqlite3_int64)294967296;
36983
36984 #if SQLITE_OS_WINCE
36985 SYSTEMTIME time;
@@ -36991,11 +37354,11 @@
36991 #else
36992 osGetSystemTimeAsFileTime( &ft );
36993 #endif
36994
36995 *piNow = winFiletimeEpoch +
36996 ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) +
36997 (sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000;
36998
36999 #ifdef SQLITE_TEST
37000 if( sqlite3_current_time ){
37001 *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
@@ -37110,11 +37473,11 @@
37110 };
37111 #endif
37112
37113 /* Double-check that the aSyscall[] array has been constructed
37114 ** correctly. See ticket [bb3a86e890c8e96ab] */
37115 assert( ArraySize(aSyscall)==76 );
37116
37117 /* get memory map allocation granularity */
37118 memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
37119 #if SQLITE_OS_WINRT
37120 osGetNativeSystemInfo(&winSysInfo);
@@ -37128,14 +37491,14 @@
37128
37129 #if defined(SQLITE_WIN32_HAS_WIDE)
37130 sqlite3_vfs_register(&winLongPathVfs, 0);
37131 #endif
37132
37133 return SQLITE_OK;
37134 }
37135
37136 SQLITE_API int sqlite3_os_end(void){
37137 #if SQLITE_OS_WINRT
37138 if( sleepObj!=NULL ){
37139 osCloseHandle(sleepObj);
37140 sleepObj = NULL;
37141 }
@@ -51332,11 +51695,11 @@
51332 /* If the client is reading or writing an index and the schema is
51333 ** not loaded, then it is too difficult to actually check to see if
51334 ** the correct locks are held. So do not bother - just return true.
51335 ** This case does not come up very often anyhow.
51336 */
51337 if( isIndex && (!pSchema || (pSchema->flags&DB_SchemaLoaded)==0) ){
51338 return 1;
51339 }
51340
51341 /* Figure out the root-page that the lock should be held on. For table
51342 ** b-trees, this is just the root page of the b-tree being read or
@@ -52802,11 +53165,11 @@
52802 return pBt->nPage;
52803 }
52804 SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree *p){
52805 assert( sqlite3BtreeHoldsMutex(p) );
52806 assert( ((p->pBt->nPage)&0x8000000)==0 );
52807 return (int)btreePagecount(p->pBt);
52808 }
52809
52810 /*
52811 ** Get a page from the pager and initialize it. This routine is just a
52812 ** convenience wrapper around separate calls to btreeGetPage() and
@@ -61928,22 +62291,39 @@
61928 pB->zSql = zTmp;
61929 pB->isPrepareV2 = pA->isPrepareV2;
61930 }
61931
61932 /*
61933 ** Resize the Vdbe.aOp array so that it is at least one op larger than
61934 ** it was.
 
61935 **
61936 ** If an out-of-memory error occurs while resizing the array, return
61937 ** SQLITE_NOMEM. In this case Vdbe.aOp and Vdbe.nOpAlloc remain
61938 ** unchanged (this is so that any opcodes already allocated can be
61939 ** correctly deallocated along with the rest of the Vdbe).
61940 */
61941 static int growOpArray(Vdbe *v){
61942 VdbeOp *pNew;
61943 Parse *p = v->pParse;
 
 
 
 
 
 
 
 
 
 
 
61944 int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op)));
 
 
 
 
 
61945 pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
61946 if( pNew ){
61947 p->nOpAlloc = sqlite3DbMallocSize(p->db, pNew)/sizeof(Op);
61948 v->aOp = pNew;
61949 }
@@ -61983,11 +62363,11 @@
61983
61984 i = p->nOp;
61985 assert( p->magic==VDBE_MAGIC_INIT );
61986 assert( op>0 && op<0xff );
61987 if( p->pParse->nOpAlloc<=i ){
61988 if( growOpArray(p) ){
61989 return 1;
61990 }
61991 }
61992 p->nOp++;
61993 pOp = &p->aOp[i];
@@ -62343,11 +62723,11 @@
62343 }
62344 sqlite3DbFree(p->db, pParse->aLabel);
62345 pParse->aLabel = 0;
62346 pParse->nLabel = 0;
62347 *pMaxFuncArgs = nMaxArgs;
62348 assert( p->bIsReader!=0 || p->btreeMask==0 );
62349 }
62350
62351 /*
62352 ** Return the address of the next instruction to be inserted.
62353 */
@@ -62370,11 +62750,11 @@
62370 SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){
62371 VdbeOp *aOp = p->aOp;
62372 assert( aOp && !p->db->mallocFailed );
62373
62374 /* Check that sqlite3VdbeUsesBtree() was not called on this VM */
62375 assert( p->btreeMask==0 );
62376
62377 resolveP2Values(p, pnMaxArg);
62378 *pnOp = p->nOp;
62379 p->aOp = 0;
62380 return aOp;
@@ -62385,11 +62765,11 @@
62385 ** address of the first operation added.
62386 */
62387 SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp, int iLineno){
62388 int addr;
62389 assert( p->magic==VDBE_MAGIC_INIT );
62390 if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p) ){
62391 return 0;
62392 }
62393 addr = p->nOp;
62394 if( ALWAYS(nOp>0) ){
62395 int i;
@@ -62570,11 +62950,11 @@
62570
62571 /*
62572 ** Change the opcode at addr into OP_Noop
62573 */
62574 SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
62575 if( p->aOp ){
62576 VdbeOp *pOp = &p->aOp[addr];
62577 sqlite3 *db = p->db;
62578 freeP4(db, pOp->p4type, pOp->p4.p);
62579 memset(pOp, 0, sizeof(pOp[0]));
62580 pOp->opcode = OP_Noop;
@@ -62955,13 +63335,13 @@
62955 ** p->btreeMask of databases that will require a lock.
62956 */
62957 SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe *p, int i){
62958 assert( i>=0 && i<p->db->nDb && i<(int)sizeof(yDbMask)*8 );
62959 assert( i<(int)sizeof(p->btreeMask)*8 );
62960 p->btreeMask |= ((yDbMask)1)<<i;
62961 if( i!=1 && sqlite3BtreeSharable(p->db->aDb[i].pBt) ){
62962 p->lockMask |= ((yDbMask)1)<<i;
62963 }
62964 }
62965
62966 #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
62967 /*
@@ -62985,20 +63365,19 @@
62985 ** this routine is N*N. But as N is rarely more than 1, this should not
62986 ** be a problem.
62987 */
62988 SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe *p){
62989 int i;
62990 yDbMask mask;
62991 sqlite3 *db;
62992 Db *aDb;
62993 int nDb;
62994 if( p->lockMask==0 ) return; /* The common case */
62995 db = p->db;
62996 aDb = db->aDb;
62997 nDb = db->nDb;
62998 for(i=0, mask=1; i<nDb; i++, mask += mask){
62999 if( i!=1 && (mask & p->lockMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){
63000 sqlite3BtreeEnter(aDb[i].pBt);
63001 }
63002 }
63003 }
63004 #endif
@@ -63007,20 +63386,19 @@
63007 /*
63008 ** Unlock all of the btrees previously locked by a call to sqlite3VdbeEnter().
63009 */
63010 SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe *p){
63011 int i;
63012 yDbMask mask;
63013 sqlite3 *db;
63014 Db *aDb;
63015 int nDb;
63016 if( p->lockMask==0 ) return; /* The common case */
63017 db = p->db;
63018 aDb = db->aDb;
63019 nDb = db->nDb;
63020 for(i=0, mask=1; i<nDb; i++, mask += mask){
63021 if( i!=1 && (mask & p->lockMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){
63022 sqlite3BtreeLeave(aDb[i].pBt);
63023 }
63024 }
63025 }
63026 #endif
@@ -63987,11 +64365,11 @@
63987 int cnt = 0;
63988 int nWrite = 0;
63989 int nRead = 0;
63990 p = db->pVdbe;
63991 while( p ){
63992 if( p->magic==VDBE_MAGIC_RUN && p->pc>=0 ){
63993 cnt++;
63994 if( p->readOnly==0 ) nWrite++;
63995 if( p->bIsReader ) nRead++;
63996 }
63997 p = p->pNext;
@@ -64147,11 +64525,10 @@
64147 /* Lock all btrees used by the statement */
64148 sqlite3VdbeEnter(p);
64149
64150 /* Check for one of the special errors */
64151 mrc = p->rc & 0xff;
64152 assert( p->rc!=SQLITE_IOERR_BLOCKED ); /* This error no longer exists */
64153 isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR
64154 || mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL;
64155 if( isSpecialError ){
64156 /* If the query was read-only and the error code is SQLITE_INTERRUPT,
64157 ** no rollback is necessary. Otherwise, at least a savepoint
@@ -64632,11 +65009,11 @@
64632 /*
64633 ** Return the serial-type for the value stored in pMem.
64634 */
64635 SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
64636 int flags = pMem->flags;
64637 int n;
64638
64639 if( flags&MEM_Null ){
64640 return 0;
64641 }
64642 if( flags&MEM_Int ){
@@ -64662,15 +65039,15 @@
64662 }
64663 if( flags&MEM_Real ){
64664 return 7;
64665 }
64666 assert( pMem->db->mallocFailed || flags&(MEM_Str|MEM_Blob) );
64667 n = pMem->n;
 
64668 if( flags & MEM_Zero ){
64669 n += pMem->u.nZero;
64670 }
64671 assert( n>=0 );
64672 return ((n*2) + 12 + ((flags&MEM_Str)!=0));
64673 }
64674
64675 /*
64676 ** Return the length of the data corresponding to the supplied serial-type.
@@ -67184,11 +67561,11 @@
67184 /*
67185 ** Return true if the prepared statement is in need of being reset.
67186 */
67187 SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
67188 Vdbe *v = (Vdbe*)pStmt;
67189 return v!=0 && v->pc>0 && v->magic==VDBE_MAGIC_RUN;
67190 }
67191
67192 /*
67193 ** Return a pointer to the next prepared statement after pStmt associated
67194 ** with database connection pDb. If pStmt is NULL, return the first
@@ -67634,10 +68011,16 @@
67634 **
67635 ** M is an integer, 2 or 3, that indices how many different ways the
67636 ** branch can go. It is usually 2. "I" is the direction the branch
67637 ** goes. 0 means falls through. 1 means branch is taken. 2 means the
67638 ** second alternative branch is taken.
 
 
 
 
 
 
67639 */
67640 #if !defined(SQLITE_VDBE_COVERAGE)
67641 # define VdbeBranchTaken(I,M)
67642 #else
67643 # define VdbeBranchTaken(I,M) vdbeTakeBranch(pOp->iSrcLine,I,M)
@@ -67742,25 +68125,25 @@
67742 ** do so without loss of information. In other words, if the string
67743 ** looks like a number, convert it into a number. If it does not
67744 ** look like a number, leave it alone.
67745 */
67746 static void applyNumericAffinity(Mem *pRec){
67747 if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){
67748 double rValue;
67749 i64 iValue;
67750 u8 enc = pRec->enc;
67751 if( (pRec->flags&MEM_Str)==0 ) return;
67752 if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return;
67753 if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){
67754 pRec->u.i = iValue;
67755 pRec->flags |= MEM_Int;
67756 }else{
67757 pRec->r = rValue;
67758 pRec->flags |= MEM_Real;
67759 }
67760 }
67761 }
67762
67763 /*
67764 ** Processing is determine by the affinity parameter:
67765 **
67766 ** SQLITE_AFF_INTEGER:
@@ -67793,11 +68176,11 @@
67793 }
67794 pRec->flags &= ~(MEM_Real|MEM_Int);
67795 }else if( affinity!=SQLITE_AFF_NONE ){
67796 assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL
67797 || affinity==SQLITE_AFF_NUMERIC );
67798 applyNumericAffinity(pRec);
67799 if( pRec->flags & MEM_Real ){
67800 sqlite3VdbeIntegerAffinity(pRec);
67801 }
67802 }
67803 }
@@ -68374,16 +68757,18 @@
68374 break;
68375 }
68376
68377 /* Opcode: InitCoroutine P1 P2 P3 * *
68378 **
68379 ** Set up register P1 so that it will OP_Yield to the co-routine
68380 ** located at address P3.
68381 **
68382 ** If P2!=0 then the co-routine implementation immediately follows
68383 ** this opcode. So jump over the co-routine implementation to
68384 ** address P2.
 
 
68385 */
68386 case OP_InitCoroutine: { /* jump */
68387 assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
68388 assert( pOp->p2>=0 && pOp->p2<p->nOp );
68389 assert( pOp->p3>=0 && pOp->p3<p->nOp );
@@ -68395,13 +68780,15 @@
68395 break;
68396 }
68397
68398 /* Opcode: EndCoroutine P1 * * * *
68399 **
68400 ** The instruction at the address in register P1 is an OP_Yield.
68401 ** Jump to the P2 parameter of that OP_Yield.
68402 ** After the jump, register P1 becomes undefined.
 
 
68403 */
68404 case OP_EndCoroutine: { /* in1 */
68405 VdbeOp *pCaller;
68406 pIn1 = &aMem[pOp->p1];
68407 assert( pIn1->flags==MEM_Int );
@@ -68414,15 +68801,20 @@
68414 break;
68415 }
68416
68417 /* Opcode: Yield P1 P2 * * *
68418 **
68419 ** Swap the program counter with the value in register P1.
 
68420 **
68421 ** If the co-routine ends with OP_Yield or OP_Return then continue
68422 ** to the next instruction. But if the co-routine ends with
68423 ** OP_EndCoroutine, jump immediately to P2.
 
 
 
 
68424 */
68425 case OP_Yield: { /* in1, jump */
68426 int pcDest;
68427 pIn1 = &aMem[pOp->p1];
68428 assert( VdbeMemDynamic(pIn1)==0 );
@@ -68581,11 +68973,11 @@
68581
68582 /* Opcode: String8 * P2 * P4 *
68583 ** Synopsis: r[P2]='P4'
68584 **
68585 ** P4 points to a nul terminated UTF-8 string. This opcode is transformed
68586 ** into an OP_String before it is executed for the first time. During
68587 ** this transformation, the length of string P4 is computed and stored
68588 ** as the P1 parameter.
68589 */
68590 case OP_String8: { /* same as TK_STRING, out2-prerelease */
68591 assert( pOp->p4.z!=0 );
@@ -69803,14 +70195,18 @@
69803 break;
69804 }
69805
69806 /* Opcode: Once P1 P2 * * *
69807 **
69808 ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise,
69809 ** set the flag and fall through to the next instruction. In other words,
69810 ** this opcode causes all following opcodes up through P2 (but not including
69811 ** P2) to run just once and to be skipped on subsequent times through the loop.
 
 
 
 
69812 */
69813 case OP_Once: { /* jump */
69814 assert( pOp->p1<p->nOnceFlag );
69815 VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2);
69816 if( p->aOnceFlag[pOp->p1] ){
@@ -69823,17 +70219,17 @@
69823
69824 /* Opcode: If P1 P2 P3 * *
69825 **
69826 ** Jump to P2 if the value in register P1 is true. The value
69827 ** is considered true if it is numeric and non-zero. If the value
69828 ** in P1 is NULL then take the jump if P3 is non-zero.
69829 */
69830 /* Opcode: IfNot P1 P2 P3 * *
69831 **
69832 ** Jump to P2 if the value in register P1 is False. The value
69833 ** is considered false if it has a numeric value of zero. If the value
69834 ** in P1 is NULL then take the jump if P3 is zero.
69835 */
69836 case OP_If: /* jump, in1 */
69837 case OP_IfNot: { /* jump, in1 */
69838 int c;
69839 pIn1 = &aMem[pOp->p1];
@@ -70641,11 +71037,11 @@
70641 int iGen;
70642
70643 assert( p->bIsReader );
70644 assert( p->readOnly==0 || pOp->p2==0 );
70645 assert( pOp->p1>=0 && pOp->p1<db->nDb );
70646 assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
70647 if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
70648 rc = SQLITE_READONLY;
70649 goto abort_due_to_error;
70650 }
70651 pBt = db->aDb[pOp->p1].pBt;
@@ -70736,11 +71132,11 @@
70736 iDb = pOp->p1;
70737 iCookie = pOp->p3;
70738 assert( pOp->p3<SQLITE_N_BTREE_META );
70739 assert( iDb>=0 && iDb<db->nDb );
70740 assert( db->aDb[iDb].pBt!=0 );
70741 assert( (p->btreeMask & (((yDbMask)1)<<iDb))!=0 );
70742
70743 sqlite3BtreeGetMeta(db->aDb[iDb].pBt, iCookie, (u32 *)&iMeta);
70744 pOut->u.i = iMeta;
70745 break;
70746 }
@@ -70757,11 +71153,11 @@
70757 */
70758 case OP_SetCookie: { /* in3 */
70759 Db *pDb;
70760 assert( pOp->p2<SQLITE_N_BTREE_META );
70761 assert( pOp->p1>=0 && pOp->p1<db->nDb );
70762 assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
70763 assert( p->readOnly==0 );
70764 pDb = &db->aDb[pOp->p1];
70765 assert( pDb->pBt!=0 );
70766 assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
70767 pIn3 = &aMem[pOp->p3];
@@ -70812,11 +71208,25 @@
70812 ** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
70813 ** structure, then said structure defines the content and collating
70814 ** sequence of the index being opened. Otherwise, if P4 is an integer
70815 ** value, it is set to the number of columns in the table.
70816 **
70817 ** See also OpenWrite.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70818 */
70819 /* Opcode: OpenWrite P1 P2 P3 P4 P5
70820 ** Synopsis: root=P2 iDb=P3
70821 **
70822 ** Open a read/write cursor named P1 on the table or index whose root
@@ -70834,10 +71244,23 @@
70834 ** in read/write mode. For a given table, there can be one or more read-only
70835 ** cursors or a single read/write cursor but not both.
70836 **
70837 ** See also OpenRead.
70838 */
 
 
 
 
 
 
 
 
 
 
 
 
 
70839 case OP_OpenRead:
70840 case OP_OpenWrite: {
70841 int nField;
70842 KeyInfo *pKeyInfo;
70843 int p2;
@@ -70848,11 +71271,12 @@
70848 Db *pDb;
70849
70850 assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 );
70851 assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 );
70852 assert( p->bIsReader );
70853 assert( pOp->opcode==OP_OpenRead || p->readOnly==0 );
 
70854
70855 if( p->expired ){
70856 rc = SQLITE_ABORT;
70857 break;
70858 }
@@ -70860,11 +71284,11 @@
70860 nField = 0;
70861 pKeyInfo = 0;
70862 p2 = pOp->p2;
70863 iDb = pOp->p3;
70864 assert( iDb>=0 && iDb<db->nDb );
70865 assert( (p->btreeMask & (((yDbMask)1)<<iDb))!=0 );
70866 pDb = &db->aDb[iDb];
70867 pX = pDb->pBt;
70868 assert( pX!=0 );
70869 if( pOp->opcode==OP_OpenWrite ){
70870 wrFlag = 1;
@@ -70905,10 +71329,11 @@
70905 testcase( nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */
70906 pCur = allocateCursor(p, pOp->p1, nField, iDb, 1);
70907 if( pCur==0 ) goto no_mem;
70908 pCur->nullRow = 1;
70909 pCur->isOrdered = 1;
 
70910 rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor);
70911 pCur->pKeyInfo = pKeyInfo;
70912 assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
70913 sqlite3BtreeCursorHints(pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
70914
@@ -71059,11 +71484,11 @@
71059 sqlite3VdbeFreeCursor(p, p->apCsr[pOp->p1]);
71060 p->apCsr[pOp->p1] = 0;
71061 break;
71062 }
71063
71064 /* Opcode: SeekGe P1 P2 P3 P4 *
71065 ** Synopsis: key=r[P3@P4]
71066 **
71067 ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
71068 ** use the value in register P3 as the key. If cursor P1 refers
71069 ** to an SQL index, then P3 is the first in an array of P4 registers
@@ -71070,14 +71495,18 @@
71070 ** that are used as an unpacked index key.
71071 **
71072 ** Reposition cursor P1 so that it points to the smallest entry that
71073 ** is greater than or equal to the key value. If there are no records
71074 ** greater than or equal to the key and P2 is not zero, then jump to P2.
 
 
 
 
71075 **
71076 ** See also: Found, NotFound, SeekLt, SeekGt, SeekLe
71077 */
71078 /* Opcode: SeekGt P1 P2 P3 P4 *
71079 ** Synopsis: key=r[P3@P4]
71080 **
71081 ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
71082 ** use the value in register P3 as a key. If cursor P1 refers
71083 ** to an SQL index, then P3 is the first in an array of P4 registers
@@ -71084,14 +71513,18 @@
71084 ** that are used as an unpacked index key.
71085 **
71086 ** Reposition cursor P1 so that it points to the smallest entry that
71087 ** is greater than the key value. If there are no records greater than
71088 ** the key and P2 is not zero, then jump to P2.
 
 
 
 
71089 **
71090 ** See also: Found, NotFound, SeekLt, SeekGe, SeekLe
71091 */
71092 /* Opcode: SeekLt P1 P2 P3 P4 *
71093 ** Synopsis: key=r[P3@P4]
71094 **
71095 ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
71096 ** use the value in register P3 as a key. If cursor P1 refers
71097 ** to an SQL index, then P3 is the first in an array of P4 registers
@@ -71098,14 +71531,18 @@
71098 ** that are used as an unpacked index key.
71099 **
71100 ** Reposition cursor P1 so that it points to the largest entry that
71101 ** is less than the key value. If there are no records less than
71102 ** the key and P2 is not zero, then jump to P2.
 
 
 
 
71103 **
71104 ** See also: Found, NotFound, SeekGt, SeekGe, SeekLe
71105 */
71106 /* Opcode: SeekLe P1 P2 P3 P4 *
71107 ** Synopsis: key=r[P3@P4]
71108 **
71109 ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
71110 ** use the value in register P3 as a key. If cursor P1 refers
71111 ** to an SQL index, then P3 is the first in an array of P4 registers
@@ -71112,10 +71549,14 @@
71112 ** that are used as an unpacked index key.
71113 **
71114 ** Reposition cursor P1 so that it points to the largest entry that
71115 ** is less than or equal to the key value. If there are no records
71116 ** less than or equal to the key and P2 is not zero, then jump to P2.
 
 
 
 
71117 **
71118 ** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
71119 */
71120 case OP_SeekLT: /* jump, in3 */
71121 case OP_SeekLE: /* jump, in3 */
@@ -71138,16 +71579,19 @@
71138 assert( OP_SeekGT == OP_SeekLT+3 );
71139 assert( pC->isOrdered );
71140 assert( pC->pCursor!=0 );
71141 oc = pOp->opcode;
71142 pC->nullRow = 0;
 
 
 
71143 if( pC->isTable ){
71144 /* The input value in P3 might be of any type: integer, real, string,
71145 ** blob, or NULL. But it needs to be an integer before we can do
71146 ** the seek, so covert it. */
71147 pIn3 = &aMem[pOp->p3];
71148 applyNumericAffinity(pIn3);
71149 iKey = sqlite3VdbeIntValue(pIn3);
71150 pC->rowidIsValid = 0;
71151
71152 /* If the P3 value could not be converted into an integer without
71153 ** loss of information, then special processing is required... */
@@ -71292,10 +71736,14 @@
71292 ** record.
71293 **
71294 ** Cursor P1 is on an index btree. If the record identified by P3 and P4
71295 ** is a prefix of any entry in P1 then a jump is made to P2 and
71296 ** P1 is left pointing at the matching entry.
 
 
 
 
71297 **
71298 ** See also: NotFound, NoConflict, NotExists. SeekGe
71299 */
71300 /* Opcode: NotFound P1 P2 P3 P4 *
71301 ** Synopsis: key=r[P3@P4]
@@ -71307,10 +71755,14 @@
71307 ** Cursor P1 is on an index btree. If the record identified by P3 and P4
71308 ** is not the prefix of any entry in P1 then a jump is made to P2. If P1
71309 ** does contain an entry whose prefix matches the P3/P4 record then control
71310 ** falls through to the next instruction and P1 is left pointing at the
71311 ** matching entry.
 
 
 
 
71312 **
71313 ** See also: Found, NotExists, NoConflict
71314 */
71315 /* Opcode: NoConflict P1 P2 P3 P4 *
71316 ** Synopsis: key=r[P3@P4]
@@ -71326,10 +71778,14 @@
71326 ** immediately to P2. If there is a match, fall through and leave the P1
71327 ** cursor pointing to the matching row.
71328 **
71329 ** This opcode is similar to OP_NotFound with the exceptions that the
71330 ** branch is always taken if any part of the search key input is NULL.
 
 
 
 
71331 **
71332 ** See also: NotFound, Found, NotExists
71333 */
71334 case OP_NoConflict: /* jump, in3 */
71335 case OP_NotFound: /* jump, in3 */
@@ -71349,10 +71805,13 @@
71349
71350 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
71351 assert( pOp->p4type==P4_INT32 );
71352 pC = p->apCsr[pOp->p1];
71353 assert( pC!=0 );
 
 
 
71354 pIn3 = &aMem[pOp->p3];
71355 assert( pC->pCursor!=0 );
71356 assert( pC->isTable==0 );
71357 pFree = 0; /* Not needed. Only used to suppress a compiler warning. */
71358 if( pOp->p4.i>0 ){
@@ -71419,10 +71878,14 @@
71419 ** with rowid P3 then leave the cursor pointing at that record and fall
71420 ** through to the next instruction.
71421 **
71422 ** The OP_NotFound opcode performs the same operation on index btrees
71423 ** (with arbitrary multi-value keys).
 
 
 
 
71424 **
71425 ** See also: Found, NotFound, NoConflict
71426 */
71427 case OP_NotExists: { /* jump, in3 */
71428 VdbeCursor *pC;
@@ -71433,10 +71896,13 @@
71433 pIn3 = &aMem[pOp->p3];
71434 assert( pIn3->flags & MEM_Int );
71435 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
71436 pC = p->apCsr[pOp->p1];
71437 assert( pC!=0 );
 
 
 
71438 assert( pC->isTable );
71439 assert( pC->pseudoTableReg==0 );
71440 pCrsr = pC->pCursor;
71441 assert( pCrsr!=0 );
71442 res = 0;
@@ -71735,11 +72201,11 @@
71735 ** Delete the record at which the P1 cursor is currently pointing.
71736 **
71737 ** The cursor will be left pointing at either the next or the previous
71738 ** record in the table. If it is left pointing at the next record, then
71739 ** the next Next instruction will be a no-op. Hence it is OK to delete
71740 ** a record from within an Next loop.
71741 **
71742 ** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is
71743 ** incremented (otherwise not).
71744 **
71745 ** P1 must not be pseudo-table. It has to be a real table with
@@ -71795,16 +72261,16 @@
71795 p->nChange = 0;
71796 break;
71797 }
71798
71799 /* Opcode: SorterCompare P1 P2 P3 P4
71800 ** Synopsis: if key(P1)!=rtrim(r[P3],P4) goto P2
71801 **
71802 ** P1 is a sorter cursor. This instruction compares a prefix of the
71803 ** the record blob in register P3 against a prefix of the entry that
71804 ** the sorter cursor currently points to. The final P4 fields of both
71805 ** the P3 and sorter record are ignored.
71806 **
71807 ** If either P3 or the sorter contains a NULL in one of their significant
71808 ** fields (not counting the P4 fields at the end which are ignored) then
71809 ** the comparison is assumed to be equal.
71810 **
@@ -71812,18 +72278,18 @@
71812 ** each other. Jump to P2 if they are different.
71813 */
71814 case OP_SorterCompare: {
71815 VdbeCursor *pC;
71816 int res;
71817 int nIgnore;
71818
71819 pC = p->apCsr[pOp->p1];
71820 assert( isSorter(pC) );
71821 assert( pOp->p4type==P4_INT32 );
71822 pIn3 = &aMem[pOp->p3];
71823 nIgnore = pOp->p4.i;
71824 rc = sqlite3VdbeSorterCompare(pC, pIn3, nIgnore, &res);
71825 VdbeBranchTaken(res!=0,2);
71826 if( res ){
71827 pc = pOp->p2-1;
71828 }
71829 break;
@@ -71999,15 +72465,19 @@
71999 break;
72000 }
72001
72002 /* Opcode: Last P1 P2 * * *
72003 **
72004 ** The next use of the Rowid or Column or Next instruction for P1
72005 ** will refer to the last entry in the database table or index.
72006 ** If the table or index is empty and P2>0, then jump immediately to P2.
72007 ** If P2 is 0 or if the table or index is not empty, fall through
72008 ** to the following instruction.
 
 
 
 
72009 */
72010 case OP_Last: { /* jump */
72011 VdbeCursor *pC;
72012 BtCursor *pCrsr;
72013 int res;
@@ -72021,10 +72491,13 @@
72021 rc = sqlite3BtreeLast(pCrsr, &res);
72022 pC->nullRow = (u8)res;
72023 pC->deferredMoveto = 0;
72024 pC->rowidIsValid = 0;
72025 pC->cacheStatus = CACHE_STALE;
 
 
 
72026 if( pOp->p2>0 ){
72027 VdbeBranchTaken(res!=0,2);
72028 if( res ) pc = pOp->p2 - 1;
72029 }
72030 break;
@@ -72057,10 +72530,14 @@
72057 ** The next use of the Rowid or Column or Next instruction for P1
72058 ** will refer to the first entry in the database table or index.
72059 ** If the table or index is empty and P2>0, then jump immediately to P2.
72060 ** If P2 is 0 or if the table or index is not empty, fall through
72061 ** to the following instruction.
 
 
 
 
72062 */
72063 case OP_Rewind: { /* jump */
72064 VdbeCursor *pC;
72065 BtCursor *pCrsr;
72066 int res;
@@ -72068,10 +72545,13 @@
72068 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
72069 pC = p->apCsr[pOp->p1];
72070 assert( pC!=0 );
72071 assert( isSorter(pC)==(pOp->opcode==OP_SorterSort) );
72072 res = 1;
 
 
 
72073 if( isSorter(pC) ){
72074 rc = sqlite3VdbeSorterRewind(db, pC, &res);
72075 }else{
72076 pCrsr = pC->pCursor;
72077 assert( pCrsr );
@@ -72093,10 +72573,14 @@
72093 **
72094 ** Advance cursor P1 so that it points to the next key/data pair in its
72095 ** table or index. If there are no more key/value pairs then fall through
72096 ** to the following instruction. But if the cursor advance was successful,
72097 ** jump immediately to P2.
 
 
 
 
72098 **
72099 ** The P1 cursor must be for a real table, not a pseudo-table. P1 must have
72100 ** been opened prior to this opcode or the program will segfault.
72101 **
72102 ** The P3 value is a hint to the btree implementation. If P3==1, that
@@ -72112,20 +72596,25 @@
72112 **
72113 ** See also: Prev, NextIfOpen
72114 */
72115 /* Opcode: NextIfOpen P1 P2 P3 P4 P5
72116 **
72117 ** This opcode works just like OP_Next except that if cursor P1 is not
72118 ** open it behaves a no-op.
72119 */
72120 /* Opcode: Prev P1 P2 P3 P4 P5
72121 **
72122 ** Back up cursor P1 so that it points to the previous key/data pair in its
72123 ** table or index. If there is no previous key/value pairs then fall through
72124 ** to the following instruction. But if the cursor backup was successful,
72125 ** jump immediately to P2.
72126 **
 
 
 
 
 
72127 ** The P1 cursor must be for a real table, not a pseudo-table. If P1 is
72128 ** not open then the behavior is undefined.
72129 **
72130 ** The P3 value is a hint to the btree implementation. If P3==1, that
72131 ** means P1 is an SQL index and that this instruction could have been
@@ -72138,11 +72627,11 @@
72138 ** If P5 is positive and the jump is taken, then event counter
72139 ** number P5-1 in the prepared statement is incremented.
72140 */
72141 /* Opcode: PrevIfOpen P1 P2 P3 P4 P5
72142 **
72143 ** This opcode works just like OP_Prev except that if cursor P1 is not
72144 ** open it behaves a no-op.
72145 */
72146 case OP_SorterNext: { /* jump */
72147 VdbeCursor *pC;
72148 int res;
@@ -72169,10 +72658,20 @@
72169 testcase( res==1 );
72170 assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
72171 assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
72172 assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext );
72173 assert( pOp->opcode!=OP_PrevIfOpen || pOp->p4.xAdvance==sqlite3BtreePrevious);
 
 
 
 
 
 
 
 
 
 
72174 rc = pOp->p4.xAdvance(pC->pCursor, &res);
72175 next_tail:
72176 pC->cacheStatus = CACHE_STALE;
72177 VdbeBranchTaken(res==0,2);
72178 if( res==0 ){
@@ -72451,11 +72950,11 @@
72451 rc = SQLITE_LOCKED;
72452 p->errorAction = OE_Abort;
72453 }else{
72454 iDb = pOp->p3;
72455 assert( iCnt==1 );
72456 assert( (p->btreeMask & (((yDbMask)1)<<iDb))!=0 );
72457 iMoved = 0; /* Not needed. Only to silence a warning. */
72458 rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved);
72459 pOut->flags = MEM_Int;
72460 pOut->u.i = iMoved;
72461 #ifndef SQLITE_OMIT_AUTOVACUUM
@@ -72491,11 +72990,11 @@
72491 case OP_Clear: {
72492 int nChange;
72493
72494 nChange = 0;
72495 assert( p->readOnly==0 );
72496 assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 );
72497 rc = sqlite3BtreeClearTable(
72498 db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0)
72499 );
72500 if( pOp->p3 ){
72501 p->nChange += nChange;
@@ -72561,11 +73060,11 @@
72561 int flags;
72562 Db *pDb;
72563
72564 pgno = 0;
72565 assert( pOp->p1>=0 && pOp->p1<db->nDb );
72566 assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
72567 assert( p->readOnly==0 );
72568 pDb = &db->aDb[pOp->p1];
72569 assert( pDb->pBt!=0 );
72570 if( pOp->opcode==OP_CreateTable ){
72571 /* flags = BTREE_INTKEY; */
@@ -72649,11 +73148,12 @@
72649
72650 /* Opcode: DropTable P1 * * P4 *
72651 **
72652 ** Remove the internal (in-memory) data structures that describe
72653 ** the table named P4 in database P1. This is called after a table
72654 ** is dropped in order to keep the internal representation of the
 
72655 ** schema consistent with what is on disk.
72656 */
72657 case OP_DropTable: {
72658 sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p4.z);
72659 break;
@@ -72661,11 +73161,12 @@
72661
72662 /* Opcode: DropIndex P1 * * P4 *
72663 **
72664 ** Remove the internal (in-memory) data structures that describe
72665 ** the index named P4 in database P1. This is called after an index
72666 ** is dropped in order to keep the internal representation of the
 
72667 ** schema consistent with what is on disk.
72668 */
72669 case OP_DropIndex: {
72670 sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p4.z);
72671 break;
@@ -72673,11 +73174,12 @@
72673
72674 /* Opcode: DropTrigger P1 * * P4 *
72675 **
72676 ** Remove the internal (in-memory) data structures that describe
72677 ** the trigger named P4 in database P1. This is called after a trigger
72678 ** is dropped in order to keep the internal representation of the
 
72679 ** schema consistent with what is on disk.
72680 */
72681 case OP_DropTrigger: {
72682 sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p4.z);
72683 break;
@@ -72726,11 +73228,11 @@
72726 for(j=0; j<nRoot; j++){
72727 aRoot[j] = (int)sqlite3VdbeIntValue(&pIn1[j]);
72728 }
72729 aRoot[j] = 0;
72730 assert( pOp->p5<db->nDb );
72731 assert( (p->btreeMask & (((yDbMask)1)<<pOp->p5))!=0 );
72732 z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot,
72733 (int)pnErr->u.i, &nErr);
72734 sqlite3DbFree(db, aRoot);
72735 pnErr->u.i -= nErr;
72736 sqlite3VdbeMemSetNull(pIn1);
@@ -73088,21 +73590,20 @@
73088 pc = pOp->p2 - 1;
73089 }
73090 break;
73091 }
73092
73093 /* Opcode: IfNeg P1 P2 * * *
73094 ** Synopsis: if r[P1]<0 goto P2
73095 **
73096 ** If the value of register P1 is less than zero, jump to P2.
73097 **
73098 ** It is illegal to use this instruction on a register that does
73099 ** not contain an integer. An assertion fault will result if you try.
73100 */
73101 case OP_IfNeg: { /* jump, in1 */
73102 pIn1 = &aMem[pOp->p1];
73103 assert( pIn1->flags&MEM_Int );
 
73104 VdbeBranchTaken(pIn1->u.i<0, 2);
73105 if( pIn1->u.i<0 ){
73106 pc = pOp->p2 - 1;
73107 }
73108 break;
@@ -73111,13 +73612,10 @@
73111 /* Opcode: IfZero P1 P2 P3 * *
73112 ** Synopsis: r[P1]+=P3, if r[P1]==0 goto P2
73113 **
73114 ** The register P1 must contain an integer. Add literal P3 to the
73115 ** value in register P1. If the result is exactly 0, jump to P2.
73116 **
73117 ** It is illegal to use this instruction on a register that does
73118 ** not contain an integer. An assertion fault will result if you try.
73119 */
73120 case OP_IfZero: { /* jump, in1 */
73121 pIn1 = &aMem[pOp->p1];
73122 assert( pIn1->flags&MEM_Int );
73123 pIn1->u.i += pOp->p3;
@@ -73386,11 +73884,11 @@
73386 */
73387 case OP_IncrVacuum: { /* jump */
73388 Btree *pBt;
73389
73390 assert( pOp->p1>=0 && pOp->p1<db->nDb );
73391 assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
73392 assert( p->readOnly==0 );
73393 pBt = db->aDb[pOp->p1].pBt;
73394 rc = sqlite3BtreeIncrVacuum(pBt);
73395 VdbeBranchTaken(rc==SQLITE_DONE,2);
73396 if( rc==SQLITE_DONE ){
@@ -73401,16 +73899,17 @@
73401 }
73402 #endif
73403
73404 /* Opcode: Expire P1 * * * *
73405 **
73406 ** Cause precompiled statements to become expired. An expired statement
73407 ** fails with an error code of SQLITE_SCHEMA if it is ever executed
73408 ** (via sqlite3_step()).
 
73409 **
73410 ** If P1 is 0, then all SQL statements become expired. If P1 is non-zero,
73411 ** then only the currently executing statement is affected.
73412 */
73413 case OP_Expire: {
73414 if( !pOp->p1 ){
73415 sqlite3ExpirePreparedStatements(db);
73416 }else{
@@ -73438,11 +73937,11 @@
73438 case OP_TableLock: {
73439 u8 isWriteLock = (u8)pOp->p3;
73440 if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){
73441 int p1 = pOp->p1;
73442 assert( p1>=0 && p1<db->nDb );
73443 assert( (p->btreeMask & (((yDbMask)1)<<p1))!=0 );
73444 assert( isWriteLock==0 || isWriteLock==1 );
73445 rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock);
73446 if( (rc&0xFF)==SQLITE_LOCKED ){
73447 const char *z = pOp->p4.z;
73448 sqlite3SetString(&p->zErrMsg, db, "database table is locked: %s", z);
@@ -73888,11 +74387,11 @@
73888 #ifdef SQLITE_USE_FCNTL_TRACE
73889 zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
73890 if( zTrace ){
73891 int i;
73892 for(i=0; i<db->nDb; i++){
73893 if( (MASKBIT(i) & p->btreeMask)==0 ) continue;
73894 sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace);
73895 }
73896 }
73897 #endif /* SQLITE_USE_FCNTL_TRACE */
73898 #ifdef SQLITE_DEBUG
@@ -74878,11 +75377,11 @@
74878 ** If pKey2 is passed a NULL pointer, then it is assumed that the pCsr->aSpace
74879 ** has been allocated and contains an unpacked record that is used as key2.
74880 */
74881 static void vdbeSorterCompare(
74882 const VdbeCursor *pCsr, /* Cursor object (for pKeyInfo) */
74883 int nIgnore, /* Ignore the last nIgnore fields */
74884 const void *pKey1, int nKey1, /* Left side of comparison */
74885 const void *pKey2, int nKey2, /* Right side of comparison */
74886 int *pRes /* OUT: Result of comparison */
74887 ){
74888 KeyInfo *pKeyInfo = pCsr->pKeyInfo;
@@ -74892,14 +75391,13 @@
74892
74893 if( pKey2 ){
74894 sqlite3VdbeRecordUnpack(pKeyInfo, nKey2, pKey2, r2);
74895 }
74896
74897 if( nIgnore ){
74898 r2->nField = pKeyInfo->nField - nIgnore;
74899 assert( r2->nField>0 );
74900 for(i=0; i<r2->nField; i++){
74901 if( r2->aMem[i].flags & MEM_Null ){
74902 *pRes = -1;
74903 return;
74904 }
74905 }
@@ -75577,18 +76075,18 @@
75577 ** key.
75578 */
75579 SQLITE_PRIVATE int sqlite3VdbeSorterCompare(
75580 const VdbeCursor *pCsr, /* Sorter cursor */
75581 Mem *pVal, /* Value to compare to current sorter key */
75582 int nIgnore, /* Ignore this many fields at the end */
75583 int *pRes /* OUT: Result of comparison */
75584 ){
75585 VdbeSorter *pSorter = pCsr->pSorter;
75586 void *pKey; int nKey; /* Sorter key to compare pVal with */
75587
75588 pKey = vdbeSorterRowkey(pSorter, &nKey);
75589 vdbeSorterCompare(pCsr, nIgnore, pVal->z, pVal->n, pKey, nKey, pRes);
75590 return SQLITE_OK;
75591 }
75592
75593 /************** End of vdbesort.c ********************************************/
75594 /************** Begin file journal.c *****************************************/
@@ -76616,11 +77114,11 @@
76616 }
76617 break;
76618 }
76619 }
76620 if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && HasRowid(pTab) ){
76621 /* IMP: R-24309-18625 */
76622 /* IMP: R-44911-55124 */
76623 iCol = -1;
76624 }
76625 if( iCol<pTab->nCol ){
76626 cnt++;
@@ -76972,11 +77470,15 @@
76972 }
76973 }else{
76974 /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is equivalent to
76975 ** likelihood(X, 0.0625).
76976 ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is short-hand for
76977 ** likelihood(X,0.0625). */
 
 
 
 
76978 /* TUNING: unlikely() probability is 0.0625. likely() is 0.9375 */
76979 pExpr->iTable = pDef->zName[0]=='u' ? 62 : 938;
76980 }
76981 }
76982 }
@@ -79085,10 +79587,13 @@
79085 case TK_INTEGER:
79086 case TK_STRING:
79087 case TK_FLOAT:
79088 case TK_BLOB:
79089 return 0;
 
 
 
79090 default:
79091 return 1;
79092 }
79093 }
79094
@@ -79192,83 +79697,124 @@
79192 SQLITE_PRIVATE int sqlite3CodeOnce(Parse *pParse){
79193 Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
79194 return sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++);
79195 }
79196
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79197 /*
79198 ** This function is used by the implementation of the IN (...) operator.
79199 ** The pX parameter is the expression on the RHS of the IN operator, which
79200 ** might be either a list of expressions or a subquery.
79201 **
79202 ** The job of this routine is to find or create a b-tree object that can
79203 ** be used either to test for membership in the RHS set or to iterate through
79204 ** all members of the RHS set, skipping duplicates.
79205 **
79206 ** A cursor is opened on the b-tree object that the RHS of the IN operator
79207 ** and pX->iTable is set to the index of that cursor.
79208 **
79209 ** The returned value of this function indicates the b-tree type, as follows:
79210 **
79211 ** IN_INDEX_ROWID - The cursor was opened on a database table.
79212 ** IN_INDEX_INDEX_ASC - The cursor was opened on an ascending index.
79213 ** IN_INDEX_INDEX_DESC - The cursor was opened on a descending index.
79214 ** IN_INDEX_EPH - The cursor was opened on a specially created and
79215 ** populated epheremal table.
 
 
79216 **
79217 ** An existing b-tree might be used if the RHS expression pX is a simple
79218 ** subquery such as:
79219 **
79220 ** SELECT <column> FROM <table>
79221 **
79222 ** If the RHS of the IN operator is a list or a more complex subquery, then
79223 ** an ephemeral table might need to be generated from the RHS and then
79224 ** pX->iTable made to point to the ephermeral table instead of an
79225 ** existing table.
79226 **
79227 ** If the prNotFound parameter is 0, then the b-tree will be used to iterate
79228 ** through the set members, skipping any duplicates. In this case an
79229 ** epheremal table must be used unless the selected <column> is guaranteed
 
 
 
 
 
 
 
79230 ** to be unique - either because it is an INTEGER PRIMARY KEY or it
79231 ** has a UNIQUE constraint or UNIQUE index.
79232 **
79233 ** If the prNotFound parameter is not 0, then the b-tree will be used
79234 ** for fast set membership tests. In this case an epheremal table must
79235 ** be used unless <column> is an INTEGER PRIMARY KEY or an index can
79236 ** be found with <column> as its left-most column.
 
 
 
 
 
 
 
79237 **
79238 ** When the b-tree is being used for membership tests, the calling function
79239 ** needs to know whether or not the structure contains an SQL NULL
79240 ** value in order to correctly evaluate expressions like "X IN (Y, Z)".
79241 ** If there is any chance that the (...) might contain a NULL value at
79242 ** runtime, then a register is allocated and the register number written
79243 ** to *prNotFound. If there is no chance that the (...) contains a
79244 ** NULL value, then *prNotFound is left unchanged.
79245 **
79246 ** If a register is allocated and its location stored in *prNotFound, then
79247 ** its initial value is NULL. If the (...) does not remain constant
79248 ** for the duration of the query (i.e. the SELECT within the (...)
79249 ** is a correlated subquery) then the value of the allocated register is
79250 ** reset to NULL each time the subquery is rerun. This allows the
79251 ** caller to use vdbe code equivalent to the following:
79252 **
79253 ** if( register==NULL ){
79254 ** has_null = <test if data structure contains null>
79255 ** register = 1
79256 ** }
79257 **
79258 ** in order to avoid running the <test if data structure contains null>
79259 ** test more often than is necessary.
79260 */
79261 #ifndef SQLITE_OMIT_SUBQUERY
79262 SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
79263 Select *p; /* SELECT to the right of IN operator */
79264 int eType = 0; /* Type of RHS table. IN_INDEX_* */
79265 int iTab = pParse->nTab++; /* Cursor of the RHS table */
79266 int mustBeUnique = (prNotFound==0); /* True if RHS must be unique */
79267 Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
79268
79269 assert( pX->op==TK_IN );
 
79270
79271 /* Check to see if an existing table or index can be used to
79272 ** satisfy the query. This is preferable to generating a new
79273 ** ephemeral table.
79274 */
@@ -79321,44 +79867,59 @@
79321 int affinity_ok = sqlite3IndexAffinityOk(pX, pTab->aCol[iCol].affinity);
79322
79323 for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){
79324 if( (pIdx->aiColumn[0]==iCol)
79325 && sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq
79326 && (!mustBeUnique || (pIdx->nKeyCol==1 && pIdx->onError!=OE_None))
79327 ){
79328 int iAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
79329 sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb);
79330 sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
79331 VdbeComment((v, "%s", pIdx->zName));
79332 assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 );
79333 eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0];
79334
79335 if( prNotFound && !pTab->aCol[iCol].notNull ){
79336 *prNotFound = ++pParse->nMem;
79337 sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound);
79338 }
79339 sqlite3VdbeJumpHere(v, iAddr);
79340 }
79341 }
79342 }
79343 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79344
79345 if( eType==0 ){
79346 /* Could not found an existing table or index to use as the RHS b-tree.
79347 ** We will have to generate an ephemeral table to do the job.
79348 */
79349 u32 savedNQueryLoop = pParse->nQueryLoop;
79350 int rMayHaveNull = 0;
79351 eType = IN_INDEX_EPH;
79352 if( prNotFound ){
79353 *prNotFound = rMayHaveNull = ++pParse->nMem;
79354 sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound);
79355 }else{
79356 pParse->nQueryLoop = 0;
79357 if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){
79358 eType = IN_INDEX_ROWID;
79359 }
 
 
79360 }
79361 sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID);
79362 pParse->nQueryLoop = savedNQueryLoop;
79363 }else{
79364 pX->iTable = iTab;
@@ -79385,31 +79946,25 @@
79385 ** intkey B-Tree to store the set of IN(...) values instead of the usual
79386 ** (slower) variable length keys B-Tree.
79387 **
79388 ** If rMayHaveNull is non-zero, that means that the operation is an IN
79389 ** (not a SELECT or EXISTS) and that the RHS might contains NULLs.
79390 ** Furthermore, the IN is in a WHERE clause and that we really want
79391 ** to iterate over the RHS of the IN operator in order to quickly locate
79392 ** all corresponding LHS elements. All this routine does is initialize
79393 ** the register given by rMayHaveNull to NULL. Calling routines will take
79394 ** care of changing this register value to non-NULL if the RHS is NULL-free.
79395 **
79396 ** If rMayHaveNull is zero, that means that the subquery is being used
79397 ** for membership testing only. There is no need to initialize any
79398 ** registers to indicate the presence or absence of NULLs on the RHS.
79399 **
79400 ** For a SELECT or EXISTS operator, return the register that holds the
79401 ** result. For IN operators or if an error occurs, the return value is 0.
79402 */
79403 #ifndef SQLITE_OMIT_SUBQUERY
79404 SQLITE_PRIVATE int sqlite3CodeSubselect(
79405 Parse *pParse, /* Parsing context */
79406 Expr *pExpr, /* The IN, SELECT, or EXISTS operator */
79407 int rMayHaveNull, /* Register that records whether NULLs exist in RHS */
79408 int isRowid /* If true, LHS of IN operator is a rowid */
79409 ){
79410 int testAddr = -1; /* One-time test address */
79411 int rReg = 0; /* Register storing resulting */
79412 Vdbe *v = sqlite3GetVdbe(pParse);
79413 if( NEVER(v==0) ) return 0;
79414 sqlite3ExprCachePush(pParse);
79415
@@ -79422,17 +79977,17 @@
79422 **
79423 ** If all of the above are false, then we can run this code just once
79424 ** save the results, and reuse the same result on subsequent invocations.
79425 */
79426 if( !ExprHasProperty(pExpr, EP_VarSelect) ){
79427 testAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
79428 }
79429
79430 #ifndef SQLITE_OMIT_EXPLAIN
79431 if( pParse->explain==2 ){
79432 char *zMsg = sqlite3MPrintf(
79433 pParse->db, "EXECUTE %s%s SUBQUERY %d", testAddr>=0?"":"CORRELATED ",
79434 pExpr->op==TK_IN?"LIST":"SCALAR", pParse->iNextSelectId
79435 );
79436 sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
79437 }
79438 #endif
@@ -79442,14 +79997,10 @@
79442 char affinity; /* Affinity of the LHS of the IN */
79443 int addr; /* Address of OP_OpenEphemeral instruction */
79444 Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */
79445 KeyInfo *pKeyInfo = 0; /* Key information */
79446
79447 if( rMayHaveNull ){
79448 sqlite3VdbeAddOp2(v, OP_Null, 0, rMayHaveNull);
79449 }
79450
79451 affinity = sqlite3ExprAffinity(pLeft);
79452
79453 /* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
79454 ** expression it is handled the same way. An ephemeral table is
79455 ** filled with single-field index keys representing the results
@@ -79471,24 +80022,27 @@
79471 /* Case 1: expr IN (SELECT ...)
79472 **
79473 ** Generate code to write the results of the select into the temporary
79474 ** table allocated and opened above.
79475 */
 
79476 SelectDest dest;
79477 ExprList *pEList;
79478
79479 assert( !isRowid );
79480 sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
79481 dest.affSdst = (u8)affinity;
79482 assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
79483 pExpr->x.pSelect->iLimit = 0;
 
 
79484 testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
79485 if( sqlite3Select(pParse, pExpr->x.pSelect, &dest) ){
79486 sqlite3KeyInfoUnref(pKeyInfo);
79487 return 0;
79488 }
79489 pEList = pExpr->x.pSelect->pEList;
79490 assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
79491 assert( pEList!=0 );
79492 assert( pEList->nExpr>0 );
79493 assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
79494 pKeyInfo->aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
@@ -79515,23 +80069,23 @@
79515 }
79516
79517 /* Loop through each expression in <exprlist>. */
79518 r1 = sqlite3GetTempReg(pParse);
79519 r2 = sqlite3GetTempReg(pParse);
79520 sqlite3VdbeAddOp2(v, OP_Null, 0, r2);
79521 for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
79522 Expr *pE2 = pItem->pExpr;
79523 int iValToIns;
79524
79525 /* If the expression is not constant then we will need to
79526 ** disable the test that was generated above that makes sure
79527 ** this code only executes once. Because for a non-constant
79528 ** expression we need to rerun this code each time.
79529 */
79530 if( testAddr>=0 && !sqlite3ExprIsConstant(pE2) ){
79531 sqlite3VdbeChangeToNoop(v, testAddr);
79532 testAddr = -1;
79533 }
79534
79535 /* Evaluate the expression and insert it into the temp table */
79536 if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){
79537 sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns);
@@ -79597,12 +80151,16 @@
79597 ExprSetVVAProperty(pExpr, EP_NoReduce);
79598 break;
79599 }
79600 }
79601
79602 if( testAddr>=0 ){
79603 sqlite3VdbeJumpHere(v, testAddr);
 
 
 
 
79604 }
79605 sqlite3ExprCachePop(pParse);
79606
79607 return rReg;
79608 }
@@ -79619,11 +80177,11 @@
79619 ** is an array of zero or more values. The expression is true if the LHS is
79620 ** contained within the RHS. The value of the expression is unknown (NULL)
79621 ** if the LHS is NULL or if the LHS is not contained within the RHS and the
79622 ** RHS contains one or more NULL values.
79623 **
79624 ** This routine generates code will jump to destIfFalse if the LHS is not
79625 ** contained within the RHS. If due to NULLs we cannot determine if the LHS
79626 ** is contained in the RHS then jump to destIfNull. If the LHS is contained
79627 ** within the RHS then fall through.
79628 */
79629 static void sqlite3ExprCodeIN(
@@ -79642,11 +80200,13 @@
79642 ** pExpr->iTable will contains the values that make up the RHS.
79643 */
79644 v = pParse->pVdbe;
79645 assert( v!=0 ); /* OOM detected prior to this routine */
79646 VdbeNoopComment((v, "begin IN expr"));
79647 eType = sqlite3FindInIndex(pParse, pExpr, &rRhsHasNull);
 
 
79648
79649 /* Figure out the affinity to use to create a key from the results
79650 ** of the expression. affinityStr stores a static string suitable for
79651 ** P4 of OP_MakeRecord.
79652 */
@@ -79656,86 +80216,118 @@
79656 */
79657 sqlite3ExprCachePush(pParse);
79658 r1 = sqlite3GetTempReg(pParse);
79659 sqlite3ExprCode(pParse, pExpr->pLeft, r1);
79660
79661 /* If the LHS is NULL, then the result is either false or NULL depending
79662 ** on whether the RHS is empty or not, respectively.
79663 */
79664 if( destIfNull==destIfFalse ){
79665 /* Shortcut for the common case where the false and NULL outcomes are
79666 ** the same. */
79667 sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull); VdbeCoverage(v);
79668 }else{
79669 int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); VdbeCoverage(v);
79670 sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse);
79671 VdbeCoverage(v);
79672 sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull);
79673 sqlite3VdbeJumpHere(v, addr1);
79674 }
79675
79676 if( eType==IN_INDEX_ROWID ){
79677 /* In this case, the RHS is the ROWID of table b-tree
79678 */
79679 sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse); VdbeCoverage(v);
79680 sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1);
79681 VdbeCoverage(v);
79682 }else{
79683 /* In this case, the RHS is an index b-tree.
79684 */
79685 sqlite3VdbeAddOp4(v, OP_Affinity, r1, 1, 0, &affinity, 1);
79686
79687 /* If the set membership test fails, then the result of the
79688 ** "x IN (...)" expression must be either 0 or NULL. If the set
79689 ** contains no NULL values, then the result is 0. If the set
79690 ** contains one or more NULL values, then the result of the
79691 ** expression is also NULL.
79692 */
79693 if( rRhsHasNull==0 || destIfFalse==destIfNull ){
79694 /* This branch runs if it is known at compile time that the RHS
79695 ** cannot contain NULL values. This happens as the result
79696 ** of a "NOT NULL" constraint in the database schema.
79697 **
79698 ** Also run this branch if NULL is equivalent to FALSE
79699 ** for this particular IN operator.
79700 */
79701 sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, r1, 1);
79702 VdbeCoverage(v);
79703 }else{
79704 /* In this branch, the RHS of the IN might contain a NULL and
79705 ** the presence of a NULL on the RHS makes a difference in the
79706 ** outcome.
79707 */
79708 int j1, j2;
79709
79710 /* First check to see if the LHS is contained in the RHS. If so,
79711 ** then the presence of NULLs in the RHS does not matter, so jump
79712 ** over all of the code that follows.
79713 */
79714 j1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1);
79715 VdbeCoverage(v);
79716
79717 /* Here we begin generating code that runs if the LHS is not
79718 ** contained within the RHS. Generate additional code that
79719 ** tests the RHS for NULLs. If the RHS contains a NULL then
79720 ** jump to destIfNull. If there are no NULLs in the RHS then
79721 ** jump to destIfFalse.
79722 */
79723 sqlite3VdbeAddOp2(v, OP_If, rRhsHasNull, destIfNull); VdbeCoverage(v);
79724 sqlite3VdbeAddOp2(v, OP_IfNot, rRhsHasNull, destIfFalse); VdbeCoverage(v);
79725 j2 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, rRhsHasNull, 1);
79726 VdbeCoverage(v);
79727 sqlite3VdbeAddOp2(v, OP_Integer, 0, rRhsHasNull);
79728 sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse);
79729 sqlite3VdbeJumpHere(v, j2);
79730 sqlite3VdbeAddOp2(v, OP_Integer, 1, rRhsHasNull);
79731 sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull);
79732
79733 /* The OP_Found at the top of this branch jumps here when true,
79734 ** causing the overall IN expression evaluation to fall through.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79735 */
79736 sqlite3VdbeJumpHere(v, j1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79737 }
79738 }
79739 sqlite3ReleaseTempReg(pParse, r1);
79740 sqlite3ExprCachePop(pParse);
79741 VdbeComment((v, "end IN expr"));
@@ -79792,21 +80384,28 @@
79792 }else{
79793 int c;
79794 i64 value;
79795 const char *z = pExpr->u.zToken;
79796 assert( z!=0 );
79797 c = sqlite3Atoi64(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
79798 if( c==0 || (c==2 && negFlag) ){
79799 char *zV;
79800 if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; }
79801 zV = dup8bytes(v, (char*)&value);
79802 sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64);
79803 }else{
79804 #ifdef SQLITE_OMIT_FLOATING_POINT
79805 sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
79806 #else
79807 codeReal(v, z, negFlag, iMem);
 
 
 
 
 
 
 
79808 #endif
79809 }
79810 }
79811 }
79812
@@ -80348,11 +80947,11 @@
80348 r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
80349 testcase( regFree1==0 );
80350 addr = sqlite3VdbeAddOp1(v, op, r1);
80351 VdbeCoverageIf(v, op==TK_ISNULL);
80352 VdbeCoverageIf(v, op==TK_NOTNULL);
80353 sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
80354 sqlite3VdbeJumpHere(v, addr);
80355 break;
80356 }
80357 case TK_AGG_FUNCTION: {
80358 AggInfo *pInfo = pExpr->pAggInfo;
@@ -80384,11 +80983,11 @@
80384 nFarg = pFarg ? pFarg->nExpr : 0;
80385 assert( !ExprHasProperty(pExpr, EP_IntValue) );
80386 zId = pExpr->u.zToken;
80387 nId = sqlite3Strlen30(zId);
80388 pDef = sqlite3FindFunction(db, zId, nId, nFarg, enc, 0);
80389 if( pDef==0 ){
80390 sqlite3ErrorMsg(pParse, "unknown function: %.*s()", nId, zId);
80391 break;
80392 }
80393
80394 /* Attempt a direct implementation of the built-in COALESCE() and
@@ -83175,19 +83774,24 @@
83175 }
83176
83177 /*
83178 ** Implementation of the stat_init(N,K,C) SQL function. The three parameters
83179 ** are:
83180 ** N: The number of columns in the index including the rowid/pk
83181 ** K: The number of columns in the index excluding the rowid/pk
83182 ** C: The number of rows in the index
83183 **
83184 ** C is only used for STAT3 and STAT4.
83185 **
83186 ** For ordinary rowid tables, N==K+1. But for WITHOUT ROWID tables,
83187 ** N=K+P where P is the number of columns in the primary key. For the
83188 ** covering index that implements the original WITHOUT ROWID table, N==K.
 
 
 
 
 
83189 **
83190 ** This routine allocates the Stat4Accum object in heap memory. The return
83191 ** value is a pointer to the the Stat4Accum object encoded as a blob (i.e.
83192 ** the size of the blob is sizeof(void*) bytes).
83193 */
@@ -83493,11 +84097,14 @@
83493 ** P Pointer to the Stat4Accum object created by stat_init()
83494 ** C Index of left-most column to differ from previous row
83495 ** R Rowid for the current row. Might be a key record for
83496 ** WITHOUT ROWID tables.
83497 **
83498 ** The SQL function always returns NULL.
 
 
 
83499 **
83500 ** The R parameter is only used for STAT3 and STAT4
83501 */
83502 static void statPush(
83503 sqlite3_context *context,
@@ -83587,11 +84194,14 @@
83587 #define STAT_GET_NLT 3 /* "nlt" column of stat[34] entry */
83588 #define STAT_GET_NDLT 4 /* "ndlt" column of stat[34] entry */
83589
83590 /*
83591 ** Implementation of the stat_get(P,J) SQL function. This routine is
83592 ** used to query the results. Content is returned for parameter J
 
 
 
83593 ** which is one of the STAT_GET_xxxx values defined above.
83594 **
83595 ** If neither STAT3 nor STAT4 are enabled, then J is always
83596 ** STAT_GET_STAT1 and is hence omitted and this routine becomes
83597 ** a one-parameter function, stat_get(P), that always returns the
@@ -83806,28 +84416,27 @@
83806 pParse->nTab = MAX(pParse->nTab, iTab);
83807 sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
83808 sqlite3VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0);
83809
83810 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
83811 int nCol; /* Number of columns indexed by pIdx */
83812 int *aGotoChng; /* Array of jump instruction addresses */
83813 int addrRewind; /* Address of "OP_Rewind iIdxCur" */
83814 int addrGotoChng0; /* Address of "Goto addr_chng_0" */
83815 int addrNextRow; /* Address of "next_row:" */
83816 const char *zIdxName; /* Name of the index */
 
83817
83818 if( pOnlyIdx && pOnlyIdx!=pIdx ) continue;
83819 if( pIdx->pPartIdxWhere==0 ) needTableCnt = 0;
83820 if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIdx) ){
83821 nCol = pIdx->nKeyCol;
83822 zIdxName = pTab->zName;
 
83823 }else{
83824 nCol = pIdx->nColumn;
83825 zIdxName = pIdx->zName;
 
83826 }
83827 aGotoChng = sqlite3DbMallocRaw(db, sizeof(int)*(nCol+1));
83828 if( aGotoChng==0 ) continue;
83829
83830 /* Populate the register containing the index name. */
83831 sqlite3VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, zIdxName, 0);
83832 VdbeComment((v, "Analysis for %s.%s", pTab->zName, zIdxName));
83833
@@ -83852,11 +84461,11 @@
83852 ** regPrev(0) = idx(0)
83853 ** chng_addr_1:
83854 ** regPrev(1) = idx(1)
83855 ** ...
83856 **
83857 ** chng_addr_N:
83858 ** regRowid = idx(rowid)
83859 ** stat_push(P, regChng, regRowid)
83860 ** Next csr
83861 ** if !eof(csr) goto next_row;
83862 **
@@ -83865,24 +84474,27 @@
83865
83866 /* Make sure there are enough memory cells allocated to accommodate
83867 ** the regPrev array and a trailing rowid (the rowid slot is required
83868 ** when building a record to insert into the sample column of
83869 ** the sqlite_stat4 table. */
83870 pParse->nMem = MAX(pParse->nMem, regPrev+nCol);
83871
83872 /* Open a read-only cursor on the index being analyzed. */
83873 assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) );
83874 sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb);
83875 sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
83876 VdbeComment((v, "%s", pIdx->zName));
83877
83878 /* Invoke the stat_init() function. The arguments are:
83879 **
83880 ** (1) the number of columns in the index including the rowid,
83881 ** (2) the number of rows in the index,
 
 
83882 **
83883 ** The second argument is only used for STAT3 and STAT4
 
83884 */
83885 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
83886 sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+3);
83887 #endif
83888 sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat4+1);
@@ -83900,56 +84512,73 @@
83900 **
83901 */
83902 addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
83903 VdbeCoverage(v);
83904 sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng);
83905 addrGotoChng0 = sqlite3VdbeAddOp0(v, OP_Goto);
83906
83907 /*
83908 ** next_row:
83909 ** regChng = 0
83910 ** if( idx(0) != regPrev(0) ) goto chng_addr_0
83911 ** regChng = 1
83912 ** if( idx(1) != regPrev(1) ) goto chng_addr_1
83913 ** ...
83914 ** regChng = N
83915 ** goto chng_addr_N
83916 */
83917 addrNextRow = sqlite3VdbeCurrentAddr(v);
83918 for(i=0; i<nCol; i++){
83919 char *pColl = (char*)sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
83920 sqlite3VdbeAddOp2(v, OP_Integer, i, regChng);
83921 sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp);
83922 aGotoChng[i] =
83923 sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ);
83924 sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
83925 VdbeCoverage(v);
83926 }
83927 sqlite3VdbeAddOp2(v, OP_Integer, nCol, regChng);
83928 aGotoChng[nCol] = sqlite3VdbeAddOp0(v, OP_Goto);
83929
83930 /*
83931 ** chng_addr_0:
83932 ** regPrev(0) = idx(0)
83933 ** chng_addr_1:
83934 ** regPrev(1) = idx(1)
83935 ** ...
83936 */
83937 sqlite3VdbeJumpHere(v, addrGotoChng0);
83938 for(i=0; i<nCol; i++){
83939 sqlite3VdbeJumpHere(v, aGotoChng[i]);
83940 sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regPrev+i);
83941 }
83942
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83943 /*
83944 ** chng_addr_N:
83945 ** regRowid = idx(rowid) // STAT34 only
83946 ** stat_push(P, regChng, regRowid) // 3rd parameter STAT34 only
83947 ** Next csr
83948 ** if !eof(csr) goto next_row;
83949 */
83950 sqlite3VdbeJumpHere(v, aGotoChng[nCol]);
83951 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
83952 assert( regRowid==(regStat4+2) );
83953 if( HasRowid(pTab) ){
83954 sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, regRowid);
83955 }else{
@@ -84023,11 +84652,10 @@
84023 }
84024 #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
84025
84026 /* End of analysis */
84027 sqlite3VdbeJumpHere(v, addrRewind);
84028 sqlite3DbFree(db, aGotoChng);
84029 }
84030
84031
84032 /* Create a single sqlite_stat1 entry containing NULL as the index
84033 ** name and the row count as the content.
@@ -84124,10 +84752,11 @@
84124 int i;
84125 char *z, *zDb;
84126 Table *pTab;
84127 Index *pIdx;
84128 Token *pTableName;
 
84129
84130 /* Read the database schema. If an error occurs, leave an error message
84131 ** and code in pParse and return NULL. */
84132 assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
84133 if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
@@ -84171,10 +84800,12 @@
84171 }
84172 sqlite3DbFree(db, z);
84173 }
84174 }
84175 }
 
 
84176 }
84177
84178 /*
84179 ** Used to pass information from the analyzer reader through to the
84180 ** callback routine.
@@ -84229,18 +84860,23 @@
84229 #ifndef SQLITE_ENABLE_STAT3_OR_STAT4
84230 assert( pIndex!=0 );
84231 #else
84232 if( pIndex )
84233 #endif
84234 {
84235 if( strcmp(z, "unordered")==0 ){
84236 pIndex->bUnordered = 1;
84237 }else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
84238 int v32 = 0;
84239 sqlite3GetInt32(z+3, &v32);
84240 pIndex->szIdxRow = sqlite3LogEst(v32);
84241 }
 
 
 
 
 
 
 
84242 }
84243 }
84244
84245 /*
84246 ** This callback is invoked once for each index when reading the
@@ -84277,15 +84913,19 @@
84277 pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase);
84278 }
84279 z = argv[2];
84280
84281 if( pIndex ){
 
84282 decodeIntArray((char*)z, pIndex->nKeyCol+1, 0, pIndex->aiRowLogEst, pIndex);
84283 if( pIndex->pPartIdxWhere==0 ) pTable->nRowLogEst = pIndex->aiRowLogEst[0];
84284 }else{
84285 Index fakeIdx;
84286 fakeIdx.szIdxRow = pTable->szTabRow;
 
 
 
84287 decodeIntArray((char*)z, 1, 0, &pTable->nRowLogEst, &fakeIdx);
84288 pTable->szTabRow = fakeIdx.szIdxRow;
84289 }
84290
84291 return 0;
@@ -85557,10 +86197,23 @@
85557 }
85558 #else
85559 #define codeTableLocks(x)
85560 #endif
85561
 
 
 
 
 
 
 
 
 
 
 
 
 
85562 /*
85563 ** This routine is called after a single SQL statement has been
85564 ** parsed and a VDBE program to execute that statement has been
85565 ** prepared. This routine puts the finishing touches on the
85566 ** VDBE program and resets the pParse structure for the next
@@ -85593,22 +86246,23 @@
85593 ** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are
85594 ** set for each database that is used. Generate code to start a
85595 ** transaction on each used database and to verify the schema cookie
85596 ** on each used database.
85597 */
85598 if( db->mallocFailed==0 && (pParse->cookieMask || pParse->pConstExpr) ){
85599 yDbMask mask;
 
85600 int iDb, i;
85601 assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init );
85602 sqlite3VdbeJumpHere(v, 0);
85603 for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){
85604 if( (mask & pParse->cookieMask)==0 ) continue;
85605 sqlite3VdbeUsesBtree(v, iDb);
85606 sqlite3VdbeAddOp4Int(v,
85607 OP_Transaction, /* Opcode */
85608 iDb, /* P1 */
85609 (mask & pParse->writeMask)!=0, /* P2 */
85610 pParse->cookieValue[iDb], /* P3 */
85611 db->aDb[iDb].pSchema->iGeneration /* P4 */
85612 );
85613 if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1);
85614 }
@@ -85660,11 +86314,11 @@
85660 }
85661 pParse->nTab = 0;
85662 pParse->nMem = 0;
85663 pParse->nSet = 0;
85664 pParse->nVar = 0;
85665 pParse->cookieMask = 0;
85666 }
85667
85668 /*
85669 ** Run the parser and code generator recursively in order to generate
85670 ** code for the SQL statement given onto the end of the pParse context
@@ -87560,11 +88214,11 @@
87560 pTable->aCol = pSelTab->aCol;
87561 pSelTab->nCol = 0;
87562 pSelTab->aCol = 0;
87563 sqlite3DeleteTable(db, pSelTab);
87564 assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) );
87565 pTable->pSchema->flags |= DB_UnresetViews;
87566 }else{
87567 pTable->nCol = 0;
87568 nErr++;
87569 }
87570 sqlite3SelectDelete(db, pSel);
@@ -88137,16 +88791,16 @@
88137 (char *)pKey, P4_KEYINFO);
88138 sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
88139
88140 addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v);
88141 assert( pKey!=0 || db->mallocFailed || pParse->nErr );
88142 if( pIndex->onError!=OE_None && pKey!=0 ){
88143 int j2 = sqlite3VdbeCurrentAddr(v) + 3;
88144 sqlite3VdbeAddOp2(v, OP_Goto, 0, j2);
88145 addr2 = sqlite3VdbeCurrentAddr(v);
88146 sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord,
88147 pKey->nField - pIndex->nKeyCol); VdbeCoverage(v);
88148 sqlite3UniqueConstraint(pParse, OE_Abort, pIndex);
88149 }else{
88150 addr2 = sqlite3VdbeCurrentAddr(v);
88151 }
88152 sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord);
@@ -88534,13 +89188,13 @@
88534 ** considered distinct and both result in separate indices.
88535 */
88536 Index *pIdx;
88537 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
88538 int k;
88539 assert( pIdx->onError!=OE_None );
88540 assert( pIdx->idxType!=SQLITE_IDXTYPE_APPDEF );
88541 assert( pIndex->onError!=OE_None );
88542
88543 if( pIdx->nKeyCol!=pIndex->nKeyCol ) continue;
88544 for(k=0; k<pIdx->nKeyCol; k++){
88545 const char *z1;
88546 const char *z2;
@@ -88727,11 +89381,11 @@
88727 for(i=nCopy+1; i<=pIdx->nKeyCol; i++){
88728 a[i] = 23; assert( 23==sqlite3LogEst(5) );
88729 }
88730
88731 assert( 0==sqlite3LogEst(1) );
88732 if( pIdx->onError!=OE_None ) a[pIdx->nKeyCol] = 0;
88733 }
88734
88735 /*
88736 ** This routine will drop an existing named index. This routine
88737 ** implements the DROP INDEX statement.
@@ -89287,19 +89941,17 @@
89287 ** later, by sqlite3FinishCoding().
89288 */
89289 SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
89290 Parse *pToplevel = sqlite3ParseToplevel(pParse);
89291 sqlite3 *db = pToplevel->db;
89292 yDbMask mask;
89293
89294 assert( iDb>=0 && iDb<db->nDb );
89295 assert( db->aDb[iDb].pBt!=0 || iDb==1 );
89296 assert( iDb<SQLITE_MAX_ATTACHED+2 );
89297 assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
89298 mask = ((yDbMask)1)<<iDb;
89299 if( (pToplevel->cookieMask & mask)==0 ){
89300 pToplevel->cookieMask |= mask;
89301 pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie;
89302 if( !OMIT_TEMPDB && iDb==1 ){
89303 sqlite3OpenTempDatabase(pToplevel);
89304 }
89305 }
@@ -89334,11 +89986,11 @@
89334 ** necessary to undo a write and the checkpoint should not be set.
89335 */
89336 SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
89337 Parse *pToplevel = sqlite3ParseToplevel(pParse);
89338 sqlite3CodeVerifySchema(pParse, iDb);
89339 pToplevel->writeMask |= ((yDbMask)1)<<iDb;
89340 pToplevel->isMultiWrite |= setStatement;
89341 }
89342
89343 /*
89344 ** Indicate that the statement currently under construction might write
@@ -90141,13 +90793,13 @@
90141 sqlite3DeleteTable(0, pTab);
90142 }
90143 sqlite3HashClear(&temp1);
90144 sqlite3HashClear(&pSchema->fkeyHash);
90145 pSchema->pSeqTab = 0;
90146 if( pSchema->flags & DB_SchemaLoaded ){
90147 pSchema->iGeneration++;
90148 pSchema->flags &= ~DB_SchemaLoaded;
90149 }
90150 }
90151
90152 /*
90153 ** Find and return the schema associated with a BTree. Create
@@ -91022,16 +91674,13 @@
91022 ** May you do good and not evil.
91023 ** May you find forgiveness for yourself and forgive others.
91024 ** May you share freely, never taking more than you give.
91025 **
91026 *************************************************************************
91027 ** This file contains the C functions that implement various SQL
91028 ** functions of SQLite.
91029 **
91030 ** There is only one exported symbol in this file - the function
91031 ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
91032 ** All other code has file scope.
91033 */
91034 /* #include <stdlib.h> */
91035 /* #include <assert.h> */
91036
91037 /*
@@ -92989,11 +93638,11 @@
92989 if( !aiCol ) return 1;
92990 *paiCol = aiCol;
92991 }
92992
92993 for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){
92994 if( pIdx->nKeyCol==nCol && pIdx->onError!=OE_None ){
92995 /* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number
92996 ** of columns. If each indexed column corresponds to a foreign key
92997 ** column of pFKey, then this index is a winner. */
92998
92999 if( zKey==0 ){
@@ -96015,11 +96664,11 @@
96015 ){
96016 return 0; /* Default values must be the same for all columns */
96017 }
96018 }
96019 for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
96020 if( pDestIdx->onError!=OE_None ){
96021 destHasUniqueIdx = 1;
96022 }
96023 for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){
96024 if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
96025 }
@@ -96245,10 +96894,13 @@
96245 goto exec_out;
96246 }
96247 }
96248 }
96249 if( xCallback(pArg, nCol, azVals, azCols) ){
 
 
 
96250 rc = SQLITE_ABORT;
96251 sqlite3VdbeFinalize((Vdbe *)pStmt);
96252 pStmt = 0;
96253 sqlite3Error(db, SQLITE_ABORT, 0);
96254 goto exec_out;
@@ -98022,11 +98674,11 @@
98022 ** Note that the values returned are one less that the values that
98023 ** should be passed into sqlite3BtreeSetSafetyLevel(). The is done
98024 ** to support legacy SQL code. The safety level used to be boolean
98025 ** and older scripts may have used numbers 0 for OFF and 1 for ON.
98026 */
98027 static u8 getSafetyLevel(const char *z, int omitFull, int dflt){
98028 /* 123456789 123456789 */
98029 static const char zText[] = "onoffalseyestruefull";
98030 static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16};
98031 static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 4};
98032 static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 2};
@@ -98044,11 +98696,11 @@
98044 }
98045
98046 /*
98047 ** Interpret the given string as a boolean value.
98048 */
98049 SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z, int dflt){
98050 return getSafetyLevel(z,1,dflt)!=0;
98051 }
98052
98053 /* The sqlite3GetBoolean() function is used by other modules but the
98054 ** remainder of this file is specific to PRAGMA processing. So omit
@@ -98590,11 +99242,11 @@
98590 */
98591 case PragTyp_JOURNAL_SIZE_LIMIT: {
98592 Pager *pPager = sqlite3BtreePager(pDb->pBt);
98593 i64 iLimit = -2;
98594 if( zRight ){
98595 sqlite3Atoi64(zRight, &iLimit, sqlite3Strlen30(zRight), SQLITE_UTF8);
98596 if( iLimit<-1 ) iLimit = -1;
98597 }
98598 iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit);
98599 returnSingleInt(pParse, "journal_size_limit", iLimit);
98600 break;
@@ -98718,11 +99370,11 @@
98718 sqlite3_int64 sz;
98719 #if SQLITE_MAX_MMAP_SIZE>0
98720 assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
98721 if( zRight ){
98722 int ii;
98723 sqlite3Atoi64(zRight, &sz, sqlite3Strlen30(zRight), SQLITE_UTF8);
98724 if( sz<0 ) sz = sqlite3GlobalConfig.szMmap;
98725 if( pId2->n==0 ) db->szMmap = sz;
98726 for(ii=db->nDb-1; ii>=0; ii--){
98727 if( db->aDb[ii].pBt && (ii==iDb || pId2->n==0) ){
98728 sqlite3BtreeSetMmapLimit(db->aDb[ii].pBt, sz);
@@ -99086,11 +99738,11 @@
99086 sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
99087 sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
99088 for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){
99089 sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
99090 sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
99091 sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);
99092 sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
99093 }
99094 }
99095 }
99096 break;
@@ -99336,13 +99988,12 @@
99336 ** messages have been generated, output OK. Otherwise output the
99337 ** error message
99338 */
99339 static const int iLn = VDBE_OFFSET_LINENO(2);
99340 static const VdbeOpList endCode[] = {
99341 { OP_AddImm, 1, 0, 0}, /* 0 */
99342 { OP_IfNeg, 1, 0, 0}, /* 1 */
99343 { OP_String8, 0, 3, 0}, /* 2 */
99344 { OP_ResultRow, 3, 1, 0},
99345 };
99346
99347 int isQuick = (sqlite3Tolower(zLeft[0])=='q');
99348
@@ -99450,32 +100101,80 @@
99450 sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */
99451 }
99452 pParse->nMem = MAX(pParse->nMem, 8+j);
99453 sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v);
99454 loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99455 for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
99456 int jmp2, jmp3, jmp4;
 
99457 if( pPk==pIdx ) continue;
99458 r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
99459 pPrior, r1);
99460 pPrior = pIdx;
99461 sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */
99462 jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, 0, r1,
 
99463 pIdx->nColumn); VdbeCoverage(v);
99464 sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
99465 sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, "row ", P4_STATIC);
99466 sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
99467 sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, " missing from index ",
99468 P4_STATIC);
99469 sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
99470 sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, pIdx->zName, P4_TRANSIENT);
 
99471 sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
99472 sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
99473 jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v);
99474 sqlite3VdbeAddOp0(v, OP_Halt);
99475 sqlite3VdbeJumpHere(v, jmp4);
99476 sqlite3VdbeJumpHere(v, jmp2);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99477 sqlite3ResolvePartIdxLabel(pParse, jmp3);
99478 }
99479 sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
99480 sqlite3VdbeJumpHere(v, loopTop-1);
99481 #ifndef SQLITE_OMIT_BTREECOUNT
@@ -99496,13 +100195,13 @@
99496 }
99497 #endif /* SQLITE_OMIT_BTREECOUNT */
99498 }
99499 }
99500 addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
99501 sqlite3VdbeChangeP2(v, addr, -mxErr);
99502 sqlite3VdbeJumpHere(v, addr+1);
99503 sqlite3VdbeChangeP4(v, addr+2, "ok", P4_STATIC);
99504 }
99505 break;
99506 #endif /* SQLITE_OMIT_INTEGRITY_CHECK */
99507
99508 #ifndef SQLITE_OMIT_UTF16
@@ -99761,11 +100460,11 @@
99761 ** Call sqlite3_soft_heap_limit64(N). Return the result. If N is omitted,
99762 ** use -1.
99763 */
99764 case PragTyp_SOFT_HEAP_LIMIT: {
99765 sqlite3_int64 N;
99766 if( zRight && sqlite3Atoi64(zRight, &N, 1000000, SQLITE_UTF8)==SQLITE_OK ){
99767 sqlite3_soft_heap_limit64(N);
99768 }
99769 returnSingleInt(pParse, "soft_heap_limit", sqlite3_soft_heap_limit64(-1));
99770 break;
99771 }
@@ -101284,12 +101983,11 @@
101284 int iOffset, /* Register holding the offset counter */
101285 int iContinue /* Jump here to skip the current record */
101286 ){
101287 if( iOffset>0 ){
101288 int addr;
101289 sqlite3VdbeAddOp2(v, OP_AddImm, iOffset, -1);
101290 addr = sqlite3VdbeAddOp1(v, OP_IfNeg, iOffset); VdbeCoverage(v);
101291 sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue);
101292 VdbeComment((v, "skip OFFSET records"));
101293 sqlite3VdbeJumpHere(v, addr);
101294 }
101295 }
@@ -101450,11 +102148,11 @@
101450 VdbeCoverage(v);
101451 }
101452 sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
101453 sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
101454 }
101455 assert( sqlite3VdbeCurrentAddr(v)==iJump );
101456 sqlite3VdbeAddOp3(v, OP_Copy, regResult, regPrev, nResultCol-1);
101457 break;
101458 }
101459
101460 case WHERE_DISTINCT_UNIQUE: {
@@ -107917,11 +108615,12 @@
107917 sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey);
107918 VdbeCoverageNeverTaken(v);
107919 }
107920 labelContinue = labelBreak;
107921 sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak);
107922 VdbeCoverage(v);
 
107923 }else if( pPk ){
107924 labelContinue = sqlite3VdbeMakeLabel(v);
107925 sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v);
107926 addrTop = sqlite3VdbeAddOp2(v, OP_RowKey, iEph, regKey);
107927 sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0);
@@ -109927,10 +110626,11 @@
109927 struct WherePath {
109928 Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */
109929 Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */
109930 LogEst nRow; /* Estimated number of rows generated by this path */
109931 LogEst rCost; /* Total cost of this path */
 
109932 i8 isOrdered; /* No. of ORDER BY terms satisfied. -1 for unknown */
109933 WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */
109934 };
109935
109936 /*
@@ -111657,11 +112357,11 @@
111657 **
111658 ** 3. All of those index columns for which the WHERE clause does not
111659 ** contain a "col=X" term are subject to a NOT NULL constraint.
111660 */
111661 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
111662 if( pIdx->onError==OE_None ) continue;
111663 for(i=0; i<pIdx->nKeyCol; i++){
111664 i16 iCol = pIdx->aiColumn[i];
111665 if( 0==findTerm(pWC, iBase, iCol, ~(Bitmask)0, WO_EQ, pIdx) ){
111666 int iIdxCol = findIndexCol(pParse, pDistinct, iBase, pIdx, i);
111667 if( iIdxCol<0 || pTab->aCol[iCol].notNull==0 ){
@@ -112234,11 +112934,12 @@
112234 int nEq = pLoop->u.btree.nEq;
112235 sqlite3 *db = pParse->db;
112236 int nLower = -1;
112237 int nUpper = p->nSample+1;
112238 int rc = SQLITE_OK;
112239 u8 aff = p->pTable->aCol[ p->aiColumn[nEq] ].affinity;
 
112240 CollSeq *pColl;
112241
112242 sqlite3_value *p1 = 0; /* Value extracted from pLower */
112243 sqlite3_value *p2 = 0; /* Value extracted from pUpper */
112244 sqlite3_value *pVal = 0; /* Value extracted from record */
@@ -112708,11 +113409,11 @@
112708 testcase( bRev );
112709 bRev = !bRev;
112710 }
112711 assert( pX->op==TK_IN );
112712 iReg = iTarget;
112713 eType = sqlite3FindInIndex(pParse, pX, 0);
112714 if( eType==IN_INDEX_INDEX_DESC ){
112715 testcase( bRev );
112716 bRev = !bRev;
112717 }
112718 iTab = pX->iTable;
@@ -113609,10 +114310,11 @@
113609 int regRowid = 0; /* Register holding rowid */
113610 int iLoopBody = sqlite3VdbeMakeLabel(v); /* Start of loop body */
113611 int iRetInit; /* Address of regReturn init */
113612 int untestedTerms = 0; /* Some terms not completely tested */
113613 int ii; /* Loop counter */
 
113614 Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
113615 Table *pTab = pTabItem->pTab;
113616
113617 pTerm = pLoop->aLTerm[0];
113618 assert( pTerm!=0 );
@@ -113704,10 +114406,12 @@
113704
113705 /* Run a separate WHERE clause for each term of the OR clause. After
113706 ** eliminating duplicates from other WHERE clauses, the action for each
113707 ** sub-WHERE clause is to to invoke the main loop body as a subroutine.
113708 */
 
 
113709 for(ii=0; ii<pOrWc->nTerm; ii++){
113710 WhereTerm *pOrTerm = &pOrWc->a[ii];
113711 if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
113712 WhereInfo *pSubWInfo; /* Info for single OR-term scan */
113713 Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
@@ -113716,12 +114420,11 @@
113716 pAndExpr->pLeft = pOrExpr;
113717 pOrExpr = pAndExpr;
113718 }
113719 /* Loop through table entries that match term pOrTerm. */
113720 pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
113721 WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
113722 WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY, iCovCur);
113723 assert( pSubWInfo || pParse->nErr || db->mallocFailed );
113724 if( pSubWInfo ){
113725 WhereLoop *pSubLoop;
113726 explainOneScan(
113727 pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
@@ -113808,10 +114511,11 @@
113808 && (ii==0 || pSubLoop->u.btree.pIndex==pCov)
113809 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pSubLoop->u.btree.pIndex))
113810 ){
113811 assert( pSubWInfo->a[0].iIdxCur==iCovCur );
113812 pCov = pSubLoop->u.btree.pIndex;
 
113813 }else{
113814 pCov = 0;
113815 }
113816
113817 /* Finish the loop through table entries that match term pOrTerm. */
@@ -114414,10 +115118,20 @@
114414 pLoop->nOut += (pTerm->truthProb<=0 ? pTerm->truthProb : -1);
114415 }
114416 }
114417 }
114418
 
 
 
 
 
 
 
 
 
 
114419 /*
114420 ** We have so far matched pBuilder->pNew->u.btree.nEq terms of the
114421 ** index pIndex. Try to match one more.
114422 **
114423 ** When this function is called, pBuilder->pNew->nOut contains the
@@ -114549,11 +115263,11 @@
114549 ** changes "x IN (?)" into "x=?". */
114550
114551 }else if( eOp & (WO_EQ) ){
114552 pNew->wsFlags |= WHERE_COLUMN_EQ;
114553 if( iCol<0 || (nInMul==0 && pNew->u.btree.nEq==pProbe->nKeyCol-1) ){
114554 if( iCol>=0 && pProbe->onError==OE_None ){
114555 pNew->wsFlags |= WHERE_UNQ_WANTED;
114556 }else{
114557 pNew->wsFlags |= WHERE_ONEROW;
114558 }
114559 }
@@ -114610,11 +115324,10 @@
114610 testcase( eOp & WO_ISNULL );
114611 rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut);
114612 }else{
114613 rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut);
114614 }
114615 assert( rc!=SQLITE_OK || nOut>0 );
114616 if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
114617 if( rc!=SQLITE_OK ) break; /* Jump out of the pTerm loop */
114618 if( nOut ){
114619 pNew->nOut = sqlite3LogEst(nOut);
114620 if( pNew->nOut>saved_nOut ) pNew->nOut = saved_nOut;
@@ -114642,10 +115355,11 @@
114642 rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow;
114643 pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx);
114644 if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
114645 pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16);
114646 }
 
114647
114648 nOutUnadjusted = pNew->nOut;
114649 pNew->rRun += nInMul + nIn;
114650 pNew->nOut += nInMul + nIn;
114651 whereLoopOutputAdjust(pBuilder->pWC, pNew);
@@ -114761,10 +115475,18 @@
114761 ** cost = nSeek * (log(nRow) + (K+3.0) * nVisit) // non-covering index
114762 **
114763 ** Normally, nSeek is 1. nSeek values greater than 1 come about if the
114764 ** WHERE clause includes "x IN (....)" terms used in place of "x=?". Or when
114765 ** implicit "x IN (SELECT x FROM tbl)" terms are added for skip-scans.
 
 
 
 
 
 
 
 
114766 */
114767 static int whereLoopAddBtree(
114768 WhereLoopBuilder *pBuilder, /* WHERE clause information */
114769 Bitmask mExtra /* Extra prerequesites for using this table */
114770 ){
@@ -114848,10 +115570,11 @@
114848 pNew->aLTerm[0] = pTerm;
114849 /* TUNING: One-time cost for computing the automatic index is
114850 ** approximately 7*N*log2(N) where N is the number of rows in
114851 ** the table being indexed. */
114852 pNew->rSetup = rLogSize + rSize + 28; assert( 28==sqlite3LogEst(7) );
 
114853 /* TUNING: Each index lookup yields 20 rows in the table. This
114854 ** is more than the usual guess of 10 rows, since we have no way
114855 ** of knowning how selective the index will ultimately be. It would
114856 ** not be unreasonable to make this value much larger. */
114857 pNew->nOut = 43; assert( 43==sqlite3LogEst(20) );
@@ -114889,10 +115612,11 @@
114889
114890 /* Full table scan */
114891 pNew->iSortIdx = b ? iSortIdx : 0;
114892 /* TUNING: Cost of full table scan is (N*3.0). */
114893 pNew->rRun = rSize + 16;
 
114894 whereLoopOutputAdjust(pWC, pNew);
114895 rc = whereLoopInsert(pBuilder, pNew);
114896 pNew->nOut = rSize;
114897 if( rc ) break;
114898 }else{
@@ -114924,11 +115648,11 @@
114924 ** also add the cost of visiting table rows (N*3.0). */
114925 pNew->rRun = rSize + 1 + (15*pProbe->szIdxRow)/pTab->szTabRow;
114926 if( m!=0 ){
114927 pNew->rRun = sqlite3LogEstAdd(pNew->rRun, rSize+16);
114928 }
114929
114930 whereLoopOutputAdjust(pWC, pNew);
114931 rc = whereLoopInsert(pBuilder, pNew);
114932 pNew->nOut = rSize;
114933 if( rc ) break;
114934 }
@@ -115394,11 +116118,11 @@
115394 }else{
115395 nKeyCol = pIndex->nKeyCol;
115396 nColumn = pIndex->nColumn;
115397 assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) );
115398 assert( pIndex->aiColumn[nColumn-1]==(-1) || !HasRowid(pIndex->pTable));
115399 isOrderDistinct = pIndex->onError!=OE_None;
115400 }
115401
115402 /* Loop through all columns of the index and deal with the ones
115403 ** that are not constrained by == or IN.
115404 */
@@ -115562,10 +116286,49 @@
115562 if( pLast ) zName[i++] = pLast->cId;
115563 zName[i] = 0;
115564 return zName;
115565 }
115566 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115567
115568 /*
115569 ** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
115570 ** attempts to find the lowest cost path that visits each WhereLoop
115571 ** once. This path is then loaded into the pWInfo->a[].pWLoop fields.
@@ -115584,139 +116347,170 @@
115584 sqlite3 *db; /* The database connection */
115585 int iLoop; /* Loop counter over the terms of the join */
115586 int ii, jj; /* Loop counters */
115587 int mxI = 0; /* Index of next entry to replace */
115588 int nOrderBy; /* Number of ORDER BY clause terms */
115589 LogEst rCost; /* Cost of a path */
115590 LogEst nOut; /* Number of outputs */
115591 LogEst mxCost = 0; /* Maximum cost of a set of paths */
 
115592 int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
115593 WherePath *aFrom; /* All nFrom paths at the previous level */
115594 WherePath *aTo; /* The nTo best paths at the current level */
115595 WherePath *pFrom; /* An element of aFrom[] that we are working on */
115596 WherePath *pTo; /* An element of aTo[] that we are working on */
115597 WhereLoop *pWLoop; /* One of the WhereLoop objects */
115598 WhereLoop **pX; /* Used to divy up the pSpace memory */
 
115599 char *pSpace; /* Temporary memory used by this routine */
 
115600
115601 pParse = pWInfo->pParse;
115602 db = pParse->db;
115603 nLoop = pWInfo->nLevel;
115604 /* TUNING: For simple queries, only the best path is tracked.
115605 ** For 2-way joins, the 5 best paths are followed.
115606 ** For joins of 3 or more tables, track the 10 best paths */
115607 mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10);
115608 assert( nLoop<=pWInfo->pTabList->nSrc );
115609 WHERETRACE(0x002, ("---- begin solver\n"));
115610
115611 /* Allocate and initialize space for aTo and aFrom */
115612 ii = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
115613 pSpace = sqlite3DbMallocRaw(db, ii);
 
 
 
 
 
 
 
 
 
 
 
 
115614 if( pSpace==0 ) return SQLITE_NOMEM;
115615 aTo = (WherePath*)pSpace;
115616 aFrom = aTo+mxChoice;
115617 memset(aFrom, 0, sizeof(aFrom[0]));
115618 pX = (WhereLoop**)(aFrom+mxChoice);
115619 for(ii=mxChoice*2, pFrom=aTo; ii>0; ii--, pFrom++, pX += nLoop){
115620 pFrom->aLoop = pX;
115621 }
 
 
 
 
 
 
 
 
 
 
 
 
115622
115623 /* Seed the search with a single WherePath containing zero WhereLoops.
115624 **
115625 ** TUNING: Do not let the number of iterations go above 25. If the cost
115626 ** of computing an automatic index is not paid back within the first 25
115627 ** rows, then do not use the automatic index. */
115628 aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==sqlite3LogEst(25) );
115629 nFrom = 1;
115630
115631 /* Precompute the cost of sorting the final result set, if the caller
115632 ** to sqlite3WhereBegin() was concerned about sorting */
115633 if( pWInfo->pOrderBy==0 || nRowEst==0 ){
115634 aFrom[0].isOrdered = 0;
115635 nOrderBy = 0;
115636 }else{
115637 aFrom[0].isOrdered = nLoop>0 ? -1 : 1;
115638 nOrderBy = pWInfo->pOrderBy->nExpr;
115639 }
115640
115641 /* Compute successively longer WherePaths using the previous generation
115642 ** of WherePaths as the basis for the next. Keep track of the mxChoice
115643 ** best paths at each generation */
115644 for(iLoop=0; iLoop<nLoop; iLoop++){
115645 nTo = 0;
115646 for(ii=0, pFrom=aFrom; ii<nFrom; ii++, pFrom++){
115647 for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
115648 Bitmask maskNew;
115649 Bitmask revMask = 0;
115650 i8 isOrdered = pFrom->isOrdered;
 
 
 
 
115651 if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
115652 if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
115653 /* At this point, pWLoop is a candidate to be the next loop.
115654 ** Compute its cost */
115655 rCost = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
115656 rCost = sqlite3LogEstAdd(rCost, pFrom->rCost);
115657 nOut = pFrom->nRow + pWLoop->nOut;
115658 maskNew = pFrom->maskLoop | pWLoop->maskSelf;
115659 if( isOrdered<0 ){
115660 isOrdered = wherePathSatisfiesOrderBy(pWInfo,
115661 pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
115662 iLoop, pWLoop, &revMask);
115663 if( isOrdered>=0 && isOrdered<nOrderBy ){
115664 /* TUNING: Estimated cost of a full external sort, where N is
115665 ** the number of rows to sort is:
115666 **
115667 ** cost = (3.0 * N * log(N)).
115668 **
115669 ** Or, if the order-by clause has X terms but only the last Y
115670 ** terms are out of order, then block-sorting will reduce the
115671 ** sorting cost to:
115672 **
115673 ** cost = (3.0 * N * log(N)) * (Y/X)
115674 **
115675 ** The (Y/X) term is implemented using stack variable rScale
115676 ** below. */
115677 LogEst rScale, rSortCost;
115678 assert( nOrderBy>0 && 66==sqlite3LogEst(100) );
115679 rScale = sqlite3LogEst((nOrderBy-isOrdered)*100/nOrderBy) - 66;
115680 rSortCost = nRowEst + estLog(nRowEst) + rScale + 16;
115681
115682 /* TUNING: The cost of implementing DISTINCT using a B-TREE is
115683 ** similar but with a larger constant of proportionality.
115684 ** Multiply by an additional factor of 3.0. */
115685 if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
115686 rSortCost += 16;
115687 }
115688 WHERETRACE(0x002,
115689 ("---- sort cost=%-3d (%d/%d) increases cost %3d to %-3d\n",
115690 rSortCost, (nOrderBy-isOrdered), nOrderBy, rCost,
115691 sqlite3LogEstAdd(rCost,rSortCost)));
115692 rCost = sqlite3LogEstAdd(rCost, rSortCost);
115693 }
115694 }else{
115695 revMask = pFrom->revLoop;
115696 }
115697 /* Check to see if pWLoop should be added to the mxChoice best so far */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115698 for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
115699 if( pTo->maskLoop==maskNew
115700 && ((pTo->isOrdered^isOrdered)&80)==0
115701 ){
115702 testcase( jj==nTo-1 );
115703 break;
115704 }
115705 }
115706 if( jj>=nTo ){
115707 if( nTo>=mxChoice && rCost>=mxCost ){
 
 
 
 
 
 
115708 #ifdef WHERETRACE_ENABLED /* 0x4 */
115709 if( sqlite3WhereTrace&0x4 ){
115710 sqlite3DebugPrintf("Skip %s cost=%-3d,%3d order=%c\n",
115711 wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
115712 isOrdered>=0 ? isOrdered+'0' : '?');
115713 }
115714 #endif
115715 continue;
115716 }
115717 /* Add a new Path to the aTo[] set */
 
115718 if( nTo<mxChoice ){
115719 /* Increase the size of the aTo set by one */
115720 jj = nTo++;
115721 }else{
115722 /* New path replaces the prior worst to keep count below mxChoice */
@@ -115729,11 +116523,15 @@
115729 wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
115730 isOrdered>=0 ? isOrdered+'0' : '?');
115731 }
115732 #endif
115733 }else{
115734 if( pTo->rCost<=rCost ){
 
 
 
 
115735 #ifdef WHERETRACE_ENABLED /* 0x4 */
115736 if( sqlite3WhereTrace&0x4 ){
115737 sqlite3DebugPrintf(
115738 "Skip %s cost=%-3d,%3d order=%c",
115739 wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
@@ -115741,15 +116539,17 @@
115741 sqlite3DebugPrintf(" vs %s cost=%-3d,%d order=%c\n",
115742 wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
115743 pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
115744 }
115745 #endif
 
115746 testcase( pTo->rCost==rCost );
115747 continue;
115748 }
115749 testcase( pTo->rCost==rCost+1 );
115750 /* A new and better score for a previously created equivalent path */
 
115751 #ifdef WHERETRACE_ENABLED /* 0x4 */
115752 if( sqlite3WhereTrace&0x4 ){
115753 sqlite3DebugPrintf(
115754 "Update %s cost=%-3d,%3d order=%c",
115755 wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
@@ -115763,19 +116563,24 @@
115763 /* pWLoop is a winner. Add it to the set of best so far */
115764 pTo->maskLoop = pFrom->maskLoop | pWLoop->maskSelf;
115765 pTo->revLoop = revMask;
115766 pTo->nRow = nOut;
115767 pTo->rCost = rCost;
 
115768 pTo->isOrdered = isOrdered;
115769 memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop);
115770 pTo->aLoop[iLoop] = pWLoop;
115771 if( nTo>=mxChoice ){
115772 mxI = 0;
115773 mxCost = aTo[0].rCost;
 
115774 for(jj=1, pTo=&aTo[1]; jj<mxChoice; jj++, pTo++){
115775 if( pTo->rCost>mxCost ){
 
 
115776 mxCost = pTo->rCost;
 
115777 mxI = jj;
115778 }
115779 }
115780 }
115781 }
@@ -115909,11 +116714,11 @@
115909 pLoop->rRun = 33; /* 33==sqlite3LogEst(10) */
115910 }else{
115911 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
115912 assert( pLoop->aLTermSpace==pLoop->aLTerm );
115913 assert( ArraySize(pLoop->aLTermSpace)==4 );
115914 if( pIdx->onError==OE_None
115915 || pIdx->pPartIdxWhere!=0
115916 || pIdx->nKeyCol>ArraySize(pLoop->aLTermSpace)
115917 ) continue;
115918 for(j=0; j<pIdx->nKeyCol; j++){
115919 pTerm = findTerm(pWC, iCur, pIdx->aiColumn[j], 0, WO_EQ, pIdx);
@@ -116399,10 +117204,11 @@
116399 }
116400 op = OP_OpenWrite;
116401 pWInfo->aiCurOnePass[1] = iIndexCur;
116402 }else if( iIdxCur && (wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ){
116403 iIndexCur = iIdxCur;
 
116404 }else{
116405 iIndexCur = pParse->nTab++;
116406 }
116407 pLevel->iIdxCur = iIndexCur;
116408 assert( pIx->pSchema==pTab->pSchema );
@@ -120723,10 +121529,16 @@
120723 testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' );
120724 testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' );
120725 testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' );
120726 testcase( z[0]=='9' );
120727 *tokenType = TK_INTEGER;
 
 
 
 
 
 
120728 for(i=0; sqlite3Isdigit(z[i]); i++){}
120729 #ifndef SQLITE_OMIT_FLOATING_POINT
120730 if( z[i]=='.' ){
120731 i++;
120732 while( sqlite3Isdigit(z[i]) ){ i++; }
@@ -122170,10 +122982,12 @@
122170 /*
122171 ** Close an existing SQLite database
122172 */
122173 static int sqlite3Close(sqlite3 *db, int forceZombie){
122174 if( !db ){
 
 
122175 return SQLITE_OK;
122176 }
122177 if( !sqlite3SafetyCheckSickOrOk(db) ){
122178 return SQLITE_MISUSE_BKPT;
122179 }
@@ -122399,11 +123213,11 @@
122399
122400 /*
122401 ** Return a static string containing the name corresponding to the error code
122402 ** specified in the argument.
122403 */
122404 #if defined(SQLITE_TEST)
122405 SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
122406 const char *zName = 0;
122407 int i, origRc = rc;
122408 for(i=0; i<2 && zName==0; i++, rc &= 0xff){
122409 switch( rc ){
@@ -122434,11 +123248,10 @@
122434 case SQLITE_IOERR_TRUNCATE: zName = "SQLITE_IOERR_TRUNCATE"; break;
122435 case SQLITE_IOERR_FSTAT: zName = "SQLITE_IOERR_FSTAT"; break;
122436 case SQLITE_IOERR_UNLOCK: zName = "SQLITE_IOERR_UNLOCK"; break;
122437 case SQLITE_IOERR_RDLOCK: zName = "SQLITE_IOERR_RDLOCK"; break;
122438 case SQLITE_IOERR_DELETE: zName = "SQLITE_IOERR_DELETE"; break;
122439 case SQLITE_IOERR_BLOCKED: zName = "SQLITE_IOERR_BLOCKED"; break;
122440 case SQLITE_IOERR_NOMEM: zName = "SQLITE_IOERR_NOMEM"; break;
122441 case SQLITE_IOERR_ACCESS: zName = "SQLITE_IOERR_ACCESS"; break;
122442 case SQLITE_IOERR_CHECKRESERVEDLOCK:
122443 zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
122444 case SQLITE_IOERR_LOCK: zName = "SQLITE_IOERR_LOCK"; break;
@@ -123419,11 +124232,11 @@
123419 SQLITE_MAX_COMPOUND_SELECT,
123420 SQLITE_MAX_VDBE_OP,
123421 SQLITE_MAX_FUNCTION_ARG,
123422 SQLITE_MAX_ATTACHED,
123423 SQLITE_MAX_LIKE_PATTERN_LENGTH,
123424 SQLITE_MAX_VARIABLE_NUMBER,
123425 SQLITE_MAX_TRIGGER_DEPTH,
123426 };
123427
123428 /*
123429 ** Make sure the hard limits are set to reasonable values
@@ -123444,12 +124257,12 @@
123444 # error SQLITE_MAX_VDBE_OP must be at least 40
123445 #endif
123446 #if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>1000
123447 # error SQLITE_MAX_FUNCTION_ARG must be between 0 and 1000
123448 #endif
123449 #if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>62
123450 # error SQLITE_MAX_ATTACHED must be between 0 and 62
123451 #endif
123452 #if SQLITE_MAX_LIKE_PATTERN_LENGTH<1
123453 # error SQLITE_MAX_LIKE_PATTERN_LENGTH must be at least 1
123454 #endif
123455 #if SQLITE_MAX_COLUMN>32767
@@ -124704,10 +125517,20 @@
124704 sqlite3GlobalConfig.pVdbeBranchArg = va_arg(ap,void*);
124705 #endif
124706 break;
124707 }
124708
 
 
 
 
 
 
 
 
 
 
124709 }
124710 va_end(ap);
124711 #endif /* SQLITE_OMIT_BUILTIN_TEST */
124712 return rc;
124713 }
@@ -124752,11 +125575,11 @@
124752 const char *zParam, /* URI parameter sought */
124753 sqlite3_int64 bDflt /* return if parameter is missing */
124754 ){
124755 const char *z = sqlite3_uri_parameter(zFilename, zParam);
124756 sqlite3_int64 v;
124757 if( z && sqlite3Atoi64(z, &v, sqlite3Strlen30(z), SQLITE_UTF8)==SQLITE_OK ){
124758 bDflt = v;
124759 }
124760 return bDflt;
124761 }
124762
@@ -126283,11 +127106,11 @@
126283
126284 /* fts3_tokenize_vtab.c */
126285 SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *);
126286
126287 /* fts3_unicode2.c (functions generated by parsing unicode text files) */
126288 #ifdef SQLITE_ENABLE_FTS4_UNICODE61
126289 SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int, int);
126290 SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int);
126291 SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int);
126292 #endif
126293
@@ -129753,11 +130576,11 @@
129753 ** to by the argument to point to the "simple" tokenizer implementation.
129754 ** And so on.
129755 */
129756 SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule);
129757 SQLITE_PRIVATE void sqlite3Fts3PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule);
129758 #ifdef SQLITE_ENABLE_FTS4_UNICODE61
129759 SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const**ppModule);
129760 #endif
129761 #ifdef SQLITE_ENABLE_ICU
129762 SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule);
129763 #endif
@@ -129771,20 +130594,20 @@
129771 SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){
129772 int rc = SQLITE_OK;
129773 Fts3Hash *pHash = 0;
129774 const sqlite3_tokenizer_module *pSimple = 0;
129775 const sqlite3_tokenizer_module *pPorter = 0;
129776 #ifdef SQLITE_ENABLE_FTS4_UNICODE61
129777 const sqlite3_tokenizer_module *pUnicode = 0;
129778 #endif
129779
129780 #ifdef SQLITE_ENABLE_ICU
129781 const sqlite3_tokenizer_module *pIcu = 0;
129782 sqlite3Fts3IcuTokenizerModule(&pIcu);
129783 #endif
129784
129785 #ifdef SQLITE_ENABLE_FTS4_UNICODE61
129786 sqlite3Fts3UnicodeTokenizer(&pUnicode);
129787 #endif
129788
129789 #ifdef SQLITE_TEST
129790 rc = sqlite3Fts3InitTerm(db);
@@ -129808,11 +130631,11 @@
129808 /* Load the built-in tokenizers into the hash table */
129809 if( rc==SQLITE_OK ){
129810 if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple)
129811 || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter)
129812
129813 #ifdef SQLITE_ENABLE_FTS4_UNICODE61
129814 || sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode)
129815 #endif
129816 #ifdef SQLITE_ENABLE_ICU
129817 || (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu))
129818 #endif
@@ -143068,11 +143891,11 @@
143068 ******************************************************************************
143069 **
143070 ** Implementation of the "unicode" full-text-search tokenizer.
143071 */
143072
143073 #ifdef SQLITE_ENABLE_FTS4_UNICODE61
143074
143075 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
143076
143077 /* #include <assert.h> */
143078 /* #include <stdlib.h> */
@@ -143284,11 +144107,11 @@
143284 memset(pNew, 0, sizeof(unicode_tokenizer));
143285 pNew->bRemoveDiacritic = 1;
143286
143287 for(i=0; rc==SQLITE_OK && i<nArg; i++){
143288 const char *z = azArg[i];
143289 int n = strlen(z);
143290
143291 if( n==19 && memcmp("remove_diacritics=1", z, 19)==0 ){
143292 pNew->bRemoveDiacritic = 1;
143293 }
143294 else if( n==19 && memcmp("remove_diacritics=0", z, 19)==0 ){
@@ -143371,11 +144194,11 @@
143371 int *piEnd, /* OUT: Ending offset of token */
143372 int *piPos /* OUT: Position integer of token */
143373 ){
143374 unicode_cursor *pCsr = (unicode_cursor *)pC;
143375 unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer);
143376 int iCode;
143377 char *zOut;
143378 const unsigned char *z = &pCsr->aInput[pCsr->iOff];
143379 const unsigned char *zStart = z;
143380 const unsigned char *zEnd;
143381 const unsigned char *zTerm = &pCsr->aInput[pCsr->nInput];
@@ -143416,15 +144239,15 @@
143416 }while( unicodeIsAlnum(p, iCode)
143417 || sqlite3FtsUnicodeIsdiacritic(iCode)
143418 );
143419
143420 /* Set the output variables and return. */
143421 pCsr->iOff = (z - pCsr->aInput);
143422 *paToken = pCsr->zToken;
143423 *pnToken = zOut - pCsr->zToken;
143424 *piStart = (zStart - pCsr->aInput);
143425 *piEnd = (zEnd - pCsr->aInput);
143426 *piPos = pCsr->iToken++;
143427 return SQLITE_OK;
143428 }
143429
143430 /*
@@ -143443,11 +144266,11 @@
143443 };
143444 *ppModule = &module;
143445 }
143446
143447 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
143448 #endif /* ifndef SQLITE_ENABLE_FTS4_UNICODE61 */
143449
143450 /************** End of fts3_unicode.c ****************************************/
143451 /************** Begin file fts3_unicode2.c ***********************************/
143452 /*
143453 ** 2012 May 25
@@ -143464,11 +144287,11 @@
143464
143465 /*
143466 ** DO NOT EDIT THIS MACHINE GENERATED FILE.
143467 */
143468
143469 #if defined(SQLITE_ENABLE_FTS4_UNICODE61)
143470 #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
143471
143472 /* #include <assert.h> */
143473
143474 /*
@@ -143488,11 +144311,11 @@
143488 ** the size of the range (always at least 1). In other words, the value
143489 ** ((C<<22) + N) represents a range of N codepoints starting with codepoint
143490 ** C. It is not possible to represent a range larger than 1023 codepoints
143491 ** using this format.
143492 */
143493 const static unsigned int aEntry[] = {
143494 0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07,
143495 0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01,
143496 0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401,
143497 0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01,
143498 0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163C01,
@@ -143580,11 +144403,11 @@
143580
143581 if( c<128 ){
143582 return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
143583 }else if( c<(1<<22) ){
143584 unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
143585 int iRes;
143586 int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
143587 int iLo = 0;
143588 while( iHi>=iLo ){
143589 int iTest = (iHi + iLo) / 2;
143590 if( key >= aEntry[iTest] ){
@@ -143651,11 +144474,11 @@
143651 iHi = iTest-1;
143652 }
143653 }
143654 assert( key>=aDia[iRes] );
143655 return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
143656 };
143657
143658
143659 /*
143660 ** Return true if the argument interpreted as a unicode codepoint
143661 ** is a diacritical modifier character.
@@ -143811,11 +144634,11 @@
143811 }
143812
143813 return ret;
143814 }
143815 #endif /* defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) */
143816 #endif /* !defined(SQLITE_ENABLE_FTS4_UNICODE61) */
143817
143818 /************** End of fts3_unicode2.c ***************************************/
143819 /************** Begin file rtree.c *******************************************/
143820 /*
143821 ** 2001 September 15
@@ -145348,13 +146171,17 @@
145348 int rc = SQLITE_OK;
145349 int iCell = 0;
145350
145351 rtreeReference(pRtree);
145352
 
145353 freeCursorConstraints(pCsr);
 
 
 
 
145354 pCsr->iStrategy = idxNum;
145355
145356 if( idxNum==1 ){
145357 /* Special case - lookup by rowid. */
145358 RtreeNode *pLeaf; /* Leaf on which the required cell resides */
145359 RtreeSearchPoint *p; /* Search point for the the leaf */
145360 i64 iRowid = sqlite3_value_int64(argv[0]);
145361
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -222,11 +222,11 @@
222 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
223 ** [sqlite_version()] and [sqlite_source_id()].
224 */
225 #define SQLITE_VERSION "3.8.6"
226 #define SQLITE_VERSION_NUMBER 3008006
227 #define SQLITE_SOURCE_ID "2014-08-12 16:13:37 6715991296886c2a02b9a285a1e61189ad1f79c0"
228
229 /*
230 ** CAPI3REF: Run-Time Library Version Numbers
231 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
232 **
@@ -382,19 +382,19 @@
382 /*
383 ** CAPI3REF: Closing A Database Connection
384 **
385 ** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
386 ** for the [sqlite3] object.
387 ** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
388 ** the [sqlite3] object is successfully destroyed and all associated
389 ** resources are deallocated.
390 **
391 ** ^If the database connection is associated with unfinalized prepared
392 ** statements or unfinished sqlite3_backup objects then sqlite3_close()
393 ** will leave the database connection open and return [SQLITE_BUSY].
394 ** ^If sqlite3_close_v2() is called with unfinalized prepared statements
395 ** and/or unfinished sqlite3_backups, then the database connection becomes
396 ** an unusable "zombie" which will automatically be deallocated when the
397 ** last prepared statement is finalized or the last sqlite3_backup is
398 ** finished. The sqlite3_close_v2() interface is intended for use with
399 ** host languages that are garbage collected, and where the order in which
400 ** destructors are called is arbitrary.
@@ -403,11 +403,11 @@
403 ** [sqlite3_blob_close | close] all [BLOB handles], and
404 ** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
405 ** with the [sqlite3] object prior to attempting to close the object. ^If
406 ** sqlite3_close_v2() is called on a [database connection] that still has
407 ** outstanding [prepared statements], [BLOB handles], and/or
408 ** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
409 ** of resources is deferred until all [prepared statements], [BLOB handles],
410 ** and [sqlite3_backup] objects are also destroyed.
411 **
412 ** ^If an [sqlite3] object is destroyed while a transaction is open,
413 ** the transaction is automatically rolled back.
@@ -499,20 +499,18 @@
499 char **errmsg /* Error msg written here */
500 );
501
502 /*
503 ** CAPI3REF: Result Codes
504 ** KEYWORDS: {result code definitions}
 
505 **
506 ** Many SQLite functions return an integer result code from the set shown
507 ** here in order to indicate success or failure.
508 **
509 ** New error codes may be added in future versions of SQLite.
510 **
511 ** See also: [extended result code definitions]
 
512 */
513 #define SQLITE_OK 0 /* Successful result */
514 /* beginning-of-error-codes */
515 #define SQLITE_ERROR 1 /* SQL error or missing database */
516 #define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
@@ -546,30 +544,23 @@
544 #define SQLITE_DONE 101 /* sqlite3_step() has finished executing */
545 /* end-of-error-codes */
546
547 /*
548 ** CAPI3REF: Extended Result Codes
549 ** KEYWORDS: {extended result code definitions}
 
550 **
551 ** In its default configuration, SQLite API routines return one of 30 integer
552 ** [result codes]. However, experience has shown that many of
553 ** these result codes are too coarse-grained. They do not provide as
554 ** much information about problems as programmers might like. In an effort to
555 ** address this, newer versions of SQLite (version 3.3.8 and later) include
556 ** support for additional result codes that provide more detailed information
557 ** about errors. These [extended result codes] are enabled or disabled
558 ** on a per database connection basis using the
559 ** [sqlite3_extended_result_codes()] API. Or, the extended code for
560 ** the most recent error can be obtained using
561 ** [sqlite3_extended_errcode()].
 
 
 
 
 
 
562 */
563 #define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
564 #define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
565 #define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8))
566 #define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8))
@@ -798,11 +789,11 @@
789 ** write return values. Potential uses for xFileControl() might be
790 ** functions to enable blocking locks with timeouts, to change the
791 ** locking strategy (for example to use dot-file locks), to inquire
792 ** about the status of a lock, or to break stale locks. The SQLite
793 ** core reserves all opcodes less than 100 for its own use.
794 ** A [file control opcodes | list of opcodes] less than 100 is available.
795 ** Applications that define a custom xFileControl method should use opcodes
796 ** greater than 100 to avoid conflicts. VFS implementations should
797 ** return [SQLITE_NOTFOUND] for file control opcodes that they do not
798 ** recognize.
799 **
@@ -871,10 +862,11 @@
862 /* Additional methods may be added in future releases */
863 };
864
865 /*
866 ** CAPI3REF: Standard File Control Opcodes
867 ** KEYWORDS: {file control opcodes} {file control opcode}
868 **
869 ** These integer constants are opcodes for the xFileControl method
870 ** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
871 ** interface.
872 **
@@ -2150,31 +2142,37 @@
2142 SQLITE_API int sqlite3_complete16(const void *sql);
2143
2144 /*
2145 ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
2146 **
2147 ** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
2148 ** that might be invoked with argument P whenever
2149 ** an attempt is made to access a database table associated with
2150 ** [database connection] D when another thread
2151 ** or process has the table locked.
2152 ** The sqlite3_busy_handler() interface is used to implement
2153 ** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout].
2154 **
2155 ** ^If the busy callback is NULL, then [SQLITE_BUSY]
2156 ** is returned immediately upon encountering the lock. ^If the busy callback
2157 ** is not NULL, then the callback might be invoked with two arguments.
2158 **
2159 ** ^The first argument to the busy handler is a copy of the void* pointer which
2160 ** is the third argument to sqlite3_busy_handler(). ^The second argument to
2161 ** the busy handler callback is the number of times that the busy handler has
2162 ** been invoked for the same locking event. ^If the
2163 ** busy callback returns 0, then no additional attempts are made to
2164 ** access the database and [SQLITE_BUSY] is returned
2165 ** to the application.
2166 ** ^If the callback returns non-zero, then another attempt
2167 ** is made to access the database and the cycle repeats.
2168 **
2169 ** The presence of a busy handler does not guarantee that it will be invoked
2170 ** when there is lock contention. ^If SQLite determines that invoking the busy
2171 ** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY]
2172 ** to the application instead of invoking the
2173 ** busy handler.
2174 ** Consider a scenario where one process is holding a read lock that
2175 ** it is trying to promote to a reserved lock and
2176 ** a second process is holding a reserved lock that it is trying
2177 ** to promote to an exclusive lock. The first process cannot proceed
2178 ** because it is blocked by the second and the second process cannot
@@ -2184,32 +2182,19 @@
2182 ** will induce the first process to release its read lock and allow
2183 ** the second process to proceed.
2184 **
2185 ** ^The default busy callback is NULL.
2186 **
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2187 ** ^(There can only be a single busy handler defined for each
2188 ** [database connection]. Setting a new busy handler clears any
2189 ** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()]
2190 ** or evaluating [PRAGMA busy_timeout=N] will change the
2191 ** busy handler and thus clear any previously set busy handler.
2192 **
2193 ** The busy callback should not take any actions which modify the
2194 ** database connection that invoked the busy handler. In other words,
2195 ** the busy handler is not reentrant. Any such actions
2196 ** result in undefined behavior.
2197 **
2198 ** A busy handler must not close the database connection
2199 ** or [prepared statement] that invoked the busy handler.
2200 */
@@ -2221,19 +2206,21 @@
2206 ** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps
2207 ** for a specified amount of time when a table is locked. ^The handler
2208 ** will sleep multiple times until at least "ms" milliseconds of sleeping
2209 ** have accumulated. ^After at least "ms" milliseconds of sleeping,
2210 ** the handler returns 0 which causes [sqlite3_step()] to return
2211 ** [SQLITE_BUSY].
2212 **
2213 ** ^Calling this routine with an argument less than or equal to zero
2214 ** turns off all busy handlers.
2215 **
2216 ** ^(There can only be a single busy handler for a particular
2217 ** [database connection] any any given moment. If another busy handler
2218 ** was defined (using [sqlite3_busy_handler()]) prior to calling
2219 ** this routine, that other busy handler is cleared.)^
2220 **
2221 ** See also: [PRAGMA busy_timeout]
2222 */
2223 SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
2224
2225 /*
2226 ** CAPI3REF: Convenience Routines For Running Queries
@@ -2631,12 +2618,12 @@
2618 ** return either [SQLITE_OK] or one of these two constants in order
2619 ** to signal SQLite whether or not the action is permitted. See the
2620 ** [sqlite3_set_authorizer | authorizer documentation] for additional
2621 ** information.
2622 **
2623 ** Note that SQLITE_IGNORE is also used as a [conflict resolution mode]
2624 ** returned from the [sqlite3_vtab_on_conflict()] interface.
2625 */
2626 #define SQLITE_DENY 1 /* Abort the SQL statement with an error */
2627 #define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
2628
2629 /*
@@ -4818,10 +4805,17 @@
4805 ** the name of a folder (a.k.a. directory), then all temporary files
4806 ** created by SQLite when using a built-in [sqlite3_vfs | VFS]
4807 ** will be placed in that directory.)^ ^If this variable
4808 ** is a NULL pointer, then SQLite performs a search for an appropriate
4809 ** temporary file directory.
4810 **
4811 ** Applications are strongly discouraged from using this global variable.
4812 ** It is required to set a temporary folder on Windows Runtime (WinRT).
4813 ** But for all other platforms, it is highly recommended that applications
4814 ** neither read nor write this variable. This global variable is a relic
4815 ** that exists for backwards compatibility of legacy applications and should
4816 ** be avoided in new projects.
4817 **
4818 ** It is not safe to read or modify this variable in more than one
4819 ** thread at a time. It is not safe to read or modify this variable
4820 ** if a [database connection] is being used at the same time in a separate
4821 ** thread.
@@ -4837,10 +4831,15 @@
4831 ** [sqlite3_malloc] and the pragma may attempt to free that memory
4832 ** using [sqlite3_free].
4833 ** Hence, if this variable is modified directly, either it should be
4834 ** made NULL or made to point to memory obtained from [sqlite3_malloc]
4835 ** or else the use of the [temp_store_directory pragma] should be avoided.
4836 ** Except when requested by the [temp_store_directory pragma], SQLite
4837 ** does not free the memory that sqlite3_temp_directory points to. If
4838 ** the application wants that memory to be freed, it must do
4839 ** so itself, taking care to only do so after all [database connection]
4840 ** objects have been destroyed.
4841 **
4842 ** <b>Note to Windows Runtime users:</b> The temporary directory must be set
4843 ** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various
4844 ** features that require the use of temporary files may fail. Here is an
4845 ** example of how to do this using C++ with the Windows Runtime:
@@ -5971,14 +5970,16 @@
5970 ** <ul>
5971 ** <li> SQLITE_MUTEX_FAST
5972 ** <li> SQLITE_MUTEX_RECURSIVE
5973 ** <li> SQLITE_MUTEX_STATIC_MASTER
5974 ** <li> SQLITE_MUTEX_STATIC_MEM
5975 ** <li> SQLITE_MUTEX_STATIC_OPEN
5976 ** <li> SQLITE_MUTEX_STATIC_PRNG
5977 ** <li> SQLITE_MUTEX_STATIC_LRU
5978 ** <li> SQLITE_MUTEX_STATIC_PMEM
5979 ** <li> SQLITE_MUTEX_STATIC_APP1
5980 ** <li> SQLITE_MUTEX_STATIC_APP2
5981 ** </ul>)^
5982 **
5983 ** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
5984 ** cause sqlite3_mutex_alloc() to create
5985 ** a new mutex. ^The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
@@ -6178,10 +6179,13 @@
6179 #define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */
6180 #define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */
6181 #define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
6182 #define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */
6183 #define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */
6184 #define SQLITE_MUTEX_STATIC_APP1 8 /* For use by application */
6185 #define SQLITE_MUTEX_STATIC_APP2 9 /* For use by application */
6186 #define SQLITE_MUTEX_STATIC_APP3 10 /* For use by application */
6187
6188 /*
6189 ** CAPI3REF: Retrieve the mutex for a database connection
6190 **
6191 ** ^This interface returns a pointer the [sqlite3_mutex] object that
@@ -6273,11 +6277,12 @@
6277 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
6278 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19
6279 #define SQLITE_TESTCTRL_NEVER_CORRUPT 20
6280 #define SQLITE_TESTCTRL_VDBE_COVERAGE 21
6281 #define SQLITE_TESTCTRL_BYTEORDER 22
6282 #define SQLITE_TESTCTRL_ISINIT 23
6283 #define SQLITE_TESTCTRL_LAST 23
6284
6285 /*
6286 ** CAPI3REF: SQLite Runtime Status
6287 **
6288 ** ^This interface is used to retrieve runtime status information
@@ -7256,10 +7261,13 @@
7261 ** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism
7262 ** configured by this function.
7263 **
7264 ** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
7265 ** from SQL.
7266 **
7267 ** ^Checkpoints initiated by this mechanism are
7268 ** [sqlite3_wal_checkpoint_v2|PASSIVE].
7269 **
7270 ** ^Every new [database connection] defaults to having the auto-checkpoint
7271 ** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
7272 ** pages. The use of this interface
7273 ** is only necessary if the default setting is found to be suboptimal
@@ -7273,10 +7281,14 @@
7281 ** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X
7282 ** on [database connection] D to be [checkpointed]. ^If X is NULL or an
7283 ** empty string, then a checkpoint is run on all databases of
7284 ** connection D. ^If the database connection D is not in
7285 ** [WAL | write-ahead log mode] then this interface is a harmless no-op.
7286 ** ^The [sqlite3_wal_checkpoint(D,X)] interface initiates a
7287 ** [sqlite3_wal_checkpoint_v2|PASSIVE] checkpoint.
7288 ** Use the [sqlite3_wal_checkpoint_v2()] interface to get a FULL
7289 ** or RESET checkpoint.
7290 **
7291 ** ^The [wal_checkpoint pragma] can be used to invoke this interface
7292 ** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the
7293 ** [wal_autocheckpoint pragma] can be used to cause this interface to be
7294 ** run whenever the WAL reaches a certain size threshold.
@@ -7295,22 +7307,25 @@
7307 ** <dl>
7308 ** <dt>SQLITE_CHECKPOINT_PASSIVE<dd>
7309 ** Checkpoint as many frames as possible without waiting for any database
7310 ** readers or writers to finish. Sync the db file if all frames in the log
7311 ** are checkpointed. This mode is the same as calling
7312 ** sqlite3_wal_checkpoint(). The [sqlite3_busy_handler|busy-handler callback]
7313 ** is never invoked.
7314 **
7315 ** <dt>SQLITE_CHECKPOINT_FULL<dd>
7316 ** This mode blocks (it invokes the
7317 ** [sqlite3_busy_handler|busy-handler callback]) until there is no
7318 ** database writer and all readers are reading from the most recent database
7319 ** snapshot. It then checkpoints all frames in the log file and syncs the
7320 ** database file. This call blocks database writers while it is running,
7321 ** but not database readers.
7322 **
7323 ** <dt>SQLITE_CHECKPOINT_RESTART<dd>
7324 ** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after
7325 ** checkpointing the log file it blocks (calls the
7326 ** [sqlite3_busy_handler|busy-handler callback])
7327 ** until all readers are reading from the database file only. This ensures
7328 ** that the next client to write to the database file restarts the log file
7329 ** from the beginning. This call blocks database writers while it is running,
7330 ** but not database readers.
7331 ** </dl>
@@ -7444,10 +7459,11 @@
7459 */
7460 SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
7461
7462 /*
7463 ** CAPI3REF: Conflict resolution modes
7464 ** KEYWORDS: {conflict resolution mode}
7465 **
7466 ** These constants are returned by [sqlite3_vtab_on_conflict()] to
7467 ** inform a [virtual table] implementation what the [ON CONFLICT] mode
7468 ** is for the SQL statement being evaluated.
7469 **
@@ -9285,43 +9301,43 @@
9301 #define OP_Affinity 47 /* synopsis: affinity(r[P1@P2]) */
9302 #define OP_MakeRecord 48 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
9303 #define OP_Count 49 /* synopsis: r[P2]=count() */
9304 #define OP_ReadCookie 50
9305 #define OP_SetCookie 51
9306 #define OP_ReopenIdx 52 /* synopsis: root=P2 iDb=P3 */
9307 #define OP_OpenRead 53 /* synopsis: root=P2 iDb=P3 */
9308 #define OP_OpenWrite 54 /* synopsis: root=P2 iDb=P3 */
9309 #define OP_OpenAutoindex 55 /* synopsis: nColumn=P2 */
9310 #define OP_OpenEphemeral 56 /* synopsis: nColumn=P2 */
9311 #define OP_SorterOpen 57
9312 #define OP_OpenPseudo 58 /* synopsis: P3 columns in r[P2] */
9313 #define OP_Close 59
9314 #define OP_SeekLT 60 /* synopsis: key=r[P3@P4] */
9315 #define OP_SeekLE 61 /* synopsis: key=r[P3@P4] */
9316 #define OP_SeekGE 62 /* synopsis: key=r[P3@P4] */
9317 #define OP_SeekGT 63 /* synopsis: key=r[P3@P4] */
9318 #define OP_Seek 64 /* synopsis: intkey=r[P2] */
9319 #define OP_NoConflict 65 /* synopsis: key=r[P3@P4] */
9320 #define OP_NotFound 66 /* synopsis: key=r[P3@P4] */
9321 #define OP_Found 67 /* synopsis: key=r[P3@P4] */
9322 #define OP_NotExists 68 /* synopsis: intkey=r[P3] */
9323 #define OP_Sequence 69 /* synopsis: r[P2]=cursor[P1].ctr++ */
9324 #define OP_NewRowid 70 /* synopsis: r[P2]=rowid */
9325 #define OP_Or 71 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
9326 #define OP_And 72 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
9327 #define OP_Insert 73 /* synopsis: intkey=r[P3] data=r[P2] */
9328 #define OP_InsertInt 74 /* synopsis: intkey=P3 data=r[P2] */
9329 #define OP_Delete 75
9330 #define OP_IsNull 76 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
9331 #define OP_NotNull 77 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
9332 #define OP_Ne 78 /* same as TK_NE, synopsis: if r[P1]!=r[P3] goto P2 */
9333 #define OP_Eq 79 /* same as TK_EQ, synopsis: if r[P1]==r[P3] goto P2 */
9334 #define OP_Gt 80 /* same as TK_GT, synopsis: if r[P1]>r[P3] goto P2 */
9335 #define OP_Le 81 /* same as TK_LE, synopsis: if r[P1]<=r[P3] goto P2 */
9336 #define OP_Lt 82 /* same as TK_LT, synopsis: if r[P1]<r[P3] goto P2 */
9337 #define OP_Ge 83 /* same as TK_GE, synopsis: if r[P1]>=r[P3] goto P2 */
9338 #define OP_ResetCount 84
9339 #define OP_BitAnd 85 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
9340 #define OP_BitOr 86 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
9341 #define OP_ShiftLeft 87 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
9342 #define OP_ShiftRight 88 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
9343 #define OP_Add 89 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
@@ -9328,73 +9344,74 @@
9344 #define OP_Subtract 90 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
9345 #define OP_Multiply 91 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
9346 #define OP_Divide 92 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
9347 #define OP_Remainder 93 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
9348 #define OP_Concat 94 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
9349 #define OP_SorterCompare 95 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
9350 #define OP_BitNot 96 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */
9351 #define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */
9352 #define OP_SorterData 98 /* synopsis: r[P2]=data */
9353 #define OP_RowKey 99 /* synopsis: r[P2]=key */
9354 #define OP_RowData 100 /* synopsis: r[P2]=data */
9355 #define OP_Rowid 101 /* synopsis: r[P2]=rowid */
9356 #define OP_NullRow 102
9357 #define OP_Last 103
9358 #define OP_SorterSort 104
9359 #define OP_Sort 105
9360 #define OP_Rewind 106
9361 #define OP_SorterInsert 107
9362 #define OP_IdxInsert 108 /* synopsis: key=r[P2] */
9363 #define OP_IdxDelete 109 /* synopsis: key=r[P2@P3] */
9364 #define OP_IdxRowid 110 /* synopsis: r[P2]=rowid */
9365 #define OP_IdxLE 111 /* synopsis: key=r[P3@P4] */
9366 #define OP_IdxGT 112 /* synopsis: key=r[P3@P4] */
9367 #define OP_IdxLT 113 /* synopsis: key=r[P3@P4] */
9368 #define OP_IdxGE 114 /* synopsis: key=r[P3@P4] */
9369 #define OP_Destroy 115
9370 #define OP_Clear 116
9371 #define OP_ResetSorter 117
9372 #define OP_CreateIndex 118 /* synopsis: r[P2]=root iDb=P1 */
9373 #define OP_CreateTable 119 /* synopsis: r[P2]=root iDb=P1 */
9374 #define OP_ParseSchema 120
9375 #define OP_LoadAnalysis 121
9376 #define OP_DropTable 122
9377 #define OP_DropIndex 123
9378 #define OP_DropTrigger 124
9379 #define OP_IntegrityCk 125
9380 #define OP_RowSetAdd 126 /* synopsis: rowset(P1)=r[P2] */
9381 #define OP_RowSetRead 127 /* synopsis: r[P3]=rowset(P1) */
9382 #define OP_RowSetTest 128 /* synopsis: if r[P3] in rowset(P1) goto P2 */
9383 #define OP_Program 129
9384 #define OP_Param 130
9385 #define OP_FkCounter 131 /* synopsis: fkctr[P1]+=P2 */
9386 #define OP_FkIfZero 132 /* synopsis: if fkctr[P1]==0 goto P2 */
9387 #define OP_Real 133 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
9388 #define OP_MemMax 134 /* synopsis: r[P1]=max(r[P1],r[P2]) */
9389 #define OP_IfPos 135 /* synopsis: if r[P1]>0 goto P2 */
9390 #define OP_IfNeg 136 /* synopsis: r[P1]+=P3, if r[P1]<0 goto P2 */
9391 #define OP_IfZero 137 /* synopsis: r[P1]+=P3, if r[P1]==0 goto P2 */
9392 #define OP_AggFinal 138 /* synopsis: accum=r[P1] N=P2 */
9393 #define OP_IncrVacuum 139
9394 #define OP_Expire 140
9395 #define OP_TableLock 141 /* synopsis: iDb=P1 root=P2 write=P3 */
9396 #define OP_VBegin 142
9397 #define OP_ToText 143 /* same as TK_TO_TEXT */
9398 #define OP_ToBlob 144 /* same as TK_TO_BLOB */
9399 #define OP_ToNumeric 145 /* same as TK_TO_NUMERIC */
9400 #define OP_ToInt 146 /* same as TK_TO_INT */
9401 #define OP_ToReal 147 /* same as TK_TO_REAL */
9402 #define OP_VCreate 148
9403 #define OP_VDestroy 149
9404 #define OP_VOpen 150
9405 #define OP_VColumn 151 /* synopsis: r[P3]=vcolumn(P2) */
9406 #define OP_VNext 152
9407 #define OP_VRename 153
9408 #define OP_Pagecount 154
9409 #define OP_MaxPgcnt 155
9410 #define OP_Init 156 /* synopsis: Start at P2 */
9411 #define OP_Noop 157
9412 #define OP_Explain 158
9413
9414
9415 /* Properties such as "out2" or "jump" that are specified in
9416 ** comments following the "case" for each opcode in the vdbe.c
9417 ** are encoded into bitvectors as follows:
@@ -9412,23 +9429,23 @@
9429 /* 16 */ 0x01, 0x01, 0x04, 0x24, 0x01, 0x04, 0x05, 0x10,\
9430 /* 24 */ 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,\
9431 /* 32 */ 0x00, 0x00, 0x20, 0x00, 0x00, 0x04, 0x05, 0x04,\
9432 /* 40 */ 0x00, 0x00, 0x01, 0x01, 0x05, 0x05, 0x00, 0x00,\
9433 /* 48 */ 0x00, 0x02, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00,\
9434 /* 56 */ 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11,\
9435 /* 64 */ 0x08, 0x11, 0x11, 0x11, 0x11, 0x02, 0x02, 0x4c,\
9436 /* 72 */ 0x4c, 0x00, 0x00, 0x00, 0x05, 0x05, 0x15, 0x15,\
9437 /* 80 */ 0x15, 0x15, 0x15, 0x15, 0x00, 0x4c, 0x4c, 0x4c,\
9438 /* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00,\
9439 /* 96 */ 0x24, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01,\
9440 /* 104 */ 0x01, 0x01, 0x01, 0x08, 0x08, 0x00, 0x02, 0x01,\
9441 /* 112 */ 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02,\
9442 /* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x45,\
9443 /* 128 */ 0x15, 0x01, 0x02, 0x00, 0x01, 0x02, 0x08, 0x05,\
9444 /* 136 */ 0x05, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04,\
9445 /* 144 */ 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,\
9446 /* 152 */ 0x01, 0x00, 0x02, 0x02, 0x01, 0x00, 0x00,}
9447
9448 /************** End of opcodes.h *********************************************/
9449 /************** Continuing where we left off in vdbe.h ***********************/
9450
9451 /*
@@ -10331,22 +10348,22 @@
10348 Hash trigHash; /* All triggers indexed by name */
10349 Hash fkeyHash; /* All foreign keys by referenced table name */
10350 Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */
10351 u8 file_format; /* Schema format version for this file */
10352 u8 enc; /* Text encoding used by this database */
10353 u16 schemaFlags; /* Flags associated with this schema */
10354 int cache_size; /* Number of pages to use in the cache */
10355 };
10356
10357 /*
10358 ** These macros can be used to test, set, or clear bits in the
10359 ** Db.pSchema->flags field.
10360 */
10361 #define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->schemaFlags&(P))==(P))
10362 #define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->schemaFlags&(P))!=0)
10363 #define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->schemaFlags|=(P)
10364 #define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->schemaFlags&=~(P)
10365
10366 /*
10367 ** Allowed values for the DB.pSchema->flags field.
10368 **
10369 ** The DB_SchemaLoaded flag is set after the database schema has been
@@ -10932,10 +10949,13 @@
10949 int tnum; /* Root BTree node for this table (see note above) */
10950 i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */
10951 i16 nCol; /* Number of columns in this table */
10952 u16 nRef; /* Number of pointers to this Table */
10953 LogEst szTabRow; /* Estimated size of each table row in bytes */
10954 #ifdef SQLITE_ENABLE_COSTMULT
10955 LogEst costMult; /* Cost multiplier for using this table */
10956 #endif
10957 u8 tabFlags; /* Mask of TF_* values */
10958 u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
10959 #ifndef SQLITE_OMIT_ALTERTABLE
10960 int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
10961 #endif
@@ -11172,10 +11192,13 @@
11192 #define SQLITE_IDXTYPE_PRIMARYKEY 2 /* Is the PRIMARY KEY for the table */
11193
11194 /* Return true if index X is a PRIMARY KEY index */
11195 #define IsPrimaryKeyIndex(X) ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY)
11196
11197 /* Return true if index X is a UNIQUE index */
11198 #define IsUniqueIndex(X) ((X)->onError!=OE_None)
11199
11200 /*
11201 ** Each sample stored in the sqlite_stat3 table is represented in memory
11202 ** using a structure of this type. See documentation at the top of the
11203 ** analyze.c source file for additional information.
11204 */
@@ -11591,10 +11614,11 @@
11614 #define WHERE_AND_ONLY 0x0080 /* Don't use indices for OR terms */
11615 #define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */
11616 #define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
11617 #define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
11618 #define WHERE_SORTBYGROUP 0x0800 /* Support sqlite3WhereIsSorted() */
11619 #define WHERE_REOPEN_IDX 0x1000 /* Try to use OP_ReopenIdx */
11620
11621 /* Allowed return values from sqlite3WhereIsDistinct()
11622 */
11623 #define WHERE_DISTINCT_NOOP 0 /* DISTINCT keyword not used */
11624 #define WHERE_DISTINCT_UNIQUE 1 /* No duplicates */
@@ -11847,13 +11871,23 @@
11871
11872 /*
11873 ** The yDbMask datatype for the bitmask of all attached databases.
11874 */
11875 #if SQLITE_MAX_ATTACHED>30
11876 typedef unsigned char yDbMask[(SQLITE_MAX_ATTACHED+9)/8];
11877 # define DbMaskTest(M,I) (((M)[(I)/8]&(1<<((I)&7)))!=0)
11878 # define DbMaskZero(M) memset((M),0,sizeof(M))
11879 # define DbMaskSet(M,I) (M)[(I)/8]|=(1<<((I)&7))
11880 # define DbMaskAllZero(M) sqlite3DbMaskAllZero(M)
11881 # define DbMaskNonZero(M) (sqlite3DbMaskAllZero(M)==0)
11882 #else
11883 typedef unsigned int yDbMask;
11884 # define DbMaskTest(M,I) (((M)&(((yDbMask)1)<<(I)))!=0)
11885 # define DbMaskZero(M) (M)=0
11886 # define DbMaskSet(M,I) (M)|=(((yDbMask)1)<<(I))
11887 # define DbMaskAllZero(M) (M)==0
11888 # define DbMaskNonZero(M) (M)!=0
11889 #endif
11890
11891 /*
11892 ** An SQL parser context. A copy of this structure is passed through
11893 ** the parser and down into all the parser action routine in order to
@@ -12522,10 +12556,13 @@
12556 SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse*,Table*);
12557 #else
12558 # define sqlite3ViewGetColumnNames(A,B) 0
12559 #endif
12560
12561 #if SQLITE_MAX_ATTACHED>30
12562 SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask);
12563 #endif
12564 SQLITE_PRIVATE void sqlite3DropTable(Parse*, SrcList*, int, int);
12565 SQLITE_PRIVATE void sqlite3CodeDropTable(Parse*, Table*, int, int);
12566 SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3*, Table*);
12567 #ifndef SQLITE_OMIT_AUTOINCREMENT
12568 SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse);
@@ -12772,10 +12809,11 @@
12809 SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe*, Table*, int);
12810 SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2);
12811 SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
12812 SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr);
12813 SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8);
12814 SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char*, i64*);
12815 SQLITE_PRIVATE void sqlite3Error(sqlite3*, int, const char*,...);
12816 SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
12817 SQLITE_PRIVATE u8 sqlite3HexToInt(int h);
12818 SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
12819
@@ -12801,11 +12839,11 @@
12839 #ifdef SQLITE_ENABLE_8_3_NAMES
12840 SQLITE_PRIVATE void sqlite3FileSuffix3(const char*, char*);
12841 #else
12842 # define sqlite3FileSuffix3(X,Y)
12843 #endif
12844 SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z,u8);
12845
12846 SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8);
12847 SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8);
12848 SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
12849 void(*)(void*));
@@ -13025,15 +13063,25 @@
13063 #else
13064 #define sqlite3BeginBenignMalloc()
13065 #define sqlite3EndBenignMalloc()
13066 #endif
13067
13068 /*
13069 ** Allowed return values from sqlite3FindInIndex()
13070 */
13071 #define IN_INDEX_ROWID 1 /* Search the rowid of the table */
13072 #define IN_INDEX_EPH 2 /* Search an ephemeral b-tree */
13073 #define IN_INDEX_INDEX_ASC 3 /* Existing index ASCENDING */
13074 #define IN_INDEX_INDEX_DESC 4 /* Existing index DESCENDING */
13075 #define IN_INDEX_NOOP 5 /* No table available. Use comparisons */
13076 /*
13077 ** Allowed flags for the 3rd parameter to sqlite3FindInIndex().
13078 */
13079 #define IN_INDEX_NOOP_OK 0x0001 /* OK to return IN_INDEX_NOOP */
13080 #define IN_INDEX_MEMBERSHIP 0x0002 /* IN operator used for membership test */
13081 #define IN_INDEX_LOOP 0x0004 /* IN operator used as a loop */
13082 SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, u32, int*);
13083
13084 #ifdef SQLITE_ENABLE_ATOMIC_WRITE
13085 SQLITE_PRIVATE int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
13086 SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *);
13087 SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *);
@@ -13876,18 +13924,22 @@
13924 KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
13925 int seekResult; /* Result of previous sqlite3BtreeMoveto() */
13926 int pseudoTableReg; /* Register holding pseudotable content. */
13927 i16 nField; /* Number of fields in the header */
13928 u16 nHdrParsed; /* Number of header fields parsed so far */
13929 #ifdef SQLITE_DEBUG
13930 u8 seekOp; /* Most recent seek operation on this cursor */
13931 #endif
13932 i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */
13933 u8 nullRow; /* True if pointing to a row with no data */
13934 u8 rowidIsValid; /* True if lastRowid is valid */
13935 u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
13936 Bool isEphemeral:1; /* True for an ephemeral table */
13937 Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */
13938 Bool isTable:1; /* True if a table requiring integer keys */
13939 Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */
13940 Pgno pgnoRoot; /* Root page of the open btree cursor */
13941 sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
13942 i64 seqCount; /* Sequence counter */
13943 i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
13944 i64 lastRowid; /* Rowid being deleted by OP_Delete */
13945 VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */
@@ -18396,11 +18448,11 @@
18448 /*
18449 ** Retrieve a pointer to a static mutex or allocate a new dynamic one.
18450 */
18451 SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int id){
18452 #ifndef SQLITE_OMIT_AUTOINIT
18453 if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0;
18454 #endif
18455 return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
18456 }
18457
18458 SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int id){
@@ -18577,11 +18629,11 @@
18629 ** The sqlite3_mutex_alloc() routine allocates a new
18630 ** mutex and returns a pointer to it. If it returns NULL
18631 ** that means that a mutex could not be allocated.
18632 */
18633 static sqlite3_mutex *debugMutexAlloc(int id){
18634 static sqlite3_debug_mutex aStatic[SQLITE_MUTEX_STATIC_APP3 - 1];
18635 sqlite3_debug_mutex *pNew = 0;
18636 switch( id ){
18637 case SQLITE_MUTEX_FAST:
18638 case SQLITE_MUTEX_RECURSIVE: {
18639 pNew = sqlite3Malloc(sizeof(*pNew));
@@ -18774,14 +18826,17 @@
18826 ** <ul>
18827 ** <li> SQLITE_MUTEX_FAST
18828 ** <li> SQLITE_MUTEX_RECURSIVE
18829 ** <li> SQLITE_MUTEX_STATIC_MASTER
18830 ** <li> SQLITE_MUTEX_STATIC_MEM
18831 ** <li> SQLITE_MUTEX_STATIC_OPEN
18832 ** <li> SQLITE_MUTEX_STATIC_PRNG
18833 ** <li> SQLITE_MUTEX_STATIC_LRU
18834 ** <li> SQLITE_MUTEX_STATIC_PMEM
18835 ** <li> SQLITE_MUTEX_STATIC_APP1
18836 ** <li> SQLITE_MUTEX_STATIC_APP2
18837 ** <li> SQLITE_MUTEX_STATIC_APP3
18838 ** </ul>
18839 **
18840 ** The first two constants cause sqlite3_mutex_alloc() to create
18841 ** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
18842 ** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
@@ -18806,10 +18861,13 @@
18861 ** mutex types, the same mutex is returned on every call that has
18862 ** the same type number.
18863 */
18864 static sqlite3_mutex *pthreadMutexAlloc(int iType){
18865 static sqlite3_mutex staticMutexes[] = {
18866 SQLITE3_MUTEX_INITIALIZER,
18867 SQLITE3_MUTEX_INITIALIZER,
18868 SQLITE3_MUTEX_INITIALIZER,
18869 SQLITE3_MUTEX_INITIALIZER,
18870 SQLITE3_MUTEX_INITIALIZER,
18871 SQLITE3_MUTEX_INITIALIZER,
18872 SQLITE3_MUTEX_INITIALIZER,
18873 SQLITE3_MUTEX_INITIALIZER,
@@ -19041,14 +19099,227 @@
19099 ** May you do good and not evil.
19100 ** May you find forgiveness for yourself and forgive others.
19101 ** May you share freely, never taking more than you give.
19102 **
19103 *************************************************************************
19104 ** This file contains the C functions that implement mutexes for Win32.
19105 */
19106
19107 #if SQLITE_OS_WIN
19108 /*
19109 ** Include code that is common to all os_*.c files
19110 */
19111 /************** Include os_common.h in the middle of mutex_w32.c *************/
19112 /************** Begin file os_common.h ***************************************/
19113 /*
19114 ** 2004 May 22
19115 **
19116 ** The author disclaims copyright to this source code. In place of
19117 ** a legal notice, here is a blessing:
19118 **
19119 ** May you do good and not evil.
19120 ** May you find forgiveness for yourself and forgive others.
19121 ** May you share freely, never taking more than you give.
19122 **
19123 ******************************************************************************
19124 **
19125 ** This file contains macros and a little bit of code that is common to
19126 ** all of the platform-specific files (os_*.c) and is #included into those
19127 ** files.
19128 **
19129 ** This file should be #included by the os_*.c files only. It is not a
19130 ** general purpose header file.
19131 */
19132 #ifndef _OS_COMMON_H_
19133 #define _OS_COMMON_H_
19134
19135 /*
19136 ** At least two bugs have slipped in because we changed the MEMORY_DEBUG
19137 ** macro to SQLITE_DEBUG and some older makefiles have not yet made the
19138 ** switch. The following code should catch this problem at compile-time.
19139 */
19140 #ifdef MEMORY_DEBUG
19141 # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
19142 #endif
19143
19144 #if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
19145 # ifndef SQLITE_DEBUG_OS_TRACE
19146 # define SQLITE_DEBUG_OS_TRACE 0
19147 # endif
19148 int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
19149 # define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
19150 #else
19151 # define OSTRACE(X)
19152 #endif
19153
19154 /*
19155 ** Macros for performance tracing. Normally turned off. Only works
19156 ** on i486 hardware.
19157 */
19158 #ifdef SQLITE_PERFORMANCE_TRACE
19159
19160 /*
19161 ** hwtime.h contains inline assembler code for implementing
19162 ** high-performance timing routines.
19163 */
19164 /************** Include hwtime.h in the middle of os_common.h ****************/
19165 /************** Begin file hwtime.h ******************************************/
19166 /*
19167 ** 2008 May 27
19168 **
19169 ** The author disclaims copyright to this source code. In place of
19170 ** a legal notice, here is a blessing:
19171 **
19172 ** May you do good and not evil.
19173 ** May you find forgiveness for yourself and forgive others.
19174 ** May you share freely, never taking more than you give.
19175 **
19176 ******************************************************************************
19177 **
19178 ** This file contains inline asm code for retrieving "high-performance"
19179 ** counters for x86 class CPUs.
19180 */
19181 #ifndef _HWTIME_H_
19182 #define _HWTIME_H_
19183
19184 /*
19185 ** The following routine only works on pentium-class (or newer) processors.
19186 ** It uses the RDTSC opcode to read the cycle count value out of the
19187 ** processor and returns that value. This can be used for high-res
19188 ** profiling.
19189 */
19190 #if (defined(__GNUC__) || defined(_MSC_VER)) && \
19191 (defined(i386) || defined(__i386__) || defined(_M_IX86))
19192
19193 #if defined(__GNUC__)
19194
19195 __inline__ sqlite_uint64 sqlite3Hwtime(void){
19196 unsigned int lo, hi;
19197 __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
19198 return (sqlite_uint64)hi << 32 | lo;
19199 }
19200
19201 #elif defined(_MSC_VER)
19202
19203 __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
19204 __asm {
19205 rdtsc
19206 ret ; return value at EDX:EAX
19207 }
19208 }
19209
19210 #endif
19211
19212 #elif (defined(__GNUC__) && defined(__x86_64__))
19213
19214 __inline__ sqlite_uint64 sqlite3Hwtime(void){
19215 unsigned long val;
19216 __asm__ __volatile__ ("rdtsc" : "=A" (val));
19217 return val;
19218 }
19219
19220 #elif (defined(__GNUC__) && defined(__ppc__))
19221
19222 __inline__ sqlite_uint64 sqlite3Hwtime(void){
19223 unsigned long long retval;
19224 unsigned long junk;
19225 __asm__ __volatile__ ("\n\
19226 1: mftbu %1\n\
19227 mftb %L0\n\
19228 mftbu %0\n\
19229 cmpw %0,%1\n\
19230 bne 1b"
19231 : "=r" (retval), "=r" (junk));
19232 return retval;
19233 }
19234
19235 #else
19236
19237 #error Need implementation of sqlite3Hwtime() for your platform.
19238
19239 /*
19240 ** To compile without implementing sqlite3Hwtime() for your platform,
19241 ** you can remove the above #error and use the following
19242 ** stub function. You will lose timing support for many
19243 ** of the debugging and testing utilities, but it should at
19244 ** least compile and run.
19245 */
19246 SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
19247
19248 #endif
19249
19250 #endif /* !defined(_HWTIME_H_) */
19251
19252 /************** End of hwtime.h **********************************************/
19253 /************** Continuing where we left off in os_common.h ******************/
19254
19255 static sqlite_uint64 g_start;
19256 static sqlite_uint64 g_elapsed;
19257 #define TIMER_START g_start=sqlite3Hwtime()
19258 #define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
19259 #define TIMER_ELAPSED g_elapsed
19260 #else
19261 #define TIMER_START
19262 #define TIMER_END
19263 #define TIMER_ELAPSED ((sqlite_uint64)0)
19264 #endif
19265
19266 /*
19267 ** If we compile with the SQLITE_TEST macro set, then the following block
19268 ** of code will give us the ability to simulate a disk I/O error. This
19269 ** is used for testing the I/O recovery logic.
19270 */
19271 #ifdef SQLITE_TEST
19272 SQLITE_API int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */
19273 SQLITE_API int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */
19274 SQLITE_API int sqlite3_io_error_pending = 0; /* Count down to first I/O error */
19275 SQLITE_API int sqlite3_io_error_persist = 0; /* True if I/O errors persist */
19276 SQLITE_API int sqlite3_io_error_benign = 0; /* True if errors are benign */
19277 SQLITE_API int sqlite3_diskfull_pending = 0;
19278 SQLITE_API int sqlite3_diskfull = 0;
19279 #define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
19280 #define SimulateIOError(CODE) \
19281 if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
19282 || sqlite3_io_error_pending-- == 1 ) \
19283 { local_ioerr(); CODE; }
19284 static void local_ioerr(){
19285 IOTRACE(("IOERR\n"));
19286 sqlite3_io_error_hit++;
19287 if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
19288 }
19289 #define SimulateDiskfullError(CODE) \
19290 if( sqlite3_diskfull_pending ){ \
19291 if( sqlite3_diskfull_pending == 1 ){ \
19292 local_ioerr(); \
19293 sqlite3_diskfull = 1; \
19294 sqlite3_io_error_hit = 1; \
19295 CODE; \
19296 }else{ \
19297 sqlite3_diskfull_pending--; \
19298 } \
19299 }
19300 #else
19301 #define SimulateIOErrorBenign(X)
19302 #define SimulateIOError(A)
19303 #define SimulateDiskfullError(A)
19304 #endif
19305
19306 /*
19307 ** When testing, keep a count of the number of open files.
19308 */
19309 #ifdef SQLITE_TEST
19310 SQLITE_API int sqlite3_open_file_count = 0;
19311 #define OpenCounter(X) sqlite3_open_file_count+=(X)
19312 #else
19313 #define OpenCounter(X)
19314 #endif
19315
19316 #endif /* !defined(_OS_COMMON_H_) */
19317
19318 /************** End of os_common.h *******************************************/
19319 /************** Continuing where we left off in mutex_w32.c ******************/
19320
19321 /*
19322 ** Include the header file for the Windows VFS.
19323 */
19324 /************** Include os_win.h in the middle of mutex_w32.c ****************/
19325 /************** Begin file os_win.h ******************************************/
@@ -19124,11 +19395,11 @@
19395 /************** Continuing where we left off in mutex_w32.c ******************/
19396 #endif
19397
19398 /*
19399 ** The code in this file is only used if we are compiling multithreaded
19400 ** on a Win32 system.
19401 */
19402 #ifdef SQLITE_MUTEX_W32
19403
19404 /*
19405 ** Each recursive mutex is an instance of the following structure.
@@ -19137,94 +19408,75 @@
19408 CRITICAL_SECTION mutex; /* Mutex controlling the lock */
19409 int id; /* Mutex type */
19410 #ifdef SQLITE_DEBUG
19411 volatile int nRef; /* Number of enterances */
19412 volatile DWORD owner; /* Thread holding this mutex */
19413 volatile int trace; /* True to trace changes */
19414 #endif
19415 };
19416
19417 /*
19418 ** These are the initializer values used when declaring a "static" mutex
19419 ** on Win32. It should be noted that all mutexes require initialization
19420 ** on the Win32 platform.
19421 */
19422 #define SQLITE_W32_MUTEX_INITIALIZER { 0 }
19423
19424 #ifdef SQLITE_DEBUG
19425 #define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, \
19426 0L, (DWORD)0, 0 }
19427 #else
19428 #define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 }
19429 #endif
19430
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19431 #ifdef SQLITE_DEBUG
19432 /*
19433 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
19434 ** intended for use only inside assert() statements.
19435 */
19436 static int winMutexHeld(sqlite3_mutex *p){
19437 return p->nRef!=0 && p->owner==GetCurrentThreadId();
19438 }
19439
19440 static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){
19441 return p->nRef==0 || p->owner!=tid;
19442 }
19443
19444 static int winMutexNotheld(sqlite3_mutex *p){
19445 DWORD tid = GetCurrentThreadId();
19446 return winMutexNotheld2(p, tid);
19447 }
19448 #endif
19449
 
19450 /*
19451 ** Initialize and deinitialize the mutex subsystem.
19452 */
19453 static sqlite3_mutex winMutex_staticMutexes[] = {
19454 SQLITE3_MUTEX_INITIALIZER,
19455 SQLITE3_MUTEX_INITIALIZER,
19456 SQLITE3_MUTEX_INITIALIZER,
19457 SQLITE3_MUTEX_INITIALIZER,
19458 SQLITE3_MUTEX_INITIALIZER,
19459 SQLITE3_MUTEX_INITIALIZER,
19460 SQLITE3_MUTEX_INITIALIZER,
19461 SQLITE3_MUTEX_INITIALIZER,
19462 SQLITE3_MUTEX_INITIALIZER
19463 };
19464
19465 static int winMutex_isInit = 0;
19466 static int winMutex_isNt = -1; /* <0 means "need to query" */
19467
19468 /* As the winMutexInit() and winMutexEnd() functions are called as part
19469 ** of the sqlite3_initialize() and sqlite3_shutdown() processing, the
19470 ** "interlocked" magic used here is probably not strictly necessary.
19471 */
19472 static LONG volatile winMutex_lock = 0;
19473
19474 SQLITE_API int sqlite3_win32_is_nt(void); /* os_win.c */
19475 SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
19476
19477 static int winMutexInit(void){
19478 /* The first to increment to 1 does actual initialization */
19479 if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
19480 int i;
19481 for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
19482 #if SQLITE_OS_WINRT
@@ -19233,20 +19485,21 @@
19485 InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);
19486 #endif
19487 }
19488 winMutex_isInit = 1;
19489 }else{
19490 /* Another thread is (in the process of) initializing the static
19491 ** mutexes */
19492 while( !winMutex_isInit ){
19493 sqlite3_win32_sleep(1);
19494 }
19495 }
19496 return SQLITE_OK;
19497 }
19498
19499 static int winMutexEnd(void){
19500 /* The first to decrement to 0 does actual shutdown
19501 ** (which should be the last to shutdown.) */
19502 if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){
19503 if( winMutex_isInit==1 ){
19504 int i;
19505 for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
@@ -19253,11 +19506,11 @@
19506 DeleteCriticalSection(&winMutex_staticMutexes[i].mutex);
19507 }
19508 winMutex_isInit = 0;
19509 }
19510 }
19511 return SQLITE_OK;
19512 }
19513
19514 /*
19515 ** The sqlite3_mutex_alloc() routine allocates a new
19516 ** mutex and returns a pointer to it. If it returns NULL
@@ -19268,14 +19521,17 @@
19521 ** <ul>
19522 ** <li> SQLITE_MUTEX_FAST
19523 ** <li> SQLITE_MUTEX_RECURSIVE
19524 ** <li> SQLITE_MUTEX_STATIC_MASTER
19525 ** <li> SQLITE_MUTEX_STATIC_MEM
19526 ** <li> SQLITE_MUTEX_STATIC_OPEN
19527 ** <li> SQLITE_MUTEX_STATIC_PRNG
19528 ** <li> SQLITE_MUTEX_STATIC_LRU
19529 ** <li> SQLITE_MUTEX_STATIC_PMEM
19530 ** <li> SQLITE_MUTEX_STATIC_APP1
19531 ** <li> SQLITE_MUTEX_STATIC_APP2
19532 ** <li> SQLITE_MUTEX_STATIC_APP3
19533 ** </ul>
19534 **
19535 ** The first two constants cause sqlite3_mutex_alloc() to create
19536 ** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
19537 ** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
@@ -19294,11 +19550,11 @@
19550 ** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
19551 ** SQLITE_MUTEX_RECURSIVE.
19552 **
19553 ** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
19554 ** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
19555 ** returns a different mutex on every call. But for the static
19556 ** mutex types, the same mutex is returned on every call that has
19557 ** the same type number.
19558 */
19559 static sqlite3_mutex *winMutexAlloc(int iType){
19560 sqlite3_mutex *p;
@@ -19305,13 +19561,16 @@
19561
19562 switch( iType ){
19563 case SQLITE_MUTEX_FAST:
19564 case SQLITE_MUTEX_RECURSIVE: {
19565 p = sqlite3MallocZero( sizeof(*p) );
19566 if( p ){
19567 #ifdef SQLITE_DEBUG
19568 p->id = iType;
19569 #ifdef SQLITE_WIN32_MUTEX_TRACE_DYNAMIC
19570 p->trace = 1;
19571 #endif
19572 #endif
19573 #if SQLITE_OS_WINRT
19574 InitializeCriticalSectionEx(&p->mutex, 0, 0);
19575 #else
19576 InitializeCriticalSection(&p->mutex);
@@ -19318,16 +19577,19 @@
19577 #endif
19578 }
19579 break;
19580 }
19581 default: {
 
19582 assert( iType-2 >= 0 );
19583 assert( iType-2 < ArraySize(winMutex_staticMutexes) );
19584 assert( winMutex_isInit==1 );
19585 p = &winMutex_staticMutexes[iType-2];
19586 #ifdef SQLITE_DEBUG
19587 p->id = iType;
19588 #ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC
19589 p->trace = 1;
19590 #endif
19591 #endif
19592 break;
19593 }
19594 }
19595 return p;
@@ -19339,12 +19601,15 @@
19601 ** allocated mutex. SQLite is careful to deallocate every
19602 ** mutex that it allocates.
19603 */
19604 static void winMutexFree(sqlite3_mutex *p){
19605 assert( p );
19606 #ifdef SQLITE_DEBUG
19607 assert( p->nRef==0 && p->owner==0 );
19608 assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
19609 #endif
19610 assert( winMutex_isInit==1 );
19611 DeleteCriticalSection(&p->mutex);
19612 sqlite3_free(p);
19613 }
19614
19615 /*
@@ -19357,53 +19622,71 @@
19622 ** mutex must be exited an equal number of times before another thread
19623 ** can enter. If the same thread tries to enter any other kind of mutex
19624 ** more than once, the behavior is undefined.
19625 */
19626 static void winMutexEnter(sqlite3_mutex *p){
19627 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
19628 DWORD tid = GetCurrentThreadId();
19629 #endif
19630 #ifdef SQLITE_DEBUG
19631 assert( p );
19632 assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
19633 #else
19634 assert( p );
19635 #endif
19636 assert( winMutex_isInit==1 );
19637 EnterCriticalSection(&p->mutex);
19638 #ifdef SQLITE_DEBUG
19639 assert( p->nRef>0 || p->owner==0 );
19640 p->owner = tid;
19641 p->nRef++;
19642 if( p->trace ){
19643 OSTRACE(("ENTER-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n",
19644 tid, p, p->trace, p->nRef));
19645 }
19646 #endif
19647 }
19648
19649 static int winMutexTry(sqlite3_mutex *p){
19650 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
19651 DWORD tid = GetCurrentThreadId();
19652 #endif
19653 int rc = SQLITE_BUSY;
19654 assert( p );
19655 assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
19656 /*
19657 ** The sqlite3_mutex_try() routine is very rarely used, and when it
19658 ** is used it is merely an optimization. So it is OK for it to always
19659 ** fail.
19660 **
19661 ** The TryEnterCriticalSection() interface is only available on WinNT.
19662 ** And some windows compilers complain if you try to use it without
19663 ** first doing some #defines that prevent SQLite from building on Win98.
19664 ** For that reason, we will omit this optimization for now. See
19665 ** ticket #2685.
19666 */
19667 #if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400
19668 assert( winMutex_isInit==1 );
19669 assert( winMutex_isNt>=-1 && winMutex_isNt<=1 );
19670 if( winMutex_isNt<0 ){
19671 winMutex_isNt = sqlite3_win32_is_nt();
19672 }
19673 assert( winMutex_isNt==0 || winMutex_isNt==1 );
19674 if( winMutex_isNt && TryEnterCriticalSection(&p->mutex) ){
19675 #ifdef SQLITE_DEBUG
19676 p->owner = tid;
19677 p->nRef++;
19678 #endif
19679 rc = SQLITE_OK;
19680 }
19681 #else
19682 UNUSED_PARAMETER(p);
19683 #endif
19684 #ifdef SQLITE_DEBUG
19685 if( p->trace ){
19686 OSTRACE(("TRY-MUTEX tid=%lu, mutex=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
19687 tid, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc)));
19688 }
19689 #endif
19690 return rc;
19691 }
19692
@@ -19412,22 +19695,27 @@
19695 ** previously entered by the same thread. The behavior
19696 ** is undefined if the mutex is not currently entered or
19697 ** is not currently allocated. SQLite will never do either.
19698 */
19699 static void winMutexLeave(sqlite3_mutex *p){
19700 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
19701 DWORD tid = GetCurrentThreadId();
19702 #endif
19703 assert( p );
19704 #ifdef SQLITE_DEBUG
19705 assert( p->nRef>0 );
19706 assert( p->owner==tid );
19707 p->nRef--;
19708 if( p->nRef==0 ) p->owner = 0;
19709 assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
19710 #endif
19711 assert( winMutex_isInit==1 );
19712 LeaveCriticalSection(&p->mutex);
19713 #ifdef SQLITE_DEBUG
19714 if( p->trace ){
19715 OSTRACE(("LEAVE-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n",
19716 tid, p, p->trace, p->nRef));
19717 }
19718 #endif
19719 }
19720
19721 SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
@@ -19445,13 +19733,13 @@
19733 #else
19734 0,
19735 0
19736 #endif
19737 };
 
19738 return &sMutex;
19739 }
19740
19741 #endif /* SQLITE_MUTEX_W32 */
19742
19743 /************** End of mutex_w32.c *******************************************/
19744 /************** Begin file malloc.c ******************************************/
19745 /*
@@ -22422,13 +22710,13 @@
22710 testcase( c==(+1) );
22711 }
22712 return c;
22713 }
22714
 
22715 /*
22716 ** Convert zNum to a 64-bit signed integer. zNum must be decimal. This
22717 ** routine does *not* accept hexadecimal notation.
22718 **
22719 ** If the zNum value is representable as a 64-bit twos-complement
22720 ** integer, then write that value into *pNum and return 0.
22721 **
22722 ** If zNum is exactly 9223372036854775808, return 2. This special
@@ -22511,14 +22799,48 @@
22799 assert( u-1==LARGEST_INT64 );
22800 return neg ? 0 : 2;
22801 }
22802 }
22803 }
22804
22805 /*
22806 ** Transform a UTF-8 integer literal, in either decimal or hexadecimal,
22807 ** into a 64-bit signed integer. This routine accepts hexadecimal literals,
22808 ** whereas sqlite3Atoi64() does not.
22809 **
22810 ** Returns:
22811 **
22812 ** 0 Successful transformation. Fits in a 64-bit signed integer.
22813 ** 1 Integer too large for a 64-bit signed integer or is malformed
22814 ** 2 Special case of 9223372036854775808
22815 */
22816 SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
22817 #ifndef SQLITE_OMIT_HEX_INTEGER
22818 if( z[0]=='0'
22819 && (z[1]=='x' || z[1]=='X')
22820 && sqlite3Isxdigit(z[2])
22821 ){
22822 u64 u = 0;
22823 int i, k;
22824 for(i=2; z[i]=='0'; i++){}
22825 for(k=i; sqlite3Isxdigit(z[k]); k++){
22826 u = u*16 + sqlite3HexToInt(z[k]);
22827 }
22828 memcpy(pOut, &u, 8);
22829 return (z[k]==0 && k-i<=16) ? 0 : 1;
22830 }else
22831 #endif /* SQLITE_OMIT_HEX_INTEGER */
22832 {
22833 return sqlite3Atoi64(z, pOut, sqlite3Strlen30(z), SQLITE_UTF8);
22834 }
22835 }
22836
22837 /*
22838 ** If zNum represents an integer that will fit in 32-bits, then set
22839 ** *pValue to that integer and return true. Otherwise return false.
22840 **
22841 ** This routine accepts both decimal and hexadecimal notation for integers.
22842 **
22843 ** Any non-numeric characters that following zNum are ignored.
22844 ** This is different from sqlite3Atoi64() which requires the
22845 ** input number to be zero-terminated.
22846 */
@@ -22530,11 +22852,29 @@
22852 neg = 1;
22853 zNum++;
22854 }else if( zNum[0]=='+' ){
22855 zNum++;
22856 }
22857 #ifndef SQLITE_OMIT_HEX_INTEGER
22858 else if( zNum[0]=='0'
22859 && (zNum[1]=='x' || zNum[1]=='X')
22860 && sqlite3Isxdigit(zNum[2])
22861 ){
22862 u32 u = 0;
22863 zNum += 2;
22864 while( zNum[0]=='0' ) zNum++;
22865 for(i=0; sqlite3Isxdigit(zNum[i]) && i<8; i++){
22866 u = u*16 + sqlite3HexToInt(zNum[i]);
22867 }
22868 if( (u&0x80000000)==0 && sqlite3Isxdigit(zNum[i])==0 ){
22869 memcpy(pValue, &u, 4);
22870 return 1;
22871 }else{
22872 return 0;
22873 }
22874 }
22875 #endif
22876 for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){
22877 v = v*10 + c;
22878 }
22879
22880 /* The longest decimal representation of a 32 bit integer is 10 digits:
@@ -23606,43 +23946,43 @@
23946 /* 47 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
23947 /* 48 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
23948 /* 49 */ "Count" OpHelp("r[P2]=count()"),
23949 /* 50 */ "ReadCookie" OpHelp(""),
23950 /* 51 */ "SetCookie" OpHelp(""),
23951 /* 52 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
23952 /* 53 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
23953 /* 54 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
23954 /* 55 */ "OpenAutoindex" OpHelp("nColumn=P2"),
23955 /* 56 */ "OpenEphemeral" OpHelp("nColumn=P2"),
23956 /* 57 */ "SorterOpen" OpHelp(""),
23957 /* 58 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
23958 /* 59 */ "Close" OpHelp(""),
23959 /* 60 */ "SeekLT" OpHelp("key=r[P3@P4]"),
23960 /* 61 */ "SeekLE" OpHelp("key=r[P3@P4]"),
23961 /* 62 */ "SeekGE" OpHelp("key=r[P3@P4]"),
23962 /* 63 */ "SeekGT" OpHelp("key=r[P3@P4]"),
23963 /* 64 */ "Seek" OpHelp("intkey=r[P2]"),
23964 /* 65 */ "NoConflict" OpHelp("key=r[P3@P4]"),
23965 /* 66 */ "NotFound" OpHelp("key=r[P3@P4]"),
23966 /* 67 */ "Found" OpHelp("key=r[P3@P4]"),
23967 /* 68 */ "NotExists" OpHelp("intkey=r[P3]"),
23968 /* 69 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
23969 /* 70 */ "NewRowid" OpHelp("r[P2]=rowid"),
23970 /* 71 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"),
23971 /* 72 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"),
23972 /* 73 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
23973 /* 74 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"),
23974 /* 75 */ "Delete" OpHelp(""),
23975 /* 76 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
23976 /* 77 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
23977 /* 78 */ "Ne" OpHelp("if r[P1]!=r[P3] goto P2"),
23978 /* 79 */ "Eq" OpHelp("if r[P1]==r[P3] goto P2"),
23979 /* 80 */ "Gt" OpHelp("if r[P1]>r[P3] goto P2"),
23980 /* 81 */ "Le" OpHelp("if r[P1]<=r[P3] goto P2"),
23981 /* 82 */ "Lt" OpHelp("if r[P1]<r[P3] goto P2"),
23982 /* 83 */ "Ge" OpHelp("if r[P1]>=r[P3] goto P2"),
23983 /* 84 */ "ResetCount" OpHelp(""),
23984 /* 85 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
23985 /* 86 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
23986 /* 87 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
23987 /* 88 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
23988 /* 89 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
@@ -23649,73 +23989,74 @@
23989 /* 90 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
23990 /* 91 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
23991 /* 92 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
23992 /* 93 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
23993 /* 94 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
23994 /* 95 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
23995 /* 96 */ "BitNot" OpHelp("r[P1]= ~r[P1]"),
23996 /* 97 */ "String8" OpHelp("r[P2]='P4'"),
23997 /* 98 */ "SorterData" OpHelp("r[P2]=data"),
23998 /* 99 */ "RowKey" OpHelp("r[P2]=key"),
23999 /* 100 */ "RowData" OpHelp("r[P2]=data"),
24000 /* 101 */ "Rowid" OpHelp("r[P2]=rowid"),
24001 /* 102 */ "NullRow" OpHelp(""),
24002 /* 103 */ "Last" OpHelp(""),
24003 /* 104 */ "SorterSort" OpHelp(""),
24004 /* 105 */ "Sort" OpHelp(""),
24005 /* 106 */ "Rewind" OpHelp(""),
24006 /* 107 */ "SorterInsert" OpHelp(""),
24007 /* 108 */ "IdxInsert" OpHelp("key=r[P2]"),
24008 /* 109 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
24009 /* 110 */ "IdxRowid" OpHelp("r[P2]=rowid"),
24010 /* 111 */ "IdxLE" OpHelp("key=r[P3@P4]"),
24011 /* 112 */ "IdxGT" OpHelp("key=r[P3@P4]"),
24012 /* 113 */ "IdxLT" OpHelp("key=r[P3@P4]"),
24013 /* 114 */ "IdxGE" OpHelp("key=r[P3@P4]"),
24014 /* 115 */ "Destroy" OpHelp(""),
24015 /* 116 */ "Clear" OpHelp(""),
24016 /* 117 */ "ResetSorter" OpHelp(""),
24017 /* 118 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"),
24018 /* 119 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"),
24019 /* 120 */ "ParseSchema" OpHelp(""),
24020 /* 121 */ "LoadAnalysis" OpHelp(""),
24021 /* 122 */ "DropTable" OpHelp(""),
24022 /* 123 */ "DropIndex" OpHelp(""),
24023 /* 124 */ "DropTrigger" OpHelp(""),
24024 /* 125 */ "IntegrityCk" OpHelp(""),
24025 /* 126 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
24026 /* 127 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
24027 /* 128 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
24028 /* 129 */ "Program" OpHelp(""),
24029 /* 130 */ "Param" OpHelp(""),
24030 /* 131 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
24031 /* 132 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
24032 /* 133 */ "Real" OpHelp("r[P2]=P4"),
24033 /* 134 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
24034 /* 135 */ "IfPos" OpHelp("if r[P1]>0 goto P2"),
24035 /* 136 */ "IfNeg" OpHelp("r[P1]+=P3, if r[P1]<0 goto P2"),
24036 /* 137 */ "IfZero" OpHelp("r[P1]+=P3, if r[P1]==0 goto P2"),
24037 /* 138 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
24038 /* 139 */ "IncrVacuum" OpHelp(""),
24039 /* 140 */ "Expire" OpHelp(""),
24040 /* 141 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
24041 /* 142 */ "VBegin" OpHelp(""),
24042 /* 143 */ "ToText" OpHelp(""),
24043 /* 144 */ "ToBlob" OpHelp(""),
24044 /* 145 */ "ToNumeric" OpHelp(""),
24045 /* 146 */ "ToInt" OpHelp(""),
24046 /* 147 */ "ToReal" OpHelp(""),
24047 /* 148 */ "VCreate" OpHelp(""),
24048 /* 149 */ "VDestroy" OpHelp(""),
24049 /* 150 */ "VOpen" OpHelp(""),
24050 /* 151 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
24051 /* 152 */ "VNext" OpHelp(""),
24052 /* 153 */ "VRename" OpHelp(""),
24053 /* 154 */ "Pagecount" OpHelp(""),
24054 /* 155 */ "MaxPgcnt" OpHelp(""),
24055 /* 156 */ "Init" OpHelp("Start at P2"),
24056 /* 157 */ "Noop" OpHelp(""),
24057 /* 158 */ "Explain" OpHelp(""),
24058 };
24059 return azName[i];
24060 }
24061 #endif
24062
@@ -23814,15 +24155,14 @@
24155 #include <unistd.h>
24156 /* #include <time.h> */
24157 #include <sys/time.h>
24158 #include <errno.h>
24159 #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
24160 # include <sys/mman.h>
24161 #endif
24162
24163 #if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS
 
24164 # include <sys/ioctl.h>
24165 # if OS_VXWORKS
24166 # include <semaphore.h>
24167 # include <limits.h>
24168 # else
@@ -24246,11 +24586,15 @@
24586 ** On some systems, calls to fchown() will trigger a message in a security
24587 ** log if they come from non-root processes. So avoid calling fchown() if
24588 ** we are not running as root.
24589 */
24590 static int posixFchown(int fd, uid_t uid, gid_t gid){
24591 #if OS_VXWORKS
24592 return 0;
24593 #else
24594 return geteuid() ? 0 : fchown(fd,uid,gid);
24595 #endif
24596 }
24597
24598 /* Forward reference */
24599 static int openDirectory(const char*, int*);
24600 static int unixGetpagesize(void);
@@ -24302,11 +24646,11 @@
24646 #define osFcntl ((int(*)(int,int,...))aSyscall[7].pCurrent)
24647
24648 { "read", (sqlite3_syscall_ptr)read, 0 },
24649 #define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
24650
24651 #if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
24652 { "pread", (sqlite3_syscall_ptr)pread, 0 },
24653 #else
24654 { "pread", (sqlite3_syscall_ptr)0, 0 },
24655 #endif
24656 #define osPread ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].pCurrent)
@@ -24319,11 +24663,11 @@
24663 #define osPread64 ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].pCurrent)
24664
24665 { "write", (sqlite3_syscall_ptr)write, 0 },
24666 #define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
24667
24668 #if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
24669 { "pwrite", (sqlite3_syscall_ptr)pwrite, 0 },
24670 #else
24671 { "pwrite", (sqlite3_syscall_ptr)0, 0 },
24672 #endif
24673 #define osPwrite ((ssize_t(*)(int,const void*,size_t,off_t))\
@@ -24689,20 +25033,10 @@
25033 }
25034 /* else fall through */
25035 case EPERM:
25036 return SQLITE_PERM;
25037
 
 
 
 
 
 
 
 
 
 
25038 #if EOPNOTSUPP!=ENOTSUP
25039 case EOPNOTSUPP:
25040 /* something went terribly awry, unless during file system support
25041 * introspection, in which it actually means what it says */
25042 #endif
@@ -25231,13 +25565,17 @@
25565
25566 /*
25567 ** Return TRUE if pFile has been renamed or unlinked since it was first opened.
25568 */
25569 static int fileHasMoved(unixFile *pFile){
25570 #if OS_VXWORKS
25571 return pFile->pInode!=0 && pFile->pId!=pFile->pInode->fileId.pId;
25572 #else
25573 struct stat buf;
25574 return pFile->pInode!=0 &&
25575 (osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino);
25576 #endif
25577 }
25578
25579
25580 /*
25581 ** Check a unixFile that is a database. Verify the following:
@@ -26376,11 +26714,10 @@
26714 }
26715
26716 /* Otherwise see if some other process holds it. */
26717 if( !reserved ){
26718 sem_t *pSem = pFile->pInode->pSem;
 
26719
26720 if( sem_trywait(pSem)==-1 ){
26721 int tErrno = errno;
26722 if( EAGAIN != tErrno ){
26723 rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
@@ -26429,11 +26766,10 @@
26766 ** This routine will only increase a lock. Use the sqlite3OsUnlock()
26767 ** routine to lower a locking level.
26768 */
26769 static int semLock(sqlite3_file *id, int eFileLock) {
26770 unixFile *pFile = (unixFile*)id;
 
26771 sem_t *pSem = pFile->pInode->pSem;
26772 int rc = SQLITE_OK;
26773
26774 /* if we already have a lock, it is exclusive.
26775 ** Just adjust level and punt on outta here. */
@@ -31713,22 +32049,18 @@
32049 #ifndef NTDDI_WINBLUE
32050 # define NTDDI_WINBLUE 0x06030000
32051 #endif
32052
32053 /*
32054 ** Check to see if the GetVersionEx[AW] functions are deprecated on the
32055 ** target system. GetVersionEx was first deprecated in Win8.1.
 
 
 
 
32056 */
32057 #ifndef SQLITE_WIN32_GETVERSIONEX
32058 # if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINBLUE
32059 # define SQLITE_WIN32_GETVERSIONEX 0 /* GetVersionEx() is deprecated */
32060 # else
32061 # define SQLITE_WIN32_GETVERSIONEX 1 /* GetVersionEx() is current */
32062 # endif
32063 #endif
32064
32065 /*
32066 ** This constant should already be defined (in the "WinDef.h" SDK file).
@@ -31796,11 +32128,11 @@
32128 /*
32129 ** This macro is used when a local variable is set to a value that is
32130 ** [sometimes] not used by the code (e.g. via conditional compilation).
32131 */
32132 #ifndef UNUSED_VARIABLE_VALUE
32133 # define UNUSED_VARIABLE_VALUE(x) (void)(x)
32134 #endif
32135
32136 /*
32137 ** Returns the character that should be used as the directory separator.
32138 */
@@ -31845,11 +32177,11 @@
32177
32178 /*
32179 ** Some Microsoft compilers lack this definition.
32180 */
32181 #ifndef INVALID_FILE_ATTRIBUTES
32182 # define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
32183 #endif
32184
32185 #ifndef FILE_FLAG_MASK
32186 # define FILE_FLAG_MASK (0xFF3C0000)
32187 #endif
@@ -31895,11 +32227,11 @@
32227 #endif
32228 const char *zPath; /* Full pathname of this file */
32229 int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */
32230 #if SQLITE_OS_WINCE
32231 LPWSTR zDeleteOnClose; /* Name of file to delete when closing */
32232 HANDLE hMutex; /* Mutex used to control access to shared lock */
32233 HANDLE hShared; /* Shared memory segment used for locking */
32234 winceLock local; /* Locks obtained by this instance of winFile */
32235 winceLock *shared; /* Global shared lock memory for the file */
32236 #endif
32237 #if SQLITE_MAX_MMAP_SIZE>0
@@ -32055,14 +32387,13 @@
32387 **
32388 ** In order to facilitate testing on a WinNT system, the test fixture
32389 ** can manually set this value to 1 to emulate Win98 behavior.
32390 */
32391 #ifdef SQLITE_TEST
32392 SQLITE_API LONG volatile sqlite3_os_type = 0;
32393 #else
32394 static LONG volatile sqlite3_os_type = 0;
 
32395 #endif
32396
32397 #ifndef SYSCALL
32398 # define SYSCALL sqlite3_syscall_ptr
32399 #endif
@@ -32689,10 +33020,26 @@
33020 #endif
33021
33022 #define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
33023 LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[75].pCurrent)
33024
33025 /*
33026 ** NOTE: On some sub-platforms, the InterlockedCompareExchange "function"
33027 ** is really just a macro that uses a compiler intrinsic (e.g. x64).
33028 ** So do not try to make this is into a redefinable interface.
33029 */
33030 #if defined(InterlockedCompareExchange)
33031 { "InterlockedCompareExchange", (SYSCALL)0, 0 },
33032
33033 #define osInterlockedCompareExchange InterlockedCompareExchange
33034 #else
33035 { "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 },
33036
33037 #define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG volatile*, \
33038 LONG,LONG))aSyscall[76].pCurrent)
33039 #endif /* defined(InterlockedCompareExchange) */
33040
33041 }; /* End of the overrideable system calls */
33042
33043 /*
33044 ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
33045 ** "win32" VFSes. Return SQLITE_OK opon successfully updating the
@@ -32939,26 +33286,42 @@
33286 #elif SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI)
33287 # define osIsNT() (1)
33288 #elif !defined(SQLITE_WIN32_HAS_WIDE)
33289 # define osIsNT() (0)
33290 #else
33291 # define osIsNT() ((sqlite3_os_type==2) || sqlite3_win32_is_nt())
33292 #endif
33293
33294 /*
33295 ** This function determines if the machine is running a version of Windows
33296 ** based on the NT kernel.
33297 */
33298 SQLITE_API int sqlite3_win32_is_nt(void){
33299 #if defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX
33300 if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){
33301 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
33302 defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WIN8
33303 OSVERSIONINFOW sInfo;
33304 sInfo.dwOSVersionInfoSize = sizeof(sInfo);
33305 osGetVersionExW(&sInfo);
33306 osInterlockedCompareExchange(&sqlite3_os_type,
33307 (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
33308 #elif defined(SQLITE_WIN32_HAS_ANSI)
33309 OSVERSIONINFOA sInfo;
33310 sInfo.dwOSVersionInfoSize = sizeof(sInfo);
33311 osGetVersionExA(&sInfo);
33312 osInterlockedCompareExchange(&sqlite3_os_type,
33313 (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
33314 #endif
33315 }
33316 return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
33317 #elif SQLITE_TEST
33318 return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
33319 #else
33320 return 1;
33321 #endif
33322 }
 
 
 
 
 
 
33323
33324 #ifdef SQLITE_WIN32_MALLOC
33325 /*
33326 ** Allocate nBytes of memory.
33327 */
@@ -33162,11 +33525,11 @@
33525 sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32());
33526 }
33527 #endif /* SQLITE_WIN32_MALLOC */
33528
33529 /*
33530 ** Convert a UTF-8 string to Microsoft Unicode (UTF-16?).
33531 **
33532 ** Space to hold the returned string is obtained from malloc.
33533 */
33534 static LPWSTR winUtf8ToUnicode(const char *zFilename){
33535 int nChar;
@@ -33215,11 +33578,11 @@
33578 }
33579
33580 /*
33581 ** Convert an ANSI string to Microsoft Unicode, based on the
33582 ** current codepage settings for file apis.
33583 **
33584 ** Space to hold the returned string is obtained
33585 ** from sqlite3_malloc.
33586 */
33587 static LPWSTR winMbcsToUnicode(const char *zFilename){
33588 int nByte;
@@ -33289,11 +33652,11 @@
33652 sqlite3_free(zTmpWide);
33653 return zFilenameUtf8;
33654 }
33655
33656 /*
33657 ** Convert UTF-8 to multibyte character string. Space to hold the
33658 ** returned string is obtained from sqlite3_malloc().
33659 */
33660 SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
33661 char *zFilenameMbcs;
33662 LPWSTR zTmpWide;
@@ -33429,15 +33792,15 @@
33792 ** This function - winLogErrorAtLine() - is only ever called via the macro
33793 ** winLogError().
33794 **
33795 ** This routine is invoked after an error occurs in an OS function.
33796 ** It logs a message using sqlite3_log() containing the current value of
33797 ** error code and, if possible, the human-readable equivalent from
33798 ** FormatMessage.
33799 **
33800 ** The first argument passed to the macro should be the error code that
33801 ** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
33802 ** The two subsequent arguments should be the name of the OS function that
33803 ** failed and the associated file-system path, if any.
33804 */
33805 #define winLogError(a,b,c,d) winLogErrorAtLine(a,b,c,d,__LINE__)
33806 static int winLogErrorAtLine(
@@ -33464,11 +33827,11 @@
33827 return errcode;
33828 }
33829
33830 /*
33831 ** The number of times that a ReadFile(), WriteFile(), and DeleteFile()
33832 ** will be retried following a locking error - probably caused by
33833 ** antivirus software. Also the initial delay before the first retry.
33834 ** The delay increases linearly with each retry.
33835 */
33836 #ifndef SQLITE_WIN32_IOERR_RETRY
33837 # define SQLITE_WIN32_IOERR_RETRY 10
@@ -33539,11 +33902,11 @@
33902 /*
33903 ** Log a I/O error retry episode.
33904 */
33905 static void winLogIoerr(int nRetry){
33906 if( nRetry ){
33907 sqlite3_log(SQLITE_IOERR,
33908 "delayed %dms for lock/sharing conflict",
33909 winIoerrRetryDelay*nRetry*(nRetry+1)/2
33910 );
33911 }
33912 }
@@ -33633,21 +33996,21 @@
33996 "winceCreateLock1", zFilename);
33997 }
33998
33999 /* Acquire the mutex before continuing */
34000 winceMutexAcquire(pFile->hMutex);
34001
34002 /* Since the names of named mutexes, semaphores, file mappings etc are
34003 ** case-sensitive, take advantage of that by uppercasing the mutex name
34004 ** and using that as the shared filemapping name.
34005 */
34006 osCharUpperW(zName);
34007 pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
34008 PAGE_READWRITE, 0, sizeof(winceLock),
34009 zName);
34010
34011 /* Set a flag that indicates we're the first to create the memory so it
34012 ** must be zero-initialized */
34013 lastErrno = osGetLastError();
34014 if (lastErrno == ERROR_ALREADY_EXISTS){
34015 bInit = FALSE;
34016 }
@@ -33654,11 +34017,11 @@
34017
34018 sqlite3_free(zName);
34019
34020 /* If we succeeded in making the shared memory handle, map it. */
34021 if( pFile->hShared ){
34022 pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared,
34023 FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
34024 /* If mapping failed, close the shared memory handle and erase it */
34025 if( !pFile->shared ){
34026 pFile->lastErrno = osGetLastError();
34027 winLogError(SQLITE_IOERR, pFile->lastErrno,
@@ -33680,11 +34043,11 @@
34043 winceMutexRelease(pFile->hMutex);
34044 osCloseHandle(pFile->hMutex);
34045 pFile->hMutex = NULL;
34046 return SQLITE_IOERR;
34047 }
34048
34049 /* Initialize the shared memory if we're supposed to */
34050 if( bInit ){
34051 memset(pFile->shared, 0, sizeof(winceLock));
34052 }
34053
@@ -33718,17 +34081,17 @@
34081 /* De-reference and close our copy of the shared memory handle */
34082 osUnmapViewOfFile(pFile->shared);
34083 osCloseHandle(pFile->hShared);
34084
34085 /* Done with the mutex */
34086 winceMutexRelease(pFile->hMutex);
34087 osCloseHandle(pFile->hMutex);
34088 pFile->hMutex = NULL;
34089 }
34090 }
34091
34092 /*
34093 ** An implementation of the LockFile() API of Windows for CE
34094 */
34095 static BOOL winceLockFile(
34096 LPHANDLE phFile,
34097 DWORD dwFileOffsetLow,
@@ -33935,12 +34298,12 @@
34298 #ifndef INVALID_SET_FILE_POINTER
34299 # define INVALID_SET_FILE_POINTER ((DWORD)-1)
34300 #endif
34301
34302 /*
34303 ** Move the current position of the file handle passed as the first
34304 ** argument to offset iOffset within the file. If successful, return 0.
34305 ** Otherwise, set pFile->lastErrno and return non-zero.
34306 */
34307 static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){
34308 #if !SQLITE_OS_WINRT
34309 LONG upperBits; /* Most sig. 32 bits of new offset */
@@ -33951,15 +34314,15 @@
34314 OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset));
34315
34316 upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
34317 lowerBits = (LONG)(iOffset & 0xffffffff);
34318
34319 /* API oddity: If successful, SetFilePointer() returns a dword
34320 ** containing the lower 32-bits of the new file-offset. Or, if it fails,
34321 ** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
34322 ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
34323 ** whether an error has actually occurred, it is also necessary to call
34324 ** GetLastError().
34325 */
34326 dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
34327
34328 if( (dwRet==INVALID_SET_FILE_POINTER
@@ -34038,11 +34401,11 @@
34401 winceDestroyLock(pFile);
34402 if( pFile->zDeleteOnClose ){
34403 int cnt = 0;
34404 while(
34405 osDeleteFileW(pFile->zDeleteOnClose)==0
34406 && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
34407 && cnt++ < WINCE_DELETION_ATTEMPTS
34408 ){
34409 sqlite3_win32_sleep(100); /* Wait a little before trying again */
34410 }
34411 sqlite3_free(pFile->zDeleteOnClose);
@@ -34886,11 +35249,11 @@
35249 winFile *p = (winFile*)id;
35250 return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
35251 ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
35252 }
35253
35254 /*
35255 ** Windows will only let you create file view mappings
35256 ** on allocation size granularity boundaries.
35257 ** During sqlite3_os_init() we do a GetSystemInfo()
35258 ** to get the granularity size.
35259 */
@@ -34898,15 +35261,15 @@
35261
35262 #ifndef SQLITE_OMIT_WAL
35263
35264 /*
35265 ** Helper functions to obtain and relinquish the global mutex. The
35266 ** global mutex is used to protect the winLockInfo objects used by
35267 ** this file, all of which may be shared by multiple threads.
35268 **
35269 ** Function winShmMutexHeld() is used to assert() that the global mutex
35270 ** is held when required. This function is only used as part of assert()
35271 ** statements. e.g.
35272 **
35273 ** winShmEnterMutex()
35274 ** assert( winShmMutexHeld() );
35275 ** winShmLeaveMutex()
@@ -34932,14 +35295,14 @@
35295 **
35296 ** winShmMutexHeld() must be true when creating or destroying
35297 ** this object or while reading or writing the following fields:
35298 **
35299 ** nRef
35300 ** pNext
35301 **
35302 ** The following fields are read-only after the object is created:
35303 **
35304 ** fid
35305 ** zFilename
35306 **
35307 ** Either winShmNode.mutex must be held or winShmNode.nRef==0 and
35308 ** winShmMutexHeld() is true when reading or writing any other field
@@ -35031,11 +35394,11 @@
35394 /* Initialize the locking parameters */
35395 DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
35396 if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
35397 rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0);
35398 }
35399
35400 if( rc!= 0 ){
35401 rc = SQLITE_OK;
35402 }else{
35403 pFile->lastErrno = osGetLastError();
35404 rc = SQLITE_BUSY;
@@ -35127,11 +35490,11 @@
35490 sqlite3_free(p);
35491 return SQLITE_IOERR_NOMEM;
35492 }
35493 pNew->zFilename = (char*)&pNew[1];
35494 sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
35495 sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
35496
35497 /* Look to see if there is an existing winShmNode that can be used.
35498 ** If no matching winShmNode currently exists, create a new one.
35499 */
35500 winShmEnterMutex();
@@ -35164,11 +35527,11 @@
35527 if( SQLITE_OK!=rc ){
35528 goto shm_open_err;
35529 }
35530
35531 /* Check to see if another process is holding the dead-man switch.
35532 ** If not, truncate the file to zero length.
35533 */
35534 if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
35535 rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
35536 if( rc!=SQLITE_OK ){
35537 rc = winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
@@ -35193,11 +35556,11 @@
35556
35557 /* The reference count on pShmNode has already been incremented under
35558 ** the cover of the winShmEnterMutex() mutex and the pointer from the
35559 ** new (struct winShm) object to the pShmNode has been set. All that is
35560 ** left to do is to link the new object into the linked list starting
35561 ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
35562 ** mutex.
35563 */
35564 sqlite3_mutex_enter(pShmNode->mutex);
35565 p->pNext = pShmNode->pFirst;
35566 pShmNode->pFirst = p;
@@ -35213,11 +35576,11 @@
35576 winShmLeaveMutex();
35577 return rc;
35578 }
35579
35580 /*
35581 ** Close a connection to shared-memory. Delete the underlying
35582 ** storage if deleteFlag is true.
35583 */
35584 static int winShmUnmap(
35585 sqlite3_file *fd, /* Database holding shared memory */
35586 int deleteFlag /* Delete after closing if true */
@@ -35302,11 +35665,11 @@
35665
35666 /* Undo the local locks */
35667 if( rc==SQLITE_OK ){
35668 p->exclMask &= ~mask;
35669 p->sharedMask &= ~mask;
35670 }
35671 }else if( flags & SQLITE_SHM_SHARED ){
35672 u16 allShared = 0; /* Union of locks held by connections other than "p" */
35673
35674 /* Find out which shared locks are already held by sibling connections.
35675 ** If any sibling already holds an exclusive lock, go ahead and return
@@ -35341,11 +35704,11 @@
35704 if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
35705 rc = SQLITE_BUSY;
35706 break;
35707 }
35708 }
35709
35710 /* Get the exclusive locks at the system level. Then if successful
35711 ** also mark the local connection as being locked.
35712 */
35713 if( rc==SQLITE_OK ){
35714 rc = winShmSystemLock(pShmNode, _SHM_WRLCK, ofst+WIN_SHM_BASE, n);
@@ -35361,11 +35724,11 @@
35724 sqlite3ErrName(rc)));
35725 return rc;
35726 }
35727
35728 /*
35729 ** Implement a memory barrier or memory fence on shared memory.
35730 **
35731 ** All loads and stores begun before the barrier must complete before
35732 ** any load or store begun after the barrier.
35733 */
35734 static void winShmBarrier(
@@ -35376,26 +35739,26 @@
35739 winShmEnterMutex();
35740 winShmLeaveMutex();
35741 }
35742
35743 /*
35744 ** This function is called to obtain a pointer to region iRegion of the
35745 ** shared-memory associated with the database file fd. Shared-memory regions
35746 ** are numbered starting from zero. Each shared-memory region is szRegion
35747 ** bytes in size.
35748 **
35749 ** If an error occurs, an error code is returned and *pp is set to NULL.
35750 **
35751 ** Otherwise, if the isWrite parameter is 0 and the requested shared-memory
35752 ** region has not been allocated (by any client, including one running in a
35753 ** separate process), then *pp is set to NULL and SQLITE_OK returned. If
35754 ** isWrite is non-zero and the requested shared-memory region has not yet
35755 ** been allocated, it is allocated by this function.
35756 **
35757 ** If the shared-memory region has already been allocated or is allocated by
35758 ** this call as described above, then it is mapped into this processes
35759 ** address space (if it is not already), *pp is set to point to the mapped
35760 ** memory and SQLITE_OK returned.
35761 */
35762 static int winShmMap(
35763 sqlite3_file *fd, /* Handle open on database file */
35764 int iRegion, /* Region to retrieve */
@@ -35463,21 +35826,21 @@
35826 pShmNode->aRegion = apNew;
35827
35828 while( pShmNode->nRegion<=iRegion ){
35829 HANDLE hMap = NULL; /* file-mapping handle */
35830 void *pMap = 0; /* Mapped memory region */
35831
35832 #if SQLITE_OS_WINRT
35833 hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
35834 NULL, PAGE_READWRITE, nByte, NULL
35835 );
35836 #elif defined(SQLITE_WIN32_HAS_WIDE)
35837 hMap = osCreateFileMappingW(pShmNode->hFile.h,
35838 NULL, PAGE_READWRITE, 0, nByte, NULL
35839 );
35840 #elif defined(SQLITE_WIN32_HAS_ANSI)
35841 hMap = osCreateFileMappingA(pShmNode->hFile.h,
35842 NULL, PAGE_READWRITE, 0, nByte, NULL
35843 );
35844 #endif
35845 OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
35846 osGetCurrentProcessId(), pShmNode->nRegion, nByte,
@@ -35570,18 +35933,18 @@
35933 return SQLITE_OK;
35934 }
35935
35936 /*
35937 ** Memory map or remap the file opened by file-descriptor pFd (if the file
35938 ** is already mapped, the existing mapping is replaced by the new). Or, if
35939 ** there already exists a mapping for this file, and there are still
35940 ** outstanding xFetch() references to it, this function is a no-op.
35941 **
35942 ** If parameter nByte is non-negative, then it is the requested size of
35943 ** the mapping to create. Otherwise, if nByte is less than zero, then the
35944 ** requested size is the size of the file on disk. The actual size of the
35945 ** created mapping is either the requested size or the value configured
35946 ** using SQLITE_FCNTL_MMAP_SIZE, whichever is smaller.
35947 **
35948 ** SQLITE_OK is returned if no error occurs (even if the mapping is not
35949 ** recreated as a result of outstanding references) or an SQLite error
35950 ** code otherwise.
@@ -35606,11 +35969,11 @@
35969 }
35970 if( nMap>pFd->mmapSizeMax ){
35971 nMap = pFd->mmapSizeMax;
35972 }
35973 nMap &= ~(sqlite3_int64)(winSysInfo.dwPageSize - 1);
35974
35975 if( nMap==0 && pFd->mmapSize>0 ){
35976 winUnmapfile(pFd);
35977 }
35978 if( nMap!=pFd->mmapSize ){
35979 void *pNew = 0;
@@ -35678,11 +36041,11 @@
36041 ** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
36042 ** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
36043 ** Finally, if an error does occur, return an SQLite error code. The final
36044 ** value of *pp is undefined in this case.
36045 **
36046 ** If this function does return a pointer, the caller must eventually
36047 ** release the reference by calling winUnfetch().
36048 */
36049 static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
36050 #if SQLITE_MAX_MMAP_SIZE>0
36051 winFile *pFd = (winFile*)fd; /* The underlying database file */
@@ -35713,24 +36076,24 @@
36076 osGetCurrentProcessId(), fd, pp, *pp));
36077 return SQLITE_OK;
36078 }
36079
36080 /*
36081 ** If the third argument is non-NULL, then this function releases a
36082 ** reference obtained by an earlier call to winFetch(). The second
36083 ** argument passed to this function must be the same as the corresponding
36084 ** argument that was passed to the winFetch() invocation.
36085 **
36086 ** Or, if the third argument is NULL, then this function is being called
36087 ** to inform the VFS layer that, according to POSIX, any existing mapping
36088 ** may now be invalid and should be unmapped.
36089 */
36090 static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){
36091 #if SQLITE_MAX_MMAP_SIZE>0
36092 winFile *pFd = (winFile*)fd; /* The underlying database file */
36093
36094 /* If p==0 (unmap the entire file) then there must be no outstanding
36095 ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
36096 ** then there must be at least one outstanding. */
36097 assert( (p==0)==(pFd->nFetchOut==0) );
36098
36099 /* If p!=0, it must match the iOff value. */
@@ -35872,11 +36235,11 @@
36235 int nMax, nBuf, nDir, nLen;
36236 char *zBuf;
36237
36238 /* It's odd to simulate an io-error here, but really this is just
36239 ** using the io-error infrastructure to test that SQLite handles this
36240 ** function failing.
36241 */
36242 SimulateIOError( return SQLITE_IOERR );
36243
36244 /* Allocate a temporary buffer to store the fully qualified file
36245 ** name for the temporary file. If this fails, we cannot continue.
@@ -36054,11 +36417,11 @@
36417 OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
36418 return winLogError(SQLITE_ERROR, 0, "winGetTempname4", 0);
36419 }
36420
36421 /*
36422 ** Check that the output buffer is large enough for the temporary file
36423 ** name in the following format:
36424 **
36425 ** "<temporary_directory>/etilqs_XXXXXXXXXXXXXXX\0\0"
36426 **
36427 ** If not, return SQLITE_ERROR. The number 17 is used here in order to
@@ -36157,42 +36520,42 @@
36520 int isReadonly = (flags & SQLITE_OPEN_READONLY);
36521 int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
36522
36523 #ifndef NDEBUG
36524 int isOpenJournal = (isCreate && (
36525 eType==SQLITE_OPEN_MASTER_JOURNAL
36526 || eType==SQLITE_OPEN_MAIN_JOURNAL
36527 || eType==SQLITE_OPEN_WAL
36528 ));
36529 #endif
36530
36531 OSTRACE(("OPEN name=%s, pFile=%p, flags=%x, pOutFlags=%p\n",
36532 zUtf8Name, id, flags, pOutFlags));
36533
36534 /* Check the following statements are true:
36535 **
36536 ** (a) Exactly one of the READWRITE and READONLY flags must be set, and
36537 ** (b) if CREATE is set, then READWRITE must also be set, and
36538 ** (c) if EXCLUSIVE is set, then CREATE must also be set.
36539 ** (d) if DELETEONCLOSE is set, then CREATE must also be set.
36540 */
36541 assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
36542 assert(isCreate==0 || isReadWrite);
36543 assert(isExclusive==0 || isCreate);
36544 assert(isDelete==0 || isCreate);
36545
36546 /* The main DB, main journal, WAL file and master journal are never
36547 ** automatically deleted. Nor are they ever temporary files. */
36548 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
36549 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
36550 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
36551 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
36552
36553 /* Assert that the upper layer has set one of the "file-type" flags. */
36554 assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
36555 || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
36556 || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
36557 || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
36558 );
36559
36560 assert( pFile!=0 );
36561 memset(pFile, 0, sizeof(winFile));
@@ -36203,12 +36566,12 @@
36566 sqlite3_log(SQLITE_ERROR,
36567 "sqlite3_temp_directory variable should be set for WinRT");
36568 }
36569 #endif
36570
36571 /* If the second argument to this function is NULL, generate a
36572 ** temporary file name to use
36573 */
36574 if( !zUtf8Name ){
36575 assert( isDelete && !isOpenJournal );
36576 rc = winGetTempname(pVfs, &zTmpname);
36577 if( rc!=SQLITE_OK ){
@@ -36244,12 +36607,12 @@
36607 dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
36608 }else{
36609 dwDesiredAccess = GENERIC_READ;
36610 }
36611
36612 /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is
36613 ** created. SQLite doesn't use it to indicate "exclusive access"
36614 ** as it is usually understood.
36615 */
36616 if( isExclusive ){
36617 /* Creates a new file, only if it does not already exist. */
36618 /* If the file exists, it fails. */
@@ -36334,11 +36697,11 @@
36697 pFile->lastErrno = lastErrno;
36698 winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name);
36699 sqlite3_free(zConverted);
36700 sqlite3_free(zTmpname);
36701 if( isReadWrite && !isExclusive ){
36702 return winOpen(pVfs, zName, id,
36703 ((flags|SQLITE_OPEN_READONLY) &
36704 ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
36705 pOutFlags);
36706 }else{
36707 return SQLITE_CANTOPEN_BKPT;
@@ -36543,18 +36906,18 @@
36906 if( osIsNT() ){
36907 int cnt = 0;
36908 WIN32_FILE_ATTRIBUTE_DATA sAttrData;
36909 memset(&sAttrData, 0, sizeof(sAttrData));
36910 while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
36911 GetFileExInfoStandard,
36912 &sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){}
36913 if( rc ){
36914 /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
36915 ** as if it does not exist.
36916 */
36917 if( flags==SQLITE_ACCESS_EXISTS
36918 && sAttrData.nFileSizeHigh==0
36919 && sAttrData.nFileSizeLow==0 ){
36920 attr = INVALID_FILE_ATTRIBUTES;
36921 }else{
36922 attr = sAttrData.dwFileAttributes;
36923 }
@@ -36649,11 +37012,11 @@
37012 sqlite3_vfs *pVfs, /* Pointer to vfs object */
37013 const char *zRelative, /* Possibly relative input path */
37014 int nFull, /* Size of output buffer in bytes */
37015 char *zFull /* Output buffer */
37016 ){
37017
37018 #if defined(__CYGWIN__)
37019 SimulateIOError( return SQLITE_ERROR );
37020 UNUSED_PARAMETER(nFull);
37021 assert( nFull>=pVfs->mxPathname );
37022 if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
@@ -36962,24 +37325,24 @@
37325 ** the current time and date as a Julian Day number times 86_400_000. In
37326 ** other words, write into *piNow the number of milliseconds since the Julian
37327 ** epoch of noon in Greenwich on November 24, 4714 B.C according to the
37328 ** proleptic Gregorian calendar.
37329 **
37330 ** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
37331 ** cannot be found.
37332 */
37333 static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
37334 /* FILETIME structure is a 64-bit value representing the number of
37335 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
37336 */
37337 FILETIME ft;
37338 static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000;
37339 #ifdef SQLITE_TEST
37340 static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
37341 #endif
37342 /* 2^32 - to avoid use of LL and warnings in gcc */
37343 static const sqlite3_int64 max32BitValue =
37344 (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 +
37345 (sqlite3_int64)294967296;
37346
37347 #if SQLITE_OS_WINCE
37348 SYSTEMTIME time;
@@ -36991,11 +37354,11 @@
37354 #else
37355 osGetSystemTimeAsFileTime( &ft );
37356 #endif
37357
37358 *piNow = winFiletimeEpoch +
37359 ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) +
37360 (sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000;
37361
37362 #ifdef SQLITE_TEST
37363 if( sqlite3_current_time ){
37364 *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
@@ -37110,11 +37473,11 @@
37473 };
37474 #endif
37475
37476 /* Double-check that the aSyscall[] array has been constructed
37477 ** correctly. See ticket [bb3a86e890c8e96ab] */
37478 assert( ArraySize(aSyscall)==77 );
37479
37480 /* get memory map allocation granularity */
37481 memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
37482 #if SQLITE_OS_WINRT
37483 osGetNativeSystemInfo(&winSysInfo);
@@ -37128,14 +37491,14 @@
37491
37492 #if defined(SQLITE_WIN32_HAS_WIDE)
37493 sqlite3_vfs_register(&winLongPathVfs, 0);
37494 #endif
37495
37496 return SQLITE_OK;
37497 }
37498
37499 SQLITE_API int sqlite3_os_end(void){
37500 #if SQLITE_OS_WINRT
37501 if( sleepObj!=NULL ){
37502 osCloseHandle(sleepObj);
37503 sleepObj = NULL;
37504 }
@@ -51332,11 +51695,11 @@
51695 /* If the client is reading or writing an index and the schema is
51696 ** not loaded, then it is too difficult to actually check to see if
51697 ** the correct locks are held. So do not bother - just return true.
51698 ** This case does not come up very often anyhow.
51699 */
51700 if( isIndex && (!pSchema || (pSchema->schemaFlags&DB_SchemaLoaded)==0) ){
51701 return 1;
51702 }
51703
51704 /* Figure out the root-page that the lock should be held on. For table
51705 ** b-trees, this is just the root page of the b-tree being read or
@@ -52802,11 +53165,11 @@
53165 return pBt->nPage;
53166 }
53167 SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree *p){
53168 assert( sqlite3BtreeHoldsMutex(p) );
53169 assert( ((p->pBt->nPage)&0x8000000)==0 );
53170 return btreePagecount(p->pBt);
53171 }
53172
53173 /*
53174 ** Get a page from the pager and initialize it. This routine is just a
53175 ** convenience wrapper around separate calls to btreeGetPage() and
@@ -61928,22 +62291,39 @@
62291 pB->zSql = zTmp;
62292 pB->isPrepareV2 = pA->isPrepareV2;
62293 }
62294
62295 /*
62296 ** Resize the Vdbe.aOp array so that it is at least nOp elements larger
62297 ** than its current size. nOp is guaranteed to be less than or equal
62298 ** to 1024/sizeof(Op).
62299 **
62300 ** If an out-of-memory error occurs while resizing the array, return
62301 ** SQLITE_NOMEM. In this case Vdbe.aOp and Parse.nOpAlloc remain
62302 ** unchanged (this is so that any opcodes already allocated can be
62303 ** correctly deallocated along with the rest of the Vdbe).
62304 */
62305 static int growOpArray(Vdbe *v, int nOp){
62306 VdbeOp *pNew;
62307 Parse *p = v->pParse;
62308
62309 /* The SQLITE_TEST_REALLOC_STRESS compile-time option is designed to force
62310 ** more frequent reallocs and hence provide more opportunities for
62311 ** simulated OOM faults. SQLITE_TEST_REALLOC_STRESS is generally used
62312 ** during testing only. With SQLITE_TEST_REALLOC_STRESS grow the op array
62313 ** by the minimum* amount required until the size reaches 512. Normal
62314 ** operation (without SQLITE_TEST_REALLOC_STRESS) is to double the current
62315 ** size of the op array or add 1KB of space, whichever is smaller. */
62316 #ifdef SQLITE_TEST_REALLOC_STRESS
62317 int nNew = (p->nOpAlloc>=512 ? p->nOpAlloc*2 : p->nOpAlloc+nOp);
62318 #else
62319 int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op)));
62320 UNUSED_PARAMETER(nOp);
62321 #endif
62322
62323 assert( nOp<=(1024/sizeof(Op)) );
62324 assert( nNew>=(p->nOpAlloc+nOp) );
62325 pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
62326 if( pNew ){
62327 p->nOpAlloc = sqlite3DbMallocSize(p->db, pNew)/sizeof(Op);
62328 v->aOp = pNew;
62329 }
@@ -61983,11 +62363,11 @@
62363
62364 i = p->nOp;
62365 assert( p->magic==VDBE_MAGIC_INIT );
62366 assert( op>0 && op<0xff );
62367 if( p->pParse->nOpAlloc<=i ){
62368 if( growOpArray(p, 1) ){
62369 return 1;
62370 }
62371 }
62372 p->nOp++;
62373 pOp = &p->aOp[i];
@@ -62343,11 +62723,11 @@
62723 }
62724 sqlite3DbFree(p->db, pParse->aLabel);
62725 pParse->aLabel = 0;
62726 pParse->nLabel = 0;
62727 *pMaxFuncArgs = nMaxArgs;
62728 assert( p->bIsReader!=0 || DbMaskAllZero(p->btreeMask) );
62729 }
62730
62731 /*
62732 ** Return the address of the next instruction to be inserted.
62733 */
@@ -62370,11 +62750,11 @@
62750 SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){
62751 VdbeOp *aOp = p->aOp;
62752 assert( aOp && !p->db->mallocFailed );
62753
62754 /* Check that sqlite3VdbeUsesBtree() was not called on this VM */
62755 assert( DbMaskAllZero(p->btreeMask) );
62756
62757 resolveP2Values(p, pnMaxArg);
62758 *pnOp = p->nOp;
62759 p->aOp = 0;
62760 return aOp;
@@ -62385,11 +62765,11 @@
62765 ** address of the first operation added.
62766 */
62767 SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp, int iLineno){
62768 int addr;
62769 assert( p->magic==VDBE_MAGIC_INIT );
62770 if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p, nOp) ){
62771 return 0;
62772 }
62773 addr = p->nOp;
62774 if( ALWAYS(nOp>0) ){
62775 int i;
@@ -62570,11 +62950,11 @@
62950
62951 /*
62952 ** Change the opcode at addr into OP_Noop
62953 */
62954 SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
62955 if( addr<p->nOp ){
62956 VdbeOp *pOp = &p->aOp[addr];
62957 sqlite3 *db = p->db;
62958 freeP4(db, pOp->p4type, pOp->p4.p);
62959 memset(pOp, 0, sizeof(pOp[0]));
62960 pOp->opcode = OP_Noop;
@@ -62955,13 +63335,13 @@
63335 ** p->btreeMask of databases that will require a lock.
63336 */
63337 SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe *p, int i){
63338 assert( i>=0 && i<p->db->nDb && i<(int)sizeof(yDbMask)*8 );
63339 assert( i<(int)sizeof(p->btreeMask)*8 );
63340 DbMaskSet(p->btreeMask, i);
63341 if( i!=1 && sqlite3BtreeSharable(p->db->aDb[i].pBt) ){
63342 DbMaskSet(p->lockMask, i);
63343 }
63344 }
63345
63346 #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
63347 /*
@@ -62985,20 +63365,19 @@
63365 ** this routine is N*N. But as N is rarely more than 1, this should not
63366 ** be a problem.
63367 */
63368 SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe *p){
63369 int i;
 
63370 sqlite3 *db;
63371 Db *aDb;
63372 int nDb;
63373 if( DbMaskAllZero(p->lockMask) ) return; /* The common case */
63374 db = p->db;
63375 aDb = db->aDb;
63376 nDb = db->nDb;
63377 for(i=0; i<nDb; i++){
63378 if( i!=1 && DbMaskTest(p->lockMask,i) && ALWAYS(aDb[i].pBt!=0) ){
63379 sqlite3BtreeEnter(aDb[i].pBt);
63380 }
63381 }
63382 }
63383 #endif
@@ -63007,20 +63386,19 @@
63386 /*
63387 ** Unlock all of the btrees previously locked by a call to sqlite3VdbeEnter().
63388 */
63389 SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe *p){
63390 int i;
 
63391 sqlite3 *db;
63392 Db *aDb;
63393 int nDb;
63394 if( DbMaskAllZero(p->lockMask) ) return; /* The common case */
63395 db = p->db;
63396 aDb = db->aDb;
63397 nDb = db->nDb;
63398 for(i=0; i<nDb; i++){
63399 if( i!=1 && DbMaskTest(p->lockMask,i) && ALWAYS(aDb[i].pBt!=0) ){
63400 sqlite3BtreeLeave(aDb[i].pBt);
63401 }
63402 }
63403 }
63404 #endif
@@ -63987,11 +64365,11 @@
64365 int cnt = 0;
64366 int nWrite = 0;
64367 int nRead = 0;
64368 p = db->pVdbe;
64369 while( p ){
64370 if( sqlite3_stmt_busy((sqlite3_stmt*)p) ){
64371 cnt++;
64372 if( p->readOnly==0 ) nWrite++;
64373 if( p->bIsReader ) nRead++;
64374 }
64375 p = p->pNext;
@@ -64147,11 +64525,10 @@
64525 /* Lock all btrees used by the statement */
64526 sqlite3VdbeEnter(p);
64527
64528 /* Check for one of the special errors */
64529 mrc = p->rc & 0xff;
 
64530 isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR
64531 || mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL;
64532 if( isSpecialError ){
64533 /* If the query was read-only and the error code is SQLITE_INTERRUPT,
64534 ** no rollback is necessary. Otherwise, at least a savepoint
@@ -64632,11 +65009,11 @@
65009 /*
65010 ** Return the serial-type for the value stored in pMem.
65011 */
65012 SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
65013 int flags = pMem->flags;
65014 u32 n;
65015
65016 if( flags&MEM_Null ){
65017 return 0;
65018 }
65019 if( flags&MEM_Int ){
@@ -64662,15 +65039,15 @@
65039 }
65040 if( flags&MEM_Real ){
65041 return 7;
65042 }
65043 assert( pMem->db->mallocFailed || flags&(MEM_Str|MEM_Blob) );
65044 assert( pMem->n>=0 );
65045 n = (u32)pMem->n;
65046 if( flags & MEM_Zero ){
65047 n += pMem->u.nZero;
65048 }
 
65049 return ((n*2) + 12 + ((flags&MEM_Str)!=0));
65050 }
65051
65052 /*
65053 ** Return the length of the data corresponding to the supplied serial-type.
@@ -67184,11 +67561,11 @@
67561 /*
67562 ** Return true if the prepared statement is in need of being reset.
67563 */
67564 SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
67565 Vdbe *v = (Vdbe*)pStmt;
67566 return v!=0 && v->pc>=0 && v->magic==VDBE_MAGIC_RUN;
67567 }
67568
67569 /*
67570 ** Return a pointer to the next prepared statement after pStmt associated
67571 ** with database connection pDb. If pStmt is NULL, return the first
@@ -67634,10 +68011,16 @@
68011 **
68012 ** M is an integer, 2 or 3, that indices how many different ways the
68013 ** branch can go. It is usually 2. "I" is the direction the branch
68014 ** goes. 0 means falls through. 1 means branch is taken. 2 means the
68015 ** second alternative branch is taken.
68016 **
68017 ** iSrcLine is the source code line (from the __LINE__ macro) that
68018 ** generated the VDBE instruction. This instrumentation assumes that all
68019 ** source code is in a single file (the amalgamation). Special values 1
68020 ** and 2 for the iSrcLine parameter mean that this particular branch is
68021 ** always taken or never taken, respectively.
68022 */
68023 #if !defined(SQLITE_VDBE_COVERAGE)
68024 # define VdbeBranchTaken(I,M)
68025 #else
68026 # define VdbeBranchTaken(I,M) vdbeTakeBranch(pOp->iSrcLine,I,M)
@@ -67742,25 +68125,25 @@
68125 ** do so without loss of information. In other words, if the string
68126 ** looks like a number, convert it into a number. If it does not
68127 ** look like a number, leave it alone.
68128 */
68129 static void applyNumericAffinity(Mem *pRec){
68130 double rValue;
68131 i64 iValue;
68132 u8 enc = pRec->enc;
68133 if( (pRec->flags&MEM_Str)==0 ) return;
68134 if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return;
68135 if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){
68136 pRec->u.i = iValue;
68137 pRec->flags |= MEM_Int;
68138 }else{
68139 pRec->r = rValue;
68140 pRec->flags |= MEM_Real;
68141 }
68142 }
68143 #define ApplyNumericAffinity(X) \
68144 if(((X)->flags&(MEM_Real|MEM_Int))==0){applyNumericAffinity(X);}
68145
68146 /*
68147 ** Processing is determine by the affinity parameter:
68148 **
68149 ** SQLITE_AFF_INTEGER:
@@ -67793,11 +68176,11 @@
68176 }
68177 pRec->flags &= ~(MEM_Real|MEM_Int);
68178 }else if( affinity!=SQLITE_AFF_NONE ){
68179 assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL
68180 || affinity==SQLITE_AFF_NUMERIC );
68181 ApplyNumericAffinity(pRec);
68182 if( pRec->flags & MEM_Real ){
68183 sqlite3VdbeIntegerAffinity(pRec);
68184 }
68185 }
68186 }
@@ -68374,16 +68757,18 @@
68757 break;
68758 }
68759
68760 /* Opcode: InitCoroutine P1 P2 P3 * *
68761 **
68762 ** Set up register P1 so that it will Yield to the coroutine
68763 ** located at address P3.
68764 **
68765 ** If P2!=0 then the coroutine implementation immediately follows
68766 ** this opcode. So jump over the coroutine implementation to
68767 ** address P2.
68768 **
68769 ** See also: EndCoroutine
68770 */
68771 case OP_InitCoroutine: { /* jump */
68772 assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
68773 assert( pOp->p2>=0 && pOp->p2<p->nOp );
68774 assert( pOp->p3>=0 && pOp->p3<p->nOp );
@@ -68395,13 +68780,15 @@
68780 break;
68781 }
68782
68783 /* Opcode: EndCoroutine P1 * * * *
68784 **
68785 ** The instruction at the address in register P1 is a Yield.
68786 ** Jump to the P2 parameter of that Yield.
68787 ** After the jump, register P1 becomes undefined.
68788 **
68789 ** See also: InitCoroutine
68790 */
68791 case OP_EndCoroutine: { /* in1 */
68792 VdbeOp *pCaller;
68793 pIn1 = &aMem[pOp->p1];
68794 assert( pIn1->flags==MEM_Int );
@@ -68414,15 +68801,20 @@
68801 break;
68802 }
68803
68804 /* Opcode: Yield P1 P2 * * *
68805 **
68806 ** Swap the program counter with the value in register P1. This
68807 ** has the effect of yielding to a coroutine.
68808 **
68809 ** If the coroutine that is launched by this instruction ends with
68810 ** Yield or Return then continue to the next instruction. But if
68811 ** the coroutine launched by this instruction ends with
68812 ** EndCoroutine, then jump to P2 rather than continuing with the
68813 ** next instruction.
68814 **
68815 ** See also: InitCoroutine
68816 */
68817 case OP_Yield: { /* in1, jump */
68818 int pcDest;
68819 pIn1 = &aMem[pOp->p1];
68820 assert( VdbeMemDynamic(pIn1)==0 );
@@ -68581,11 +68973,11 @@
68973
68974 /* Opcode: String8 * P2 * P4 *
68975 ** Synopsis: r[P2]='P4'
68976 **
68977 ** P4 points to a nul terminated UTF-8 string. This opcode is transformed
68978 ** into a String before it is executed for the first time. During
68979 ** this transformation, the length of string P4 is computed and stored
68980 ** as the P1 parameter.
68981 */
68982 case OP_String8: { /* same as TK_STRING, out2-prerelease */
68983 assert( pOp->p4.z!=0 );
@@ -69803,14 +70195,18 @@
70195 break;
70196 }
70197
70198 /* Opcode: Once P1 P2 * * *
70199 **
70200 ** Check the "once" flag number P1. If it is set, jump to instruction P2.
70201 ** Otherwise, set the flag and fall through to the next instruction.
70202 ** In other words, this opcode causes all following opcodes up through P2
70203 ** (but not including P2) to run just once and to be skipped on subsequent
70204 ** times through the loop.
70205 **
70206 ** All "once" flags are initially cleared whenever a prepared statement
70207 ** first begins to run.
70208 */
70209 case OP_Once: { /* jump */
70210 assert( pOp->p1<p->nOnceFlag );
70211 VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2);
70212 if( p->aOnceFlag[pOp->p1] ){
@@ -69823,17 +70219,17 @@
70219
70220 /* Opcode: If P1 P2 P3 * *
70221 **
70222 ** Jump to P2 if the value in register P1 is true. The value
70223 ** is considered true if it is numeric and non-zero. If the value
70224 ** in P1 is NULL then take the jump if and only if P3 is non-zero.
70225 */
70226 /* Opcode: IfNot P1 P2 P3 * *
70227 **
70228 ** Jump to P2 if the value in register P1 is False. The value
70229 ** is considered false if it has a numeric value of zero. If the value
70230 ** in P1 is NULL then take the jump if and only if P3 is non-zero.
70231 */
70232 case OP_If: /* jump, in1 */
70233 case OP_IfNot: { /* jump, in1 */
70234 int c;
70235 pIn1 = &aMem[pOp->p1];
@@ -70641,11 +71037,11 @@
71037 int iGen;
71038
71039 assert( p->bIsReader );
71040 assert( p->readOnly==0 || pOp->p2==0 );
71041 assert( pOp->p1>=0 && pOp->p1<db->nDb );
71042 assert( DbMaskTest(p->btreeMask, pOp->p1) );
71043 if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
71044 rc = SQLITE_READONLY;
71045 goto abort_due_to_error;
71046 }
71047 pBt = db->aDb[pOp->p1].pBt;
@@ -70736,11 +71132,11 @@
71132 iDb = pOp->p1;
71133 iCookie = pOp->p3;
71134 assert( pOp->p3<SQLITE_N_BTREE_META );
71135 assert( iDb>=0 && iDb<db->nDb );
71136 assert( db->aDb[iDb].pBt!=0 );
71137 assert( DbMaskTest(p->btreeMask, iDb) );
71138
71139 sqlite3BtreeGetMeta(db->aDb[iDb].pBt, iCookie, (u32 *)&iMeta);
71140 pOut->u.i = iMeta;
71141 break;
71142 }
@@ -70757,11 +71153,11 @@
71153 */
71154 case OP_SetCookie: { /* in3 */
71155 Db *pDb;
71156 assert( pOp->p2<SQLITE_N_BTREE_META );
71157 assert( pOp->p1>=0 && pOp->p1<db->nDb );
71158 assert( DbMaskTest(p->btreeMask, pOp->p1) );
71159 assert( p->readOnly==0 );
71160 pDb = &db->aDb[pOp->p1];
71161 assert( pDb->pBt!=0 );
71162 assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
71163 pIn3 = &aMem[pOp->p3];
@@ -70812,11 +71208,25 @@
71208 ** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
71209 ** structure, then said structure defines the content and collating
71210 ** sequence of the index being opened. Otherwise, if P4 is an integer
71211 ** value, it is set to the number of columns in the table.
71212 **
71213 ** See also: OpenWrite, ReopenIdx
71214 */
71215 /* Opcode: ReopenIdx P1 P2 P3 P4 P5
71216 ** Synopsis: root=P2 iDb=P3
71217 **
71218 ** The ReopenIdx opcode works exactly like ReadOpen except that it first
71219 ** checks to see if the cursor on P1 is already open with a root page
71220 ** number of P2 and if it is this opcode becomes a no-op. In other words,
71221 ** if the cursor is already open, do not reopen it.
71222 **
71223 ** The ReopenIdx opcode may only be used with P5==0 and with P4 being
71224 ** a P4_KEYINFO object. Furthermore, the P3 value must be the same as
71225 ** every other ReopenIdx or OpenRead for the same cursor number.
71226 **
71227 ** See the OpenRead opcode documentation for additional information.
71228 */
71229 /* Opcode: OpenWrite P1 P2 P3 P4 P5
71230 ** Synopsis: root=P2 iDb=P3
71231 **
71232 ** Open a read/write cursor named P1 on the table or index whose root
@@ -70834,10 +71244,23 @@
71244 ** in read/write mode. For a given table, there can be one or more read-only
71245 ** cursors or a single read/write cursor but not both.
71246 **
71247 ** See also OpenRead.
71248 */
71249 case OP_ReopenIdx: {
71250 VdbeCursor *pCur;
71251
71252 assert( pOp->p5==0 );
71253 assert( pOp->p4type==P4_KEYINFO );
71254 pCur = p->apCsr[pOp->p1];
71255 if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){
71256 assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */
71257 break;
71258 }
71259 /* If the cursor is not currently open or is open on a different
71260 ** index, then fall through into OP_OpenRead to force a reopen */
71261 }
71262 case OP_OpenRead:
71263 case OP_OpenWrite: {
71264 int nField;
71265 KeyInfo *pKeyInfo;
71266 int p2;
@@ -70848,11 +71271,12 @@
71271 Db *pDb;
71272
71273 assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 );
71274 assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 );
71275 assert( p->bIsReader );
71276 assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx
71277 || p->readOnly==0 );
71278
71279 if( p->expired ){
71280 rc = SQLITE_ABORT;
71281 break;
71282 }
@@ -70860,11 +71284,11 @@
71284 nField = 0;
71285 pKeyInfo = 0;
71286 p2 = pOp->p2;
71287 iDb = pOp->p3;
71288 assert( iDb>=0 && iDb<db->nDb );
71289 assert( DbMaskTest(p->btreeMask, iDb) );
71290 pDb = &db->aDb[iDb];
71291 pX = pDb->pBt;
71292 assert( pX!=0 );
71293 if( pOp->opcode==OP_OpenWrite ){
71294 wrFlag = 1;
@@ -70905,10 +71329,11 @@
71329 testcase( nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */
71330 pCur = allocateCursor(p, pOp->p1, nField, iDb, 1);
71331 if( pCur==0 ) goto no_mem;
71332 pCur->nullRow = 1;
71333 pCur->isOrdered = 1;
71334 pCur->pgnoRoot = p2;
71335 rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor);
71336 pCur->pKeyInfo = pKeyInfo;
71337 assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
71338 sqlite3BtreeCursorHints(pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
71339
@@ -71059,11 +71484,11 @@
71484 sqlite3VdbeFreeCursor(p, p->apCsr[pOp->p1]);
71485 p->apCsr[pOp->p1] = 0;
71486 break;
71487 }
71488
71489 /* Opcode: SeekGE P1 P2 P3 P4 *
71490 ** Synopsis: key=r[P3@P4]
71491 **
71492 ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
71493 ** use the value in register P3 as the key. If cursor P1 refers
71494 ** to an SQL index, then P3 is the first in an array of P4 registers
@@ -71070,14 +71495,18 @@
71495 ** that are used as an unpacked index key.
71496 **
71497 ** Reposition cursor P1 so that it points to the smallest entry that
71498 ** is greater than or equal to the key value. If there are no records
71499 ** greater than or equal to the key and P2 is not zero, then jump to P2.
71500 **
71501 ** This opcode leaves the cursor configured to move in forward order,
71502 ** from the beginning toward the end. In other words, the cursor is
71503 ** configured to use Next, not Prev.
71504 **
71505 ** See also: Found, NotFound, SeekLt, SeekGt, SeekLe
71506 */
71507 /* Opcode: SeekGT P1 P2 P3 P4 *
71508 ** Synopsis: key=r[P3@P4]
71509 **
71510 ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
71511 ** use the value in register P3 as a key. If cursor P1 refers
71512 ** to an SQL index, then P3 is the first in an array of P4 registers
@@ -71084,14 +71513,18 @@
71513 ** that are used as an unpacked index key.
71514 **
71515 ** Reposition cursor P1 so that it points to the smallest entry that
71516 ** is greater than the key value. If there are no records greater than
71517 ** the key and P2 is not zero, then jump to P2.
71518 **
71519 ** This opcode leaves the cursor configured to move in forward order,
71520 ** from the begining toward the end. In other words, the cursor is
71521 ** configured to use Next, not Prev.
71522 **
71523 ** See also: Found, NotFound, SeekLt, SeekGe, SeekLe
71524 */
71525 /* Opcode: SeekLT P1 P2 P3 P4 *
71526 ** Synopsis: key=r[P3@P4]
71527 **
71528 ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
71529 ** use the value in register P3 as a key. If cursor P1 refers
71530 ** to an SQL index, then P3 is the first in an array of P4 registers
@@ -71098,14 +71531,18 @@
71531 ** that are used as an unpacked index key.
71532 **
71533 ** Reposition cursor P1 so that it points to the largest entry that
71534 ** is less than the key value. If there are no records less than
71535 ** the key and P2 is not zero, then jump to P2.
71536 **
71537 ** This opcode leaves the cursor configured to move in reverse order,
71538 ** from the end toward the beginning. In other words, the cursor is
71539 ** configured to use Prev, not Next.
71540 **
71541 ** See also: Found, NotFound, SeekGt, SeekGe, SeekLe
71542 */
71543 /* Opcode: SeekLE P1 P2 P3 P4 *
71544 ** Synopsis: key=r[P3@P4]
71545 **
71546 ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
71547 ** use the value in register P3 as a key. If cursor P1 refers
71548 ** to an SQL index, then P3 is the first in an array of P4 registers
@@ -71112,10 +71549,14 @@
71549 ** that are used as an unpacked index key.
71550 **
71551 ** Reposition cursor P1 so that it points to the largest entry that
71552 ** is less than or equal to the key value. If there are no records
71553 ** less than or equal to the key and P2 is not zero, then jump to P2.
71554 **
71555 ** This opcode leaves the cursor configured to move in reverse order,
71556 ** from the end toward the beginning. In other words, the cursor is
71557 ** configured to use Prev, not Next.
71558 **
71559 ** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
71560 */
71561 case OP_SeekLT: /* jump, in3 */
71562 case OP_SeekLE: /* jump, in3 */
@@ -71138,16 +71579,19 @@
71579 assert( OP_SeekGT == OP_SeekLT+3 );
71580 assert( pC->isOrdered );
71581 assert( pC->pCursor!=0 );
71582 oc = pOp->opcode;
71583 pC->nullRow = 0;
71584 #ifdef SQLITE_DEBUG
71585 pC->seekOp = pOp->opcode;
71586 #endif
71587 if( pC->isTable ){
71588 /* The input value in P3 might be of any type: integer, real, string,
71589 ** blob, or NULL. But it needs to be an integer before we can do
71590 ** the seek, so covert it. */
71591 pIn3 = &aMem[pOp->p3];
71592 ApplyNumericAffinity(pIn3);
71593 iKey = sqlite3VdbeIntValue(pIn3);
71594 pC->rowidIsValid = 0;
71595
71596 /* If the P3 value could not be converted into an integer without
71597 ** loss of information, then special processing is required... */
@@ -71292,10 +71736,14 @@
71736 ** record.
71737 **
71738 ** Cursor P1 is on an index btree. If the record identified by P3 and P4
71739 ** is a prefix of any entry in P1 then a jump is made to P2 and
71740 ** P1 is left pointing at the matching entry.
71741 **
71742 ** This operation leaves the cursor in a state where it can be
71743 ** advanced in the forward direction. The Next instruction will work,
71744 ** but not the Prev instruction.
71745 **
71746 ** See also: NotFound, NoConflict, NotExists. SeekGe
71747 */
71748 /* Opcode: NotFound P1 P2 P3 P4 *
71749 ** Synopsis: key=r[P3@P4]
@@ -71307,10 +71755,14 @@
71755 ** Cursor P1 is on an index btree. If the record identified by P3 and P4
71756 ** is not the prefix of any entry in P1 then a jump is made to P2. If P1
71757 ** does contain an entry whose prefix matches the P3/P4 record then control
71758 ** falls through to the next instruction and P1 is left pointing at the
71759 ** matching entry.
71760 **
71761 ** This operation leaves the cursor in a state where it cannot be
71762 ** advanced in either direction. In other words, the Next and Prev
71763 ** opcodes do not work after this operation.
71764 **
71765 ** See also: Found, NotExists, NoConflict
71766 */
71767 /* Opcode: NoConflict P1 P2 P3 P4 *
71768 ** Synopsis: key=r[P3@P4]
@@ -71326,10 +71778,14 @@
71778 ** immediately to P2. If there is a match, fall through and leave the P1
71779 ** cursor pointing to the matching row.
71780 **
71781 ** This opcode is similar to OP_NotFound with the exceptions that the
71782 ** branch is always taken if any part of the search key input is NULL.
71783 **
71784 ** This operation leaves the cursor in a state where it cannot be
71785 ** advanced in either direction. In other words, the Next and Prev
71786 ** opcodes do not work after this operation.
71787 **
71788 ** See also: NotFound, Found, NotExists
71789 */
71790 case OP_NoConflict: /* jump, in3 */
71791 case OP_NotFound: /* jump, in3 */
@@ -71349,10 +71805,13 @@
71805
71806 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
71807 assert( pOp->p4type==P4_INT32 );
71808 pC = p->apCsr[pOp->p1];
71809 assert( pC!=0 );
71810 #ifdef SQLITE_DEBUG
71811 pC->seekOp = pOp->opcode;
71812 #endif
71813 pIn3 = &aMem[pOp->p3];
71814 assert( pC->pCursor!=0 );
71815 assert( pC->isTable==0 );
71816 pFree = 0; /* Not needed. Only used to suppress a compiler warning. */
71817 if( pOp->p4.i>0 ){
@@ -71419,10 +71878,14 @@
71878 ** with rowid P3 then leave the cursor pointing at that record and fall
71879 ** through to the next instruction.
71880 **
71881 ** The OP_NotFound opcode performs the same operation on index btrees
71882 ** (with arbitrary multi-value keys).
71883 **
71884 ** This opcode leaves the cursor in a state where it cannot be advanced
71885 ** in either direction. In other words, the Next and Prev opcodes will
71886 ** not work following this opcode.
71887 **
71888 ** See also: Found, NotFound, NoConflict
71889 */
71890 case OP_NotExists: { /* jump, in3 */
71891 VdbeCursor *pC;
@@ -71433,10 +71896,13 @@
71896 pIn3 = &aMem[pOp->p3];
71897 assert( pIn3->flags & MEM_Int );
71898 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
71899 pC = p->apCsr[pOp->p1];
71900 assert( pC!=0 );
71901 #ifdef SQLITE_DEBUG
71902 pC->seekOp = 0;
71903 #endif
71904 assert( pC->isTable );
71905 assert( pC->pseudoTableReg==0 );
71906 pCrsr = pC->pCursor;
71907 assert( pCrsr!=0 );
71908 res = 0;
@@ -71735,11 +72201,11 @@
72201 ** Delete the record at which the P1 cursor is currently pointing.
72202 **
72203 ** The cursor will be left pointing at either the next or the previous
72204 ** record in the table. If it is left pointing at the next record, then
72205 ** the next Next instruction will be a no-op. Hence it is OK to delete
72206 ** a record from within a Next loop.
72207 **
72208 ** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is
72209 ** incremented (otherwise not).
72210 **
72211 ** P1 must not be pseudo-table. It has to be a real table with
@@ -71795,16 +72261,16 @@
72261 p->nChange = 0;
72262 break;
72263 }
72264
72265 /* Opcode: SorterCompare P1 P2 P3 P4
72266 ** Synopsis: if key(P1)!=trim(r[P3],P4) goto P2
72267 **
72268 ** P1 is a sorter cursor. This instruction compares a prefix of the
72269 ** record blob in register P3 against a prefix of the entry that
72270 ** the sorter cursor currently points to. Only the first P4 fields
72271 ** of r[P3] and the sorter record are compared.
72272 **
72273 ** If either P3 or the sorter contains a NULL in one of their significant
72274 ** fields (not counting the P4 fields at the end which are ignored) then
72275 ** the comparison is assumed to be equal.
72276 **
@@ -71812,18 +72278,18 @@
72278 ** each other. Jump to P2 if they are different.
72279 */
72280 case OP_SorterCompare: {
72281 VdbeCursor *pC;
72282 int res;
72283 int nKeyCol;
72284
72285 pC = p->apCsr[pOp->p1];
72286 assert( isSorter(pC) );
72287 assert( pOp->p4type==P4_INT32 );
72288 pIn3 = &aMem[pOp->p3];
72289 nKeyCol = pOp->p4.i;
72290 rc = sqlite3VdbeSorterCompare(pC, pIn3, nKeyCol, &res);
72291 VdbeBranchTaken(res!=0,2);
72292 if( res ){
72293 pc = pOp->p2-1;
72294 }
72295 break;
@@ -71999,15 +72465,19 @@
72465 break;
72466 }
72467
72468 /* Opcode: Last P1 P2 * * *
72469 **
72470 ** The next use of the Rowid or Column or Prev instruction for P1
72471 ** will refer to the last entry in the database table or index.
72472 ** If the table or index is empty and P2>0, then jump immediately to P2.
72473 ** If P2 is 0 or if the table or index is not empty, fall through
72474 ** to the following instruction.
72475 **
72476 ** This opcode leaves the cursor configured to move in reverse order,
72477 ** from the end toward the beginning. In other words, the cursor is
72478 ** configured to use Prev, not Next.
72479 */
72480 case OP_Last: { /* jump */
72481 VdbeCursor *pC;
72482 BtCursor *pCrsr;
72483 int res;
@@ -72021,10 +72491,13 @@
72491 rc = sqlite3BtreeLast(pCrsr, &res);
72492 pC->nullRow = (u8)res;
72493 pC->deferredMoveto = 0;
72494 pC->rowidIsValid = 0;
72495 pC->cacheStatus = CACHE_STALE;
72496 #ifdef SQLITE_DEBUG
72497 pC->seekOp = OP_Last;
72498 #endif
72499 if( pOp->p2>0 ){
72500 VdbeBranchTaken(res!=0,2);
72501 if( res ) pc = pOp->p2 - 1;
72502 }
72503 break;
@@ -72057,10 +72530,14 @@
72530 ** The next use of the Rowid or Column or Next instruction for P1
72531 ** will refer to the first entry in the database table or index.
72532 ** If the table or index is empty and P2>0, then jump immediately to P2.
72533 ** If P2 is 0 or if the table or index is not empty, fall through
72534 ** to the following instruction.
72535 **
72536 ** This opcode leaves the cursor configured to move in forward order,
72537 ** from the begining toward the end. In other words, the cursor is
72538 ** configured to use Next, not Prev.
72539 */
72540 case OP_Rewind: { /* jump */
72541 VdbeCursor *pC;
72542 BtCursor *pCrsr;
72543 int res;
@@ -72068,10 +72545,13 @@
72545 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
72546 pC = p->apCsr[pOp->p1];
72547 assert( pC!=0 );
72548 assert( isSorter(pC)==(pOp->opcode==OP_SorterSort) );
72549 res = 1;
72550 #ifdef SQLITE_DEBUG
72551 pC->seekOp = OP_Rewind;
72552 #endif
72553 if( isSorter(pC) ){
72554 rc = sqlite3VdbeSorterRewind(db, pC, &res);
72555 }else{
72556 pCrsr = pC->pCursor;
72557 assert( pCrsr );
@@ -72093,10 +72573,14 @@
72573 **
72574 ** Advance cursor P1 so that it points to the next key/data pair in its
72575 ** table or index. If there are no more key/value pairs then fall through
72576 ** to the following instruction. But if the cursor advance was successful,
72577 ** jump immediately to P2.
72578 **
72579 ** The Next opcode is only valid following an SeekGT, SeekGE, or
72580 ** OP_Rewind opcode used to position the cursor. Next is not allowed
72581 ** to follow SeekLT, SeekLE, or OP_Last.
72582 **
72583 ** The P1 cursor must be for a real table, not a pseudo-table. P1 must have
72584 ** been opened prior to this opcode or the program will segfault.
72585 **
72586 ** The P3 value is a hint to the btree implementation. If P3==1, that
@@ -72112,20 +72596,25 @@
72596 **
72597 ** See also: Prev, NextIfOpen
72598 */
72599 /* Opcode: NextIfOpen P1 P2 P3 P4 P5
72600 **
72601 ** This opcode works just like Next except that if cursor P1 is not
72602 ** open it behaves a no-op.
72603 */
72604 /* Opcode: Prev P1 P2 P3 P4 P5
72605 **
72606 ** Back up cursor P1 so that it points to the previous key/data pair in its
72607 ** table or index. If there is no previous key/value pairs then fall through
72608 ** to the following instruction. But if the cursor backup was successful,
72609 ** jump immediately to P2.
72610 **
72611 **
72612 ** The Prev opcode is only valid following an SeekLT, SeekLE, or
72613 ** OP_Last opcode used to position the cursor. Prev is not allowed
72614 ** to follow SeekGT, SeekGE, or OP_Rewind.
72615 **
72616 ** The P1 cursor must be for a real table, not a pseudo-table. If P1 is
72617 ** not open then the behavior is undefined.
72618 **
72619 ** The P3 value is a hint to the btree implementation. If P3==1, that
72620 ** means P1 is an SQL index and that this instruction could have been
@@ -72138,11 +72627,11 @@
72627 ** If P5 is positive and the jump is taken, then event counter
72628 ** number P5-1 in the prepared statement is incremented.
72629 */
72630 /* Opcode: PrevIfOpen P1 P2 P3 P4 P5
72631 **
72632 ** This opcode works just like Prev except that if cursor P1 is not
72633 ** open it behaves a no-op.
72634 */
72635 case OP_SorterNext: { /* jump */
72636 VdbeCursor *pC;
72637 int res;
@@ -72169,10 +72658,20 @@
72658 testcase( res==1 );
72659 assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
72660 assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
72661 assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext );
72662 assert( pOp->opcode!=OP_PrevIfOpen || pOp->p4.xAdvance==sqlite3BtreePrevious);
72663
72664 /* The Next opcode is only used after SeekGT, SeekGE, and Rewind.
72665 ** The Prev opcode is only used after SeekLT, SeekLE, and Last. */
72666 assert( pOp->opcode!=OP_Next || pOp->opcode!=OP_NextIfOpen
72667 || pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE
72668 || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found);
72669 assert( pOp->opcode!=OP_Prev || pOp->opcode!=OP_PrevIfOpen
72670 || pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
72671 || pC->seekOp==OP_Last );
72672
72673 rc = pOp->p4.xAdvance(pC->pCursor, &res);
72674 next_tail:
72675 pC->cacheStatus = CACHE_STALE;
72676 VdbeBranchTaken(res==0,2);
72677 if( res==0 ){
@@ -72451,11 +72950,11 @@
72950 rc = SQLITE_LOCKED;
72951 p->errorAction = OE_Abort;
72952 }else{
72953 iDb = pOp->p3;
72954 assert( iCnt==1 );
72955 assert( DbMaskTest(p->btreeMask, iDb) );
72956 iMoved = 0; /* Not needed. Only to silence a warning. */
72957 rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved);
72958 pOut->flags = MEM_Int;
72959 pOut->u.i = iMoved;
72960 #ifndef SQLITE_OMIT_AUTOVACUUM
@@ -72491,11 +72990,11 @@
72990 case OP_Clear: {
72991 int nChange;
72992
72993 nChange = 0;
72994 assert( p->readOnly==0 );
72995 assert( DbMaskTest(p->btreeMask, pOp->p2) );
72996 rc = sqlite3BtreeClearTable(
72997 db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0)
72998 );
72999 if( pOp->p3 ){
73000 p->nChange += nChange;
@@ -72561,11 +73060,11 @@
73060 int flags;
73061 Db *pDb;
73062
73063 pgno = 0;
73064 assert( pOp->p1>=0 && pOp->p1<db->nDb );
73065 assert( DbMaskTest(p->btreeMask, pOp->p1) );
73066 assert( p->readOnly==0 );
73067 pDb = &db->aDb[pOp->p1];
73068 assert( pDb->pBt!=0 );
73069 if( pOp->opcode==OP_CreateTable ){
73070 /* flags = BTREE_INTKEY; */
@@ -72649,11 +73148,12 @@
73148
73149 /* Opcode: DropTable P1 * * P4 *
73150 **
73151 ** Remove the internal (in-memory) data structures that describe
73152 ** the table named P4 in database P1. This is called after a table
73153 ** is dropped from disk (using the Destroy opcode) in order to keep
73154 ** the internal representation of the
73155 ** schema consistent with what is on disk.
73156 */
73157 case OP_DropTable: {
73158 sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p4.z);
73159 break;
@@ -72661,11 +73161,12 @@
73161
73162 /* Opcode: DropIndex P1 * * P4 *
73163 **
73164 ** Remove the internal (in-memory) data structures that describe
73165 ** the index named P4 in database P1. This is called after an index
73166 ** is dropped from disk (using the Destroy opcode)
73167 ** in order to keep the internal representation of the
73168 ** schema consistent with what is on disk.
73169 */
73170 case OP_DropIndex: {
73171 sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p4.z);
73172 break;
@@ -72673,11 +73174,12 @@
73174
73175 /* Opcode: DropTrigger P1 * * P4 *
73176 **
73177 ** Remove the internal (in-memory) data structures that describe
73178 ** the trigger named P4 in database P1. This is called after a trigger
73179 ** is dropped from disk (using the Destroy opcode) in order to keep
73180 ** the internal representation of the
73181 ** schema consistent with what is on disk.
73182 */
73183 case OP_DropTrigger: {
73184 sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p4.z);
73185 break;
@@ -72726,11 +73228,11 @@
73228 for(j=0; j<nRoot; j++){
73229 aRoot[j] = (int)sqlite3VdbeIntValue(&pIn1[j]);
73230 }
73231 aRoot[j] = 0;
73232 assert( pOp->p5<db->nDb );
73233 assert( DbMaskTest(p->btreeMask, pOp->p5) );
73234 z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot,
73235 (int)pnErr->u.i, &nErr);
73236 sqlite3DbFree(db, aRoot);
73237 pnErr->u.i -= nErr;
73238 sqlite3VdbeMemSetNull(pIn1);
@@ -73088,21 +73590,20 @@
73590 pc = pOp->p2 - 1;
73591 }
73592 break;
73593 }
73594
73595 /* Opcode: IfNeg P1 P2 P3 * *
73596 ** Synopsis: r[P1]+=P3, if r[P1]<0 goto P2
73597 **
73598 ** Register P1 must contain an integer. Add literal P3 to the value in
73599 ** register P1 then if the value of register P1 is less than zero, jump to P2.
 
 
73600 */
73601 case OP_IfNeg: { /* jump, in1 */
73602 pIn1 = &aMem[pOp->p1];
73603 assert( pIn1->flags&MEM_Int );
73604 pIn1->u.i += pOp->p3;
73605 VdbeBranchTaken(pIn1->u.i<0, 2);
73606 if( pIn1->u.i<0 ){
73607 pc = pOp->p2 - 1;
73608 }
73609 break;
@@ -73111,13 +73612,10 @@
73612 /* Opcode: IfZero P1 P2 P3 * *
73613 ** Synopsis: r[P1]+=P3, if r[P1]==0 goto P2
73614 **
73615 ** The register P1 must contain an integer. Add literal P3 to the
73616 ** value in register P1. If the result is exactly 0, jump to P2.
 
 
 
73617 */
73618 case OP_IfZero: { /* jump, in1 */
73619 pIn1 = &aMem[pOp->p1];
73620 assert( pIn1->flags&MEM_Int );
73621 pIn1->u.i += pOp->p3;
@@ -73386,11 +73884,11 @@
73884 */
73885 case OP_IncrVacuum: { /* jump */
73886 Btree *pBt;
73887
73888 assert( pOp->p1>=0 && pOp->p1<db->nDb );
73889 assert( DbMaskTest(p->btreeMask, pOp->p1) );
73890 assert( p->readOnly==0 );
73891 pBt = db->aDb[pOp->p1].pBt;
73892 rc = sqlite3BtreeIncrVacuum(pBt);
73893 VdbeBranchTaken(rc==SQLITE_DONE,2);
73894 if( rc==SQLITE_DONE ){
@@ -73401,16 +73899,17 @@
73899 }
73900 #endif
73901
73902 /* Opcode: Expire P1 * * * *
73903 **
73904 ** Cause precompiled statements to expire. When an expired statement
73905 ** is executed using sqlite3_step() it will either automatically
73906 ** reprepare itself (if it was originally created using sqlite3_prepare_v2())
73907 ** or it will fail with SQLITE_SCHEMA.
73908 **
73909 ** If P1 is 0, then all SQL statements become expired. If P1 is non-zero,
73910 ** then only the currently executing statement is expired.
73911 */
73912 case OP_Expire: {
73913 if( !pOp->p1 ){
73914 sqlite3ExpirePreparedStatements(db);
73915 }else{
@@ -73438,11 +73937,11 @@
73937 case OP_TableLock: {
73938 u8 isWriteLock = (u8)pOp->p3;
73939 if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){
73940 int p1 = pOp->p1;
73941 assert( p1>=0 && p1<db->nDb );
73942 assert( DbMaskTest(p->btreeMask, p1) );
73943 assert( isWriteLock==0 || isWriteLock==1 );
73944 rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock);
73945 if( (rc&0xFF)==SQLITE_LOCKED ){
73946 const char *z = pOp->p4.z;
73947 sqlite3SetString(&p->zErrMsg, db, "database table is locked: %s", z);
@@ -73888,11 +74387,11 @@
74387 #ifdef SQLITE_USE_FCNTL_TRACE
74388 zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
74389 if( zTrace ){
74390 int i;
74391 for(i=0; i<db->nDb; i++){
74392 if( DbMaskTest(p->btreeMask, i)==0 ) continue;
74393 sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace);
74394 }
74395 }
74396 #endif /* SQLITE_USE_FCNTL_TRACE */
74397 #ifdef SQLITE_DEBUG
@@ -74878,11 +75377,11 @@
75377 ** If pKey2 is passed a NULL pointer, then it is assumed that the pCsr->aSpace
75378 ** has been allocated and contains an unpacked record that is used as key2.
75379 */
75380 static void vdbeSorterCompare(
75381 const VdbeCursor *pCsr, /* Cursor object (for pKeyInfo) */
75382 int nKeyCol, /* Num of columns. 0 means "all" */
75383 const void *pKey1, int nKey1, /* Left side of comparison */
75384 const void *pKey2, int nKey2, /* Right side of comparison */
75385 int *pRes /* OUT: Result of comparison */
75386 ){
75387 KeyInfo *pKeyInfo = pCsr->pKeyInfo;
@@ -74892,14 +75391,13 @@
75391
75392 if( pKey2 ){
75393 sqlite3VdbeRecordUnpack(pKeyInfo, nKey2, pKey2, r2);
75394 }
75395
75396 if( nKeyCol ){
75397 r2->nField = nKeyCol;
75398 for(i=0; i<nKeyCol; i++){
 
75399 if( r2->aMem[i].flags & MEM_Null ){
75400 *pRes = -1;
75401 return;
75402 }
75403 }
@@ -75577,18 +76075,18 @@
76075 ** key.
76076 */
76077 SQLITE_PRIVATE int sqlite3VdbeSorterCompare(
76078 const VdbeCursor *pCsr, /* Sorter cursor */
76079 Mem *pVal, /* Value to compare to current sorter key */
76080 int nKeyCol, /* Only compare this many fields */
76081 int *pRes /* OUT: Result of comparison */
76082 ){
76083 VdbeSorter *pSorter = pCsr->pSorter;
76084 void *pKey; int nKey; /* Sorter key to compare pVal with */
76085
76086 pKey = vdbeSorterRowkey(pSorter, &nKey);
76087 vdbeSorterCompare(pCsr, nKeyCol, pVal->z, pVal->n, pKey, nKey, pRes);
76088 return SQLITE_OK;
76089 }
76090
76091 /************** End of vdbesort.c ********************************************/
76092 /************** Begin file journal.c *****************************************/
@@ -76616,11 +77114,11 @@
77114 }
77115 break;
77116 }
77117 }
77118 if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && HasRowid(pTab) ){
77119 /* IMP: R-51414-32910 */
77120 /* IMP: R-44911-55124 */
77121 iCol = -1;
77122 }
77123 if( iCol<pTab->nCol ){
77124 cnt++;
@@ -76972,11 +77470,15 @@
77470 }
77471 }else{
77472 /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is equivalent to
77473 ** likelihood(X, 0.0625).
77474 ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is short-hand for
77475 ** likelihood(X,0.0625).
77476 ** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand for
77477 ** likelihood(X,0.9375).
77478 ** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent to
77479 ** likelihood(X,0.9375). */
77480 /* TUNING: unlikely() probability is 0.0625. likely() is 0.9375 */
77481 pExpr->iTable = pDef->zName[0]=='u' ? 62 : 938;
77482 }
77483 }
77484 }
@@ -79085,10 +79587,13 @@
79587 case TK_INTEGER:
79588 case TK_STRING:
79589 case TK_FLOAT:
79590 case TK_BLOB:
79591 return 0;
79592 case TK_COLUMN:
79593 assert( p->pTab!=0 );
79594 return p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0;
79595 default:
79596 return 1;
79597 }
79598 }
79599
@@ -79192,83 +79697,124 @@
79697 SQLITE_PRIVATE int sqlite3CodeOnce(Parse *pParse){
79698 Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
79699 return sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++);
79700 }
79701
79702 /*
79703 ** Generate code that checks the left-most column of index table iCur to see if
79704 ** it contains any NULL entries. Cause the register at regHasNull to be set
79705 ** to a non-NULL value if iCur contains no NULLs. Cause register regHasNull
79706 ** to be set to NULL if iCur contains one or more NULL values.
79707 */
79708 static void sqlite3SetHasNullFlag(Vdbe *v, int iCur, int regHasNull){
79709 int j1;
79710 sqlite3VdbeAddOp2(v, OP_Integer, 0, regHasNull);
79711 j1 = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
79712 sqlite3VdbeAddOp3(v, OP_Column, iCur, 0, regHasNull);
79713 sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
79714 VdbeComment((v, "first_entry_in(%d)", iCur));
79715 sqlite3VdbeJumpHere(v, j1);
79716 }
79717
79718
79719 #ifndef SQLITE_OMIT_SUBQUERY
79720 /*
79721 ** The argument is an IN operator with a list (not a subquery) on the
79722 ** right-hand side. Return TRUE if that list is constant.
79723 */
79724 static int sqlite3InRhsIsConstant(Expr *pIn){
79725 Expr *pLHS;
79726 int res;
79727 assert( !ExprHasProperty(pIn, EP_xIsSelect) );
79728 pLHS = pIn->pLeft;
79729 pIn->pLeft = 0;
79730 res = sqlite3ExprIsConstant(pIn);
79731 pIn->pLeft = pLHS;
79732 return res;
79733 }
79734 #endif
79735
79736 /*
79737 ** This function is used by the implementation of the IN (...) operator.
79738 ** The pX parameter is the expression on the RHS of the IN operator, which
79739 ** might be either a list of expressions or a subquery.
79740 **
79741 ** The job of this routine is to find or create a b-tree object that can
79742 ** be used either to test for membership in the RHS set or to iterate through
79743 ** all members of the RHS set, skipping duplicates.
79744 **
79745 ** A cursor is opened on the b-tree object that is the RHS of the IN operator
79746 ** and pX->iTable is set to the index of that cursor.
79747 **
79748 ** The returned value of this function indicates the b-tree type, as follows:
79749 **
79750 ** IN_INDEX_ROWID - The cursor was opened on a database table.
79751 ** IN_INDEX_INDEX_ASC - The cursor was opened on an ascending index.
79752 ** IN_INDEX_INDEX_DESC - The cursor was opened on a descending index.
79753 ** IN_INDEX_EPH - The cursor was opened on a specially created and
79754 ** populated epheremal table.
79755 ** IN_INDEX_NOOP - No cursor was allocated. The IN operator must be
79756 ** implemented as a sequence of comparisons.
79757 **
79758 ** An existing b-tree might be used if the RHS expression pX is a simple
79759 ** subquery such as:
79760 **
79761 ** SELECT <column> FROM <table>
79762 **
79763 ** If the RHS of the IN operator is a list or a more complex subquery, then
79764 ** an ephemeral table might need to be generated from the RHS and then
79765 ** pX->iTable made to point to the ephermeral table instead of an
79766 ** existing table.
79767 **
79768 ** The inFlags parameter must contain exactly one of the bits
79769 ** IN_INDEX_MEMBERSHIP or IN_INDEX_LOOP. If inFlags contains
79770 ** IN_INDEX_MEMBERSHIP, then the generated table will be used for a
79771 ** fast membership test. When the IN_INDEX_LOOP bit is set, the
79772 ** IN index will be used to loop over all values of the RHS of the
79773 ** IN operator.
79774 **
79775 ** When IN_INDEX_LOOP is used (and the b-tree will be used to iterate
79776 ** through the set members) then the b-tree must not contain duplicates.
79777 ** An epheremal table must be used unless the selected <column> is guaranteed
79778 ** to be unique - either because it is an INTEGER PRIMARY KEY or it
79779 ** has a UNIQUE constraint or UNIQUE index.
79780 **
79781 ** When IN_INDEX_MEMBERSHIP is used (and the b-tree will be used
79782 ** for fast set membership tests) then an epheremal table must
79783 ** be used unless <column> is an INTEGER PRIMARY KEY or an index can
79784 ** be found with <column> as its left-most column.
79785 **
79786 ** If the IN_INDEX_NOOP_OK and IN_INDEX_MEMBERSHIP are both set and
79787 ** if the RHS of the IN operator is a list (not a subquery) then this
79788 ** routine might decide that creating an ephemeral b-tree for membership
79789 ** testing is too expensive and return IN_INDEX_NOOP. In that case, the
79790 ** calling routine should implement the IN operator using a sequence
79791 ** of Eq or Ne comparison operations.
79792 **
79793 ** When the b-tree is being used for membership tests, the calling function
79794 ** might need to know whether or not the RHS side of the IN operator
79795 ** contains a NULL. If prRhsHasNull is not a NULL pointer and
79796 ** if there is any chance that the (...) might contain a NULL value at
79797 ** runtime, then a register is allocated and the register number written
79798 ** to *prRhsHasNull. If there is no chance that the (...) contains a
79799 ** NULL value, then *prRhsHasNull is left unchanged.
79800 **
79801 ** If a register is allocated and its location stored in *prRhsHasNull, then
79802 ** the value in that register will be NULL if the b-tree contains one or more
79803 ** NULL values, and it will be some non-NULL value if the b-tree contains no
79804 ** NULL values.
 
 
 
 
 
 
 
 
 
 
79805 */
79806 #ifndef SQLITE_OMIT_SUBQUERY
79807 SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){
79808 Select *p; /* SELECT to the right of IN operator */
79809 int eType = 0; /* Type of RHS table. IN_INDEX_* */
79810 int iTab = pParse->nTab++; /* Cursor of the RHS table */
79811 int mustBeUnique; /* True if RHS must be unique */
79812 Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
79813
79814 assert( pX->op==TK_IN );
79815 mustBeUnique = (inFlags & IN_INDEX_LOOP)!=0;
79816
79817 /* Check to see if an existing table or index can be used to
79818 ** satisfy the query. This is preferable to generating a new
79819 ** ephemeral table.
79820 */
@@ -79321,44 +79867,59 @@
79867 int affinity_ok = sqlite3IndexAffinityOk(pX, pTab->aCol[iCol].affinity);
79868
79869 for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){
79870 if( (pIdx->aiColumn[0]==iCol)
79871 && sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq
79872 && (!mustBeUnique || (pIdx->nKeyCol==1 && IsUniqueIndex(pIdx)))
79873 ){
79874 int iAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
79875 sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb);
79876 sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
79877 VdbeComment((v, "%s", pIdx->zName));
79878 assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 );
79879 eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0];
79880
79881 if( prRhsHasNull && !pTab->aCol[iCol].notNull ){
79882 *prRhsHasNull = ++pParse->nMem;
79883 sqlite3SetHasNullFlag(v, iTab, *prRhsHasNull);
79884 }
79885 sqlite3VdbeJumpHere(v, iAddr);
79886 }
79887 }
79888 }
79889 }
79890
79891 /* If no preexisting index is available for the IN clause
79892 ** and IN_INDEX_NOOP is an allowed reply
79893 ** and the RHS of the IN operator is a list, not a subquery
79894 ** and the RHS is not contant or has two or fewer terms,
79895 ** then it is not worth creating an ephermeral table to evaluate
79896 ** the IN operator so return IN_INDEX_NOOP.
79897 */
79898 if( eType==0
79899 && (inFlags & IN_INDEX_NOOP_OK)
79900 && !ExprHasProperty(pX, EP_xIsSelect)
79901 && (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2)
79902 ){
79903 eType = IN_INDEX_NOOP;
79904 }
79905
79906
79907 if( eType==0 ){
79908 /* Could not find an existing table or index to use as the RHS b-tree.
79909 ** We will have to generate an ephemeral table to do the job.
79910 */
79911 u32 savedNQueryLoop = pParse->nQueryLoop;
79912 int rMayHaveNull = 0;
79913 eType = IN_INDEX_EPH;
79914 if( inFlags & IN_INDEX_LOOP ){
 
 
 
79915 pParse->nQueryLoop = 0;
79916 if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){
79917 eType = IN_INDEX_ROWID;
79918 }
79919 }else if( prRhsHasNull ){
79920 *prRhsHasNull = rMayHaveNull = ++pParse->nMem;
79921 }
79922 sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID);
79923 pParse->nQueryLoop = savedNQueryLoop;
79924 }else{
79925 pX->iTable = iTab;
@@ -79385,31 +79946,25 @@
79946 ** intkey B-Tree to store the set of IN(...) values instead of the usual
79947 ** (slower) variable length keys B-Tree.
79948 **
79949 ** If rMayHaveNull is non-zero, that means that the operation is an IN
79950 ** (not a SELECT or EXISTS) and that the RHS might contains NULLs.
79951 ** All this routine does is initialize the register given by rMayHaveNull
79952 ** to NULL. Calling routines will take care of changing this register
79953 ** value to non-NULL if the RHS is NULL-free.
 
 
 
 
 
 
79954 **
79955 ** For a SELECT or EXISTS operator, return the register that holds the
79956 ** result. For IN operators or if an error occurs, the return value is 0.
79957 */
79958 #ifndef SQLITE_OMIT_SUBQUERY
79959 SQLITE_PRIVATE int sqlite3CodeSubselect(
79960 Parse *pParse, /* Parsing context */
79961 Expr *pExpr, /* The IN, SELECT, or EXISTS operator */
79962 int rHasNullFlag, /* Register that records whether NULLs exist in RHS */
79963 int isRowid /* If true, LHS of IN operator is a rowid */
79964 ){
79965 int jmpIfDynamic = -1; /* One-time test address */
79966 int rReg = 0; /* Register storing resulting */
79967 Vdbe *v = sqlite3GetVdbe(pParse);
79968 if( NEVER(v==0) ) return 0;
79969 sqlite3ExprCachePush(pParse);
79970
@@ -79422,17 +79977,17 @@
79977 **
79978 ** If all of the above are false, then we can run this code just once
79979 ** save the results, and reuse the same result on subsequent invocations.
79980 */
79981 if( !ExprHasProperty(pExpr, EP_VarSelect) ){
79982 jmpIfDynamic = sqlite3CodeOnce(pParse); VdbeCoverage(v);
79983 }
79984
79985 #ifndef SQLITE_OMIT_EXPLAIN
79986 if( pParse->explain==2 ){
79987 char *zMsg = sqlite3MPrintf(
79988 pParse->db, "EXECUTE %s%s SUBQUERY %d", jmpIfDynamic>=0?"":"CORRELATED ",
79989 pExpr->op==TK_IN?"LIST":"SCALAR", pParse->iNextSelectId
79990 );
79991 sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
79992 }
79993 #endif
@@ -79442,14 +79997,10 @@
79997 char affinity; /* Affinity of the LHS of the IN */
79998 int addr; /* Address of OP_OpenEphemeral instruction */
79999 Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */
80000 KeyInfo *pKeyInfo = 0; /* Key information */
80001
 
 
 
 
80002 affinity = sqlite3ExprAffinity(pLeft);
80003
80004 /* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
80005 ** expression it is handled the same way. An ephemeral table is
80006 ** filled with single-field index keys representing the results
@@ -79471,24 +80022,27 @@
80022 /* Case 1: expr IN (SELECT ...)
80023 **
80024 ** Generate code to write the results of the select into the temporary
80025 ** table allocated and opened above.
80026 */
80027 Select *pSelect = pExpr->x.pSelect;
80028 SelectDest dest;
80029 ExprList *pEList;
80030
80031 assert( !isRowid );
80032 sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
80033 dest.affSdst = (u8)affinity;
80034 assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
80035 pSelect->iLimit = 0;
80036 testcase( pSelect->selFlags & SF_Distinct );
80037 pSelect->selFlags &= ~SF_Distinct;
80038 testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
80039 if( sqlite3Select(pParse, pSelect, &dest) ){
80040 sqlite3KeyInfoUnref(pKeyInfo);
80041 return 0;
80042 }
80043 pEList = pSelect->pEList;
80044 assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
80045 assert( pEList!=0 );
80046 assert( pEList->nExpr>0 );
80047 assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
80048 pKeyInfo->aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
@@ -79515,23 +80069,23 @@
80069 }
80070
80071 /* Loop through each expression in <exprlist>. */
80072 r1 = sqlite3GetTempReg(pParse);
80073 r2 = sqlite3GetTempReg(pParse);
80074 if( isRowid ) sqlite3VdbeAddOp2(v, OP_Null, 0, r2);
80075 for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
80076 Expr *pE2 = pItem->pExpr;
80077 int iValToIns;
80078
80079 /* If the expression is not constant then we will need to
80080 ** disable the test that was generated above that makes sure
80081 ** this code only executes once. Because for a non-constant
80082 ** expression we need to rerun this code each time.
80083 */
80084 if( jmpIfDynamic>=0 && !sqlite3ExprIsConstant(pE2) ){
80085 sqlite3VdbeChangeToNoop(v, jmpIfDynamic);
80086 jmpIfDynamic = -1;
80087 }
80088
80089 /* Evaluate the expression and insert it into the temp table */
80090 if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){
80091 sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns);
@@ -79597,12 +80151,16 @@
80151 ExprSetVVAProperty(pExpr, EP_NoReduce);
80152 break;
80153 }
80154 }
80155
80156 if( rHasNullFlag ){
80157 sqlite3SetHasNullFlag(v, pExpr->iTable, rHasNullFlag);
80158 }
80159
80160 if( jmpIfDynamic>=0 ){
80161 sqlite3VdbeJumpHere(v, jmpIfDynamic);
80162 }
80163 sqlite3ExprCachePop(pParse);
80164
80165 return rReg;
80166 }
@@ -79619,11 +80177,11 @@
80177 ** is an array of zero or more values. The expression is true if the LHS is
80178 ** contained within the RHS. The value of the expression is unknown (NULL)
80179 ** if the LHS is NULL or if the LHS is not contained within the RHS and the
80180 ** RHS contains one or more NULL values.
80181 **
80182 ** This routine generates code that jumps to destIfFalse if the LHS is not
80183 ** contained within the RHS. If due to NULLs we cannot determine if the LHS
80184 ** is contained in the RHS then jump to destIfNull. If the LHS is contained
80185 ** within the RHS then fall through.
80186 */
80187 static void sqlite3ExprCodeIN(
@@ -79642,11 +80200,13 @@
80200 ** pExpr->iTable will contains the values that make up the RHS.
80201 */
80202 v = pParse->pVdbe;
80203 assert( v!=0 ); /* OOM detected prior to this routine */
80204 VdbeNoopComment((v, "begin IN expr"));
80205 eType = sqlite3FindInIndex(pParse, pExpr,
80206 IN_INDEX_MEMBERSHIP | IN_INDEX_NOOP_OK,
80207 destIfFalse==destIfNull ? 0 : &rRhsHasNull);
80208
80209 /* Figure out the affinity to use to create a key from the results
80210 ** of the expression. affinityStr stores a static string suitable for
80211 ** P4 of OP_MakeRecord.
80212 */
@@ -79656,86 +80216,118 @@
80216 */
80217 sqlite3ExprCachePush(pParse);
80218 r1 = sqlite3GetTempReg(pParse);
80219 sqlite3ExprCode(pParse, pExpr->pLeft, r1);
80220
80221 /* If sqlite3FindInIndex() did not find or create an index that is
80222 ** suitable for evaluating the IN operator, then evaluate using a
80223 ** sequence of comparisons.
80224 */
80225 if( eType==IN_INDEX_NOOP ){
80226 ExprList *pList = pExpr->x.pList;
80227 CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
80228 int labelOk = sqlite3VdbeMakeLabel(v);
80229 int r2, regToFree;
80230 int regCkNull = 0;
80231 int ii;
80232 assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
80233 if( destIfNull!=destIfFalse ){
80234 regCkNull = sqlite3GetTempReg(pParse);
80235 sqlite3VdbeAddOp3(v, OP_BitAnd, r1, r1, regCkNull);
80236 }
80237 for(ii=0; ii<pList->nExpr; ii++){
80238 r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr, &regToFree);
80239 if( regCkNull && sqlite3ExprCanBeNull(pList->a[ii].pExpr) ){
80240 sqlite3VdbeAddOp3(v, OP_BitAnd, regCkNull, r2, regCkNull);
80241 }
80242 if( ii<pList->nExpr-1 || destIfNull!=destIfFalse ){
80243 sqlite3VdbeAddOp4(v, OP_Eq, r1, labelOk, r2,
80244 (void*)pColl, P4_COLLSEQ);
80245 VdbeCoverageIf(v, ii<pList->nExpr-1);
80246 VdbeCoverageIf(v, ii==pList->nExpr-1);
80247 sqlite3VdbeChangeP5(v, affinity);
80248 }else{
80249 assert( destIfNull==destIfFalse );
80250 sqlite3VdbeAddOp4(v, OP_Ne, r1, destIfFalse, r2,
80251 (void*)pColl, P4_COLLSEQ); VdbeCoverage(v);
80252 sqlite3VdbeChangeP5(v, affinity | SQLITE_JUMPIFNULL);
80253 }
80254 sqlite3ReleaseTempReg(pParse, regToFree);
80255 }
80256 if( regCkNull ){
80257 sqlite3VdbeAddOp2(v, OP_IsNull, regCkNull, destIfNull); VdbeCoverage(v);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80258 sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse);
80259 }
80260 sqlite3VdbeResolveLabel(v, labelOk);
80261 sqlite3ReleaseTempReg(pParse, regCkNull);
80262 }else{
80263
80264 /* If the LHS is NULL, then the result is either false or NULL depending
80265 ** on whether the RHS is empty or not, respectively.
80266 */
80267 if( sqlite3ExprCanBeNull(pExpr->pLeft) ){
80268 if( destIfNull==destIfFalse ){
80269 /* Shortcut for the common case where the false and NULL outcomes are
80270 ** the same. */
80271 sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull); VdbeCoverage(v);
80272 }else{
80273 int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); VdbeCoverage(v);
80274 sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse);
80275 VdbeCoverage(v);
80276 sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull);
80277 sqlite3VdbeJumpHere(v, addr1);
80278 }
80279 }
80280
80281 if( eType==IN_INDEX_ROWID ){
80282 /* In this case, the RHS is the ROWID of table b-tree
80283 */
80284 sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse); VdbeCoverage(v);
80285 sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1);
80286 VdbeCoverage(v);
80287 }else{
80288 /* In this case, the RHS is an index b-tree.
80289 */
80290 sqlite3VdbeAddOp4(v, OP_Affinity, r1, 1, 0, &affinity, 1);
80291
80292 /* If the set membership test fails, then the result of the
80293 ** "x IN (...)" expression must be either 0 or NULL. If the set
80294 ** contains no NULL values, then the result is 0. If the set
80295 ** contains one or more NULL values, then the result of the
80296 ** expression is also NULL.
80297 */
80298 assert( destIfFalse!=destIfNull || rRhsHasNull==0 );
80299 if( rRhsHasNull==0 ){
80300 /* This branch runs if it is known at compile time that the RHS
80301 ** cannot contain NULL values. This happens as the result
80302 ** of a "NOT NULL" constraint in the database schema.
80303 **
80304 ** Also run this branch if NULL is equivalent to FALSE
80305 ** for this particular IN operator.
80306 */
80307 sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, r1, 1);
80308 VdbeCoverage(v);
80309 }else{
80310 /* In this branch, the RHS of the IN might contain a NULL and
80311 ** the presence of a NULL on the RHS makes a difference in the
80312 ** outcome.
80313 */
80314 int j1;
80315
80316 /* First check to see if the LHS is contained in the RHS. If so,
80317 ** then the answer is TRUE the presence of NULLs in the RHS does
80318 ** not matter. If the LHS is not contained in the RHS, then the
80319 ** answer is NULL if the RHS contains NULLs and the answer is
80320 ** FALSE if the RHS is NULL-free.
80321 */
80322 j1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1);
80323 VdbeCoverage(v);
80324 sqlite3VdbeAddOp2(v, OP_IsNull, rRhsHasNull, destIfNull);
80325 VdbeCoverage(v);
80326 sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse);
80327 sqlite3VdbeJumpHere(v, j1);
80328 }
80329 }
80330 }
80331 sqlite3ReleaseTempReg(pParse, r1);
80332 sqlite3ExprCachePop(pParse);
80333 VdbeComment((v, "end IN expr"));
@@ -79792,21 +80384,28 @@
80384 }else{
80385 int c;
80386 i64 value;
80387 const char *z = pExpr->u.zToken;
80388 assert( z!=0 );
80389 c = sqlite3DecOrHexToI64(z, &value);
80390 if( c==0 || (c==2 && negFlag) ){
80391 char *zV;
80392 if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; }
80393 zV = dup8bytes(v, (char*)&value);
80394 sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64);
80395 }else{
80396 #ifdef SQLITE_OMIT_FLOATING_POINT
80397 sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
80398 #else
80399 #ifndef SQLITE_OMIT_HEX_INTEGER
80400 if( sqlite3_strnicmp(z,"0x",2)==0 ){
80401 sqlite3ErrorMsg(pParse, "hex literal too big: %s", z);
80402 }else
80403 #endif
80404 {
80405 codeReal(v, z, negFlag, iMem);
80406 }
80407 #endif
80408 }
80409 }
80410 }
80411
@@ -80348,11 +80947,11 @@
80947 r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
80948 testcase( regFree1==0 );
80949 addr = sqlite3VdbeAddOp1(v, op, r1);
80950 VdbeCoverageIf(v, op==TK_ISNULL);
80951 VdbeCoverageIf(v, op==TK_NOTNULL);
80952 sqlite3VdbeAddOp2(v, OP_Integer, 0, target);
80953 sqlite3VdbeJumpHere(v, addr);
80954 break;
80955 }
80956 case TK_AGG_FUNCTION: {
80957 AggInfo *pInfo = pExpr->pAggInfo;
@@ -80384,11 +80983,11 @@
80983 nFarg = pFarg ? pFarg->nExpr : 0;
80984 assert( !ExprHasProperty(pExpr, EP_IntValue) );
80985 zId = pExpr->u.zToken;
80986 nId = sqlite3Strlen30(zId);
80987 pDef = sqlite3FindFunction(db, zId, nId, nFarg, enc, 0);
80988 if( pDef==0 || pDef->xFunc==0 ){
80989 sqlite3ErrorMsg(pParse, "unknown function: %.*s()", nId, zId);
80990 break;
80991 }
80992
80993 /* Attempt a direct implementation of the built-in COALESCE() and
@@ -83175,19 +83774,24 @@
83774 }
83775
83776 /*
83777 ** Implementation of the stat_init(N,K,C) SQL function. The three parameters
83778 ** are:
83779 ** N: The number of columns in the index including the rowid/pk (note 1)
83780 ** K: The number of columns in the index excluding the rowid/pk.
83781 ** C: The number of rows in the index (note 2)
83782 **
83783 ** Note 1: In the special case of the covering index that implements a
83784 ** WITHOUT ROWID table, N is the number of PRIMARY KEY columns, not the
83785 ** total number of columns in the table.
83786 **
83787 ** Note 2: C is only used for STAT3 and STAT4.
83788 **
83789 ** For indexes on ordinary rowid tables, N==K+1. But for indexes on
83790 ** WITHOUT ROWID tables, N=K+P where P is the number of columns in the
83791 ** PRIMARY KEY of the table. The covering index that implements the
83792 ** original WITHOUT ROWID table as N==K as a special case.
83793 **
83794 ** This routine allocates the Stat4Accum object in heap memory. The return
83795 ** value is a pointer to the the Stat4Accum object encoded as a blob (i.e.
83796 ** the size of the blob is sizeof(void*) bytes).
83797 */
@@ -83493,11 +84097,14 @@
84097 ** P Pointer to the Stat4Accum object created by stat_init()
84098 ** C Index of left-most column to differ from previous row
84099 ** R Rowid for the current row. Might be a key record for
84100 ** WITHOUT ROWID tables.
84101 **
84102 ** This SQL function always returns NULL. It's purpose it to accumulate
84103 ** statistical data and/or samples in the Stat4Accum object about the
84104 ** index being analyzed. The stat_get() SQL function will later be used to
84105 ** extract relevant information for constructing the sqlite_statN tables.
84106 **
84107 ** The R parameter is only used for STAT3 and STAT4
84108 */
84109 static void statPush(
84110 sqlite3_context *context,
@@ -83587,11 +84194,14 @@
84194 #define STAT_GET_NLT 3 /* "nlt" column of stat[34] entry */
84195 #define STAT_GET_NDLT 4 /* "ndlt" column of stat[34] entry */
84196
84197 /*
84198 ** Implementation of the stat_get(P,J) SQL function. This routine is
84199 ** used to query statistical information that has been gathered into
84200 ** the Stat4Accum object by prior calls to stat_push(). The P parameter
84201 ** is a BLOB which is decoded into a pointer to the Stat4Accum objects.
84202 ** The content to returned is determined by the parameter J
84203 ** which is one of the STAT_GET_xxxx values defined above.
84204 **
84205 ** If neither STAT3 nor STAT4 are enabled, then J is always
84206 ** STAT_GET_STAT1 and is hence omitted and this routine becomes
84207 ** a one-parameter function, stat_get(P), that always returns the
@@ -83806,28 +84416,27 @@
84416 pParse->nTab = MAX(pParse->nTab, iTab);
84417 sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
84418 sqlite3VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0);
84419
84420 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
84421 int nCol; /* Number of columns in pIdx. "N" */
 
84422 int addrRewind; /* Address of "OP_Rewind iIdxCur" */
 
84423 int addrNextRow; /* Address of "next_row:" */
84424 const char *zIdxName; /* Name of the index */
84425 int nColTest; /* Number of columns to test for changes */
84426
84427 if( pOnlyIdx && pOnlyIdx!=pIdx ) continue;
84428 if( pIdx->pPartIdxWhere==0 ) needTableCnt = 0;
84429 if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIdx) ){
84430 nCol = pIdx->nKeyCol;
84431 zIdxName = pTab->zName;
84432 nColTest = nCol - 1;
84433 }else{
84434 nCol = pIdx->nColumn;
84435 zIdxName = pIdx->zName;
84436 nColTest = pIdx->uniqNotNull ? pIdx->nKeyCol-1 : nCol-1;
84437 }
 
 
84438
84439 /* Populate the register containing the index name. */
84440 sqlite3VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, zIdxName, 0);
84441 VdbeComment((v, "Analysis for %s.%s", pTab->zName, zIdxName));
84442
@@ -83852,11 +84461,11 @@
84461 ** regPrev(0) = idx(0)
84462 ** chng_addr_1:
84463 ** regPrev(1) = idx(1)
84464 ** ...
84465 **
84466 ** endDistinctTest:
84467 ** regRowid = idx(rowid)
84468 ** stat_push(P, regChng, regRowid)
84469 ** Next csr
84470 ** if !eof(csr) goto next_row;
84471 **
@@ -83865,24 +84474,27 @@
84474
84475 /* Make sure there are enough memory cells allocated to accommodate
84476 ** the regPrev array and a trailing rowid (the rowid slot is required
84477 ** when building a record to insert into the sample column of
84478 ** the sqlite_stat4 table. */
84479 pParse->nMem = MAX(pParse->nMem, regPrev+nColTest);
84480
84481 /* Open a read-only cursor on the index being analyzed. */
84482 assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) );
84483 sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb);
84484 sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
84485 VdbeComment((v, "%s", pIdx->zName));
84486
84487 /* Invoke the stat_init() function. The arguments are:
84488 **
84489 ** (1) the number of columns in the index including the rowid
84490 ** (or for a WITHOUT ROWID table, the number of PK columns),
84491 ** (2) the number of columns in the key without the rowid/pk
84492 ** (3) the number of rows in the index,
84493 **
84494 **
84495 ** The third argument is only used for STAT3 and STAT4
84496 */
84497 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
84498 sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+3);
84499 #endif
84500 sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat4+1);
@@ -83900,56 +84512,73 @@
84512 **
84513 */
84514 addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
84515 VdbeCoverage(v);
84516 sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng);
 
 
 
 
 
 
 
 
 
 
 
 
84517 addrNextRow = sqlite3VdbeCurrentAddr(v);
84518
84519 if( nColTest>0 ){
84520 int endDistinctTest = sqlite3VdbeMakeLabel(v);
84521 int *aGotoChng; /* Array of jump instruction addresses */
84522 aGotoChng = sqlite3DbMallocRaw(db, sizeof(int)*nColTest);
84523 if( aGotoChng==0 ) continue;
84524
84525 /*
84526 ** next_row:
84527 ** regChng = 0
84528 ** if( idx(0) != regPrev(0) ) goto chng_addr_0
84529 ** regChng = 1
84530 ** if( idx(1) != regPrev(1) ) goto chng_addr_1
84531 ** ...
84532 ** regChng = N
84533 ** goto endDistinctTest
84534 */
84535 sqlite3VdbeAddOp0(v, OP_Goto);
84536 addrNextRow = sqlite3VdbeCurrentAddr(v);
84537 if( nColTest==1 && pIdx->nKeyCol==1 && IsUniqueIndex(pIdx) ){
84538 /* For a single-column UNIQUE index, once we have found a non-NULL
84539 ** row, we know that all the rest will be distinct, so skip
84540 ** subsequent distinctness tests. */
84541 sqlite3VdbeAddOp2(v, OP_NotNull, regPrev, endDistinctTest);
84542 VdbeCoverage(v);
84543 }
84544 for(i=0; i<nColTest; i++){
84545 char *pColl = (char*)sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
84546 sqlite3VdbeAddOp2(v, OP_Integer, i, regChng);
84547 sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp);
84548 aGotoChng[i] =
84549 sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ);
84550 sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
84551 VdbeCoverage(v);
84552 }
84553 sqlite3VdbeAddOp2(v, OP_Integer, nColTest, regChng);
84554 sqlite3VdbeAddOp2(v, OP_Goto, 0, endDistinctTest);
84555
84556
84557 /*
84558 ** chng_addr_0:
84559 ** regPrev(0) = idx(0)
84560 ** chng_addr_1:
84561 ** regPrev(1) = idx(1)
84562 ** ...
84563 */
84564 sqlite3VdbeJumpHere(v, addrNextRow-1);
84565 for(i=0; i<nColTest; i++){
84566 sqlite3VdbeJumpHere(v, aGotoChng[i]);
84567 sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regPrev+i);
84568 }
84569 sqlite3VdbeResolveLabel(v, endDistinctTest);
84570 sqlite3DbFree(db, aGotoChng);
84571 }
84572
84573 /*
84574 ** chng_addr_N:
84575 ** regRowid = idx(rowid) // STAT34 only
84576 ** stat_push(P, regChng, regRowid) // 3rd parameter STAT34 only
84577 ** Next csr
84578 ** if !eof(csr) goto next_row;
84579 */
 
84580 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
84581 assert( regRowid==(regStat4+2) );
84582 if( HasRowid(pTab) ){
84583 sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, regRowid);
84584 }else{
@@ -84023,11 +84652,10 @@
84652 }
84653 #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
84654
84655 /* End of analysis */
84656 sqlite3VdbeJumpHere(v, addrRewind);
 
84657 }
84658
84659
84660 /* Create a single sqlite_stat1 entry containing NULL as the index
84661 ** name and the row count as the content.
@@ -84124,10 +84752,11 @@
84752 int i;
84753 char *z, *zDb;
84754 Table *pTab;
84755 Index *pIdx;
84756 Token *pTableName;
84757 Vdbe *v;
84758
84759 /* Read the database schema. If an error occurs, leave an error message
84760 ** and code in pParse and return NULL. */
84761 assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
84762 if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
@@ -84171,10 +84800,12 @@
84800 }
84801 sqlite3DbFree(db, z);
84802 }
84803 }
84804 }
84805 v = sqlite3GetVdbe(pParse);
84806 if( v ) sqlite3VdbeAddOp0(v, OP_Expire);
84807 }
84808
84809 /*
84810 ** Used to pass information from the analyzer reader through to the
84811 ** callback routine.
@@ -84229,18 +84860,23 @@
84860 #ifndef SQLITE_ENABLE_STAT3_OR_STAT4
84861 assert( pIndex!=0 );
84862 #else
84863 if( pIndex )
84864 #endif
84865 while( z[0] ){
84866 if( sqlite3_strglob("unordered*", z)==0 ){
84867 pIndex->bUnordered = 1;
84868 }else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
84869 pIndex->szIdxRow = sqlite3LogEst(sqlite3Atoi(z+3));
 
 
84870 }
84871 #ifdef SQLITE_ENABLE_COSTMULT
84872 else if( sqlite3_strglob("costmult=[0-9]*",z)==0 ){
84873 pIndex->pTable->costMult = sqlite3LogEst(sqlite3Atoi(z+9));
84874 }
84875 #endif
84876 while( z[0]!=0 && z[0]!=' ' ) z++;
84877 while( z[0]==' ' ) z++;
84878 }
84879 }
84880
84881 /*
84882 ** This callback is invoked once for each index when reading the
@@ -84277,15 +84913,19 @@
84913 pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase);
84914 }
84915 z = argv[2];
84916
84917 if( pIndex ){
84918 pIndex->bUnordered = 0;
84919 decodeIntArray((char*)z, pIndex->nKeyCol+1, 0, pIndex->aiRowLogEst, pIndex);
84920 if( pIndex->pPartIdxWhere==0 ) pTable->nRowLogEst = pIndex->aiRowLogEst[0];
84921 }else{
84922 Index fakeIdx;
84923 fakeIdx.szIdxRow = pTable->szTabRow;
84924 #ifdef SQLITE_ENABLE_COSTMULT
84925 fakeIdx.pTable = pTable;
84926 #endif
84927 decodeIntArray((char*)z, 1, 0, &pTable->nRowLogEst, &fakeIdx);
84928 pTable->szTabRow = fakeIdx.szIdxRow;
84929 }
84930
84931 return 0;
@@ -85557,10 +86197,23 @@
86197 }
86198 #else
86199 #define codeTableLocks(x)
86200 #endif
86201
86202 /*
86203 ** Return TRUE if the given yDbMask object is empty - if it contains no
86204 ** 1 bits. This routine is used by the DbMaskAllZero() and DbMaskNotZero()
86205 ** macros when SQLITE_MAX_ATTACHED is greater than 30.
86206 */
86207 #if SQLITE_MAX_ATTACHED>30
86208 SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask m){
86209 int i;
86210 for(i=0; i<sizeof(yDbMask); i++) if( m[i] ) return 0;
86211 return 1;
86212 }
86213 #endif
86214
86215 /*
86216 ** This routine is called after a single SQL statement has been
86217 ** parsed and a VDBE program to execute that statement has been
86218 ** prepared. This routine puts the finishing touches on the
86219 ** VDBE program and resets the pParse structure for the next
@@ -85593,22 +86246,23 @@
86246 ** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are
86247 ** set for each database that is used. Generate code to start a
86248 ** transaction on each used database and to verify the schema cookie
86249 ** on each used database.
86250 */
86251 if( db->mallocFailed==0
86252 && (DbMaskNonZero(pParse->cookieMask) || pParse->pConstExpr)
86253 ){
86254 int iDb, i;
86255 assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init );
86256 sqlite3VdbeJumpHere(v, 0);
86257 for(iDb=0; iDb<db->nDb; iDb++){
86258 if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue;
86259 sqlite3VdbeUsesBtree(v, iDb);
86260 sqlite3VdbeAddOp4Int(v,
86261 OP_Transaction, /* Opcode */
86262 iDb, /* P1 */
86263 DbMaskTest(pParse->writeMask,iDb), /* P2 */
86264 pParse->cookieValue[iDb], /* P3 */
86265 db->aDb[iDb].pSchema->iGeneration /* P4 */
86266 );
86267 if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1);
86268 }
@@ -85660,11 +86314,11 @@
86314 }
86315 pParse->nTab = 0;
86316 pParse->nMem = 0;
86317 pParse->nSet = 0;
86318 pParse->nVar = 0;
86319 DbMaskZero(pParse->cookieMask);
86320 }
86321
86322 /*
86323 ** Run the parser and code generator recursively in order to generate
86324 ** code for the SQL statement given onto the end of the pParse context
@@ -87560,11 +88214,11 @@
88214 pTable->aCol = pSelTab->aCol;
88215 pSelTab->nCol = 0;
88216 pSelTab->aCol = 0;
88217 sqlite3DeleteTable(db, pSelTab);
88218 assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) );
88219 pTable->pSchema->schemaFlags |= DB_UnresetViews;
88220 }else{
88221 pTable->nCol = 0;
88222 nErr++;
88223 }
88224 sqlite3SelectDelete(db, pSel);
@@ -88137,16 +88791,16 @@
88791 (char *)pKey, P4_KEYINFO);
88792 sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
88793
88794 addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v);
88795 assert( pKey!=0 || db->mallocFailed || pParse->nErr );
88796 if( IsUniqueIndex(pIndex) && pKey!=0 ){
88797 int j2 = sqlite3VdbeCurrentAddr(v) + 3;
88798 sqlite3VdbeAddOp2(v, OP_Goto, 0, j2);
88799 addr2 = sqlite3VdbeCurrentAddr(v);
88800 sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord,
88801 pIndex->nKeyCol); VdbeCoverage(v);
88802 sqlite3UniqueConstraint(pParse, OE_Abort, pIndex);
88803 }else{
88804 addr2 = sqlite3VdbeCurrentAddr(v);
88805 }
88806 sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord);
@@ -88534,13 +89188,13 @@
89188 ** considered distinct and both result in separate indices.
89189 */
89190 Index *pIdx;
89191 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
89192 int k;
89193 assert( IsUniqueIndex(pIdx) );
89194 assert( pIdx->idxType!=SQLITE_IDXTYPE_APPDEF );
89195 assert( IsUniqueIndex(pIndex) );
89196
89197 if( pIdx->nKeyCol!=pIndex->nKeyCol ) continue;
89198 for(k=0; k<pIdx->nKeyCol; k++){
89199 const char *z1;
89200 const char *z2;
@@ -88727,11 +89381,11 @@
89381 for(i=nCopy+1; i<=pIdx->nKeyCol; i++){
89382 a[i] = 23; assert( 23==sqlite3LogEst(5) );
89383 }
89384
89385 assert( 0==sqlite3LogEst(1) );
89386 if( IsUniqueIndex(pIdx) ) a[pIdx->nKeyCol] = 0;
89387 }
89388
89389 /*
89390 ** This routine will drop an existing named index. This routine
89391 ** implements the DROP INDEX statement.
@@ -89287,19 +89941,17 @@
89941 ** later, by sqlite3FinishCoding().
89942 */
89943 SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
89944 Parse *pToplevel = sqlite3ParseToplevel(pParse);
89945 sqlite3 *db = pToplevel->db;
 
89946
89947 assert( iDb>=0 && iDb<db->nDb );
89948 assert( db->aDb[iDb].pBt!=0 || iDb==1 );
89949 assert( iDb<SQLITE_MAX_ATTACHED+2 );
89950 assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
89951 if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){
89952 DbMaskSet(pToplevel->cookieMask, iDb);
 
89953 pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie;
89954 if( !OMIT_TEMPDB && iDb==1 ){
89955 sqlite3OpenTempDatabase(pToplevel);
89956 }
89957 }
@@ -89334,11 +89986,11 @@
89986 ** necessary to undo a write and the checkpoint should not be set.
89987 */
89988 SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
89989 Parse *pToplevel = sqlite3ParseToplevel(pParse);
89990 sqlite3CodeVerifySchema(pParse, iDb);
89991 DbMaskSet(pToplevel->writeMask, iDb);
89992 pToplevel->isMultiWrite |= setStatement;
89993 }
89994
89995 /*
89996 ** Indicate that the statement currently under construction might write
@@ -90141,13 +90793,13 @@
90793 sqlite3DeleteTable(0, pTab);
90794 }
90795 sqlite3HashClear(&temp1);
90796 sqlite3HashClear(&pSchema->fkeyHash);
90797 pSchema->pSeqTab = 0;
90798 if( pSchema->schemaFlags & DB_SchemaLoaded ){
90799 pSchema->iGeneration++;
90800 pSchema->schemaFlags &= ~DB_SchemaLoaded;
90801 }
90802 }
90803
90804 /*
90805 ** Find and return the schema associated with a BTree. Create
@@ -91022,16 +91674,13 @@
91674 ** May you do good and not evil.
91675 ** May you find forgiveness for yourself and forgive others.
91676 ** May you share freely, never taking more than you give.
91677 **
91678 *************************************************************************
91679 ** This file contains the C-language implementions for many of the SQL
91680 ** functions of SQLite. (Some function, and in particular the date and
91681 ** time functions, are implemented separately.)
 
 
 
91682 */
91683 /* #include <stdlib.h> */
91684 /* #include <assert.h> */
91685
91686 /*
@@ -92989,11 +93638,11 @@
93638 if( !aiCol ) return 1;
93639 *paiCol = aiCol;
93640 }
93641
93642 for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){
93643 if( pIdx->nKeyCol==nCol && IsUniqueIndex(pIdx) ){
93644 /* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number
93645 ** of columns. If each indexed column corresponds to a foreign key
93646 ** column of pFKey, then this index is a winner. */
93647
93648 if( zKey==0 ){
@@ -96015,11 +96664,11 @@
96664 ){
96665 return 0; /* Default values must be the same for all columns */
96666 }
96667 }
96668 for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
96669 if( IsUniqueIndex(pDestIdx) ){
96670 destHasUniqueIdx = 1;
96671 }
96672 for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){
96673 if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
96674 }
@@ -96245,10 +96894,13 @@
96894 goto exec_out;
96895 }
96896 }
96897 }
96898 if( xCallback(pArg, nCol, azVals, azCols) ){
96899 /* EVIDENCE-OF: R-38229-40159 If the callback function to
96900 ** sqlite3_exec() returns non-zero, then sqlite3_exec() will
96901 ** return SQLITE_ABORT. */
96902 rc = SQLITE_ABORT;
96903 sqlite3VdbeFinalize((Vdbe *)pStmt);
96904 pStmt = 0;
96905 sqlite3Error(db, SQLITE_ABORT, 0);
96906 goto exec_out;
@@ -98022,11 +98674,11 @@
98674 ** Note that the values returned are one less that the values that
98675 ** should be passed into sqlite3BtreeSetSafetyLevel(). The is done
98676 ** to support legacy SQL code. The safety level used to be boolean
98677 ** and older scripts may have used numbers 0 for OFF and 1 for ON.
98678 */
98679 static u8 getSafetyLevel(const char *z, int omitFull, u8 dflt){
98680 /* 123456789 123456789 */
98681 static const char zText[] = "onoffalseyestruefull";
98682 static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16};
98683 static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 4};
98684 static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 2};
@@ -98044,11 +98696,11 @@
98696 }
98697
98698 /*
98699 ** Interpret the given string as a boolean value.
98700 */
98701 SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z, u8 dflt){
98702 return getSafetyLevel(z,1,dflt)!=0;
98703 }
98704
98705 /* The sqlite3GetBoolean() function is used by other modules but the
98706 ** remainder of this file is specific to PRAGMA processing. So omit
@@ -98590,11 +99242,11 @@
99242 */
99243 case PragTyp_JOURNAL_SIZE_LIMIT: {
99244 Pager *pPager = sqlite3BtreePager(pDb->pBt);
99245 i64 iLimit = -2;
99246 if( zRight ){
99247 sqlite3DecOrHexToI64(zRight, &iLimit);
99248 if( iLimit<-1 ) iLimit = -1;
99249 }
99250 iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit);
99251 returnSingleInt(pParse, "journal_size_limit", iLimit);
99252 break;
@@ -98718,11 +99370,11 @@
99370 sqlite3_int64 sz;
99371 #if SQLITE_MAX_MMAP_SIZE>0
99372 assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
99373 if( zRight ){
99374 int ii;
99375 sqlite3DecOrHexToI64(zRight, &sz);
99376 if( sz<0 ) sz = sqlite3GlobalConfig.szMmap;
99377 if( pId2->n==0 ) db->szMmap = sz;
99378 for(ii=db->nDb-1; ii>=0; ii--){
99379 if( db->aDb[ii].pBt && (ii==iDb || pId2->n==0) ){
99380 sqlite3BtreeSetMmapLimit(db->aDb[ii].pBt, sz);
@@ -99086,11 +99738,11 @@
99738 sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
99739 sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
99740 for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){
99741 sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
99742 sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
99743 sqlite3VdbeAddOp2(v, OP_Integer, IsUniqueIndex(pIdx), 3);
99744 sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
99745 }
99746 }
99747 }
99748 break;
@@ -99336,13 +99988,12 @@
99988 ** messages have been generated, output OK. Otherwise output the
99989 ** error message
99990 */
99991 static const int iLn = VDBE_OFFSET_LINENO(2);
99992 static const VdbeOpList endCode[] = {
99993 { OP_IfNeg, 1, 0, 0}, /* 0 */
99994 { OP_String8, 0, 3, 0}, /* 1 */
 
99995 { OP_ResultRow, 3, 1, 0},
99996 };
99997
99998 int isQuick = (sqlite3Tolower(zLeft[0])=='q');
99999
@@ -99450,32 +100101,80 @@
100101 sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */
100102 }
100103 pParse->nMem = MAX(pParse->nMem, 8+j);
100104 sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v);
100105 loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1);
100106 /* Verify that all NOT NULL columns really are NOT NULL */
100107 for(j=0; j<pTab->nCol; j++){
100108 char *zErr;
100109 int jmp2, jmp3;
100110 if( j==pTab->iPKey ) continue;
100111 if( pTab->aCol[j].notNull==0 ) continue;
100112 sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
100113 sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
100114 jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
100115 sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
100116 zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
100117 pTab->aCol[j].zName);
100118 sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
100119 sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
100120 jmp3 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v);
100121 sqlite3VdbeAddOp0(v, OP_Halt);
100122 sqlite3VdbeJumpHere(v, jmp2);
100123 sqlite3VdbeJumpHere(v, jmp3);
100124 }
100125 /* Validate index entries for the current row */
100126 for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
100127 int jmp2, jmp3, jmp4, jmp5;
100128 int ckUniq = sqlite3VdbeMakeLabel(v);
100129 if( pPk==pIdx ) continue;
100130 r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
100131 pPrior, r1);
100132 pPrior = pIdx;
100133 sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */
100134 /* Verify that an index entry exists for the current table row */
100135 jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
100136 pIdx->nColumn); VdbeCoverage(v);
100137 sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
100138 sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, "row ", P4_STATIC);
100139 sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
100140 sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0,
100141 " missing from index ", P4_STATIC);
100142 sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
100143 jmp5 = sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0,
100144 pIdx->zName, P4_TRANSIENT);
100145 sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
100146 sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
100147 jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v);
100148 sqlite3VdbeAddOp0(v, OP_Halt);
 
100149 sqlite3VdbeJumpHere(v, jmp2);
100150 /* For UNIQUE indexes, verify that only one entry exists with the
100151 ** current key. The entry is unique if (1) any column is NULL
100152 ** or (2) the next entry has a different key */
100153 if( IsUniqueIndex(pIdx) ){
100154 int uniqOk = sqlite3VdbeMakeLabel(v);
100155 int jmp6;
100156 int kk;
100157 for(kk=0; kk<pIdx->nKeyCol; kk++){
100158 int iCol = pIdx->aiColumn[kk];
100159 assert( iCol>=0 && iCol<pTab->nCol );
100160 if( pTab->aCol[iCol].notNull ) continue;
100161 sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk);
100162 VdbeCoverage(v);
100163 }
100164 jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v);
100165 sqlite3VdbeAddOp2(v, OP_Goto, 0, uniqOk);
100166 sqlite3VdbeJumpHere(v, jmp6);
100167 sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1,
100168 pIdx->nKeyCol); VdbeCoverage(v);
100169 sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
100170 sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
100171 "non-unique entry in index ", P4_STATIC);
100172 sqlite3VdbeAddOp2(v, OP_Goto, 0, jmp5);
100173 sqlite3VdbeResolveLabel(v, uniqOk);
100174 }
100175 sqlite3VdbeJumpHere(v, jmp4);
100176 sqlite3ResolvePartIdxLabel(pParse, jmp3);
100177 }
100178 sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
100179 sqlite3VdbeJumpHere(v, loopTop-1);
100180 #ifndef SQLITE_OMIT_BTREECOUNT
@@ -99496,13 +100195,13 @@
100195 }
100196 #endif /* SQLITE_OMIT_BTREECOUNT */
100197 }
100198 }
100199 addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
100200 sqlite3VdbeChangeP3(v, addr, -mxErr);
100201 sqlite3VdbeJumpHere(v, addr);
100202 sqlite3VdbeChangeP4(v, addr+1, "ok", P4_STATIC);
100203 }
100204 break;
100205 #endif /* SQLITE_OMIT_INTEGRITY_CHECK */
100206
100207 #ifndef SQLITE_OMIT_UTF16
@@ -99761,11 +100460,11 @@
100460 ** Call sqlite3_soft_heap_limit64(N). Return the result. If N is omitted,
100461 ** use -1.
100462 */
100463 case PragTyp_SOFT_HEAP_LIMIT: {
100464 sqlite3_int64 N;
100465 if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){
100466 sqlite3_soft_heap_limit64(N);
100467 }
100468 returnSingleInt(pParse, "soft_heap_limit", sqlite3_soft_heap_limit64(-1));
100469 break;
100470 }
@@ -101284,12 +101983,11 @@
101983 int iOffset, /* Register holding the offset counter */
101984 int iContinue /* Jump here to skip the current record */
101985 ){
101986 if( iOffset>0 ){
101987 int addr;
101988 addr = sqlite3VdbeAddOp3(v, OP_IfNeg, iOffset, 0, -1); VdbeCoverage(v);
 
101989 sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue);
101990 VdbeComment((v, "skip OFFSET records"));
101991 sqlite3VdbeJumpHere(v, addr);
101992 }
101993 }
@@ -101450,11 +102148,11 @@
102148 VdbeCoverage(v);
102149 }
102150 sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
102151 sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
102152 }
102153 assert( sqlite3VdbeCurrentAddr(v)==iJump || pParse->db->mallocFailed );
102154 sqlite3VdbeAddOp3(v, OP_Copy, regResult, regPrev, nResultCol-1);
102155 break;
102156 }
102157
102158 case WHERE_DISTINCT_UNIQUE: {
@@ -107917,11 +108615,12 @@
108615 sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey);
108616 VdbeCoverageNeverTaken(v);
108617 }
108618 labelContinue = labelBreak;
108619 sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak);
108620 VdbeCoverageIf(v, pPk==0);
108621 VdbeCoverageIf(v, pPk!=0);
108622 }else if( pPk ){
108623 labelContinue = sqlite3VdbeMakeLabel(v);
108624 sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v);
108625 addrTop = sqlite3VdbeAddOp2(v, OP_RowKey, iEph, regKey);
108626 sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0);
@@ -109927,10 +110626,11 @@
110626 struct WherePath {
110627 Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */
110628 Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */
110629 LogEst nRow; /* Estimated number of rows generated by this path */
110630 LogEst rCost; /* Total cost of this path */
110631 LogEst rUnsorted; /* Total cost of this path ignoring sorting costs */
110632 i8 isOrdered; /* No. of ORDER BY terms satisfied. -1 for unknown */
110633 WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */
110634 };
110635
110636 /*
@@ -111657,11 +112357,11 @@
112357 **
112358 ** 3. All of those index columns for which the WHERE clause does not
112359 ** contain a "col=X" term are subject to a NOT NULL constraint.
112360 */
112361 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
112362 if( !IsUniqueIndex(pIdx) ) continue;
112363 for(i=0; i<pIdx->nKeyCol; i++){
112364 i16 iCol = pIdx->aiColumn[i];
112365 if( 0==findTerm(pWC, iBase, iCol, ~(Bitmask)0, WO_EQ, pIdx) ){
112366 int iIdxCol = findIndexCol(pParse, pDistinct, iBase, pIdx, i);
112367 if( iIdxCol<0 || pTab->aCol[iCol].notNull==0 ){
@@ -112234,11 +112934,12 @@
112934 int nEq = pLoop->u.btree.nEq;
112935 sqlite3 *db = pParse->db;
112936 int nLower = -1;
112937 int nUpper = p->nSample+1;
112938 int rc = SQLITE_OK;
112939 int iCol = p->aiColumn[nEq];
112940 u8 aff = iCol>=0 ? p->pTable->aCol[iCol].affinity : SQLITE_AFF_INTEGER;
112941 CollSeq *pColl;
112942
112943 sqlite3_value *p1 = 0; /* Value extracted from pLower */
112944 sqlite3_value *p2 = 0; /* Value extracted from pUpper */
112945 sqlite3_value *pVal = 0; /* Value extracted from record */
@@ -112708,11 +113409,11 @@
113409 testcase( bRev );
113410 bRev = !bRev;
113411 }
113412 assert( pX->op==TK_IN );
113413 iReg = iTarget;
113414 eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0);
113415 if( eType==IN_INDEX_INDEX_DESC ){
113416 testcase( bRev );
113417 bRev = !bRev;
113418 }
113419 iTab = pX->iTable;
@@ -113609,10 +114310,11 @@
114310 int regRowid = 0; /* Register holding rowid */
114311 int iLoopBody = sqlite3VdbeMakeLabel(v); /* Start of loop body */
114312 int iRetInit; /* Address of regReturn init */
114313 int untestedTerms = 0; /* Some terms not completely tested */
114314 int ii; /* Loop counter */
114315 u16 wctrlFlags; /* Flags for sub-WHERE clause */
114316 Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
114317 Table *pTab = pTabItem->pTab;
114318
114319 pTerm = pLoop->aLTerm[0];
114320 assert( pTerm!=0 );
@@ -113704,10 +114406,12 @@
114406
114407 /* Run a separate WHERE clause for each term of the OR clause. After
114408 ** eliminating duplicates from other WHERE clauses, the action for each
114409 ** sub-WHERE clause is to to invoke the main loop body as a subroutine.
114410 */
114411 wctrlFlags = WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
114412 WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY;
114413 for(ii=0; ii<pOrWc->nTerm; ii++){
114414 WhereTerm *pOrTerm = &pOrWc->a[ii];
114415 if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
114416 WhereInfo *pSubWInfo; /* Info for single OR-term scan */
114417 Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
@@ -113716,12 +114420,11 @@
114420 pAndExpr->pLeft = pOrExpr;
114421 pOrExpr = pAndExpr;
114422 }
114423 /* Loop through table entries that match term pOrTerm. */
114424 pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
114425 wctrlFlags, iCovCur);
 
114426 assert( pSubWInfo || pParse->nErr || db->mallocFailed );
114427 if( pSubWInfo ){
114428 WhereLoop *pSubLoop;
114429 explainOneScan(
114430 pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
@@ -113808,10 +114511,11 @@
114511 && (ii==0 || pSubLoop->u.btree.pIndex==pCov)
114512 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pSubLoop->u.btree.pIndex))
114513 ){
114514 assert( pSubWInfo->a[0].iIdxCur==iCovCur );
114515 pCov = pSubLoop->u.btree.pIndex;
114516 wctrlFlags |= WHERE_REOPEN_IDX;
114517 }else{
114518 pCov = 0;
114519 }
114520
114521 /* Finish the loop through table entries that match term pOrTerm. */
@@ -114414,10 +115118,20 @@
115118 pLoop->nOut += (pTerm->truthProb<=0 ? pTerm->truthProb : -1);
115119 }
115120 }
115121 }
115122
115123 /*
115124 ** Adjust the cost C by the costMult facter T. This only occurs if
115125 ** compiled with -DSQLITE_ENABLE_COSTMULT
115126 */
115127 #ifdef SQLITE_ENABLE_COSTMULT
115128 # define ApplyCostMultiplier(C,T) C += T
115129 #else
115130 # define ApplyCostMultiplier(C,T)
115131 #endif
115132
115133 /*
115134 ** We have so far matched pBuilder->pNew->u.btree.nEq terms of the
115135 ** index pIndex. Try to match one more.
115136 **
115137 ** When this function is called, pBuilder->pNew->nOut contains the
@@ -114549,11 +115263,11 @@
115263 ** changes "x IN (?)" into "x=?". */
115264
115265 }else if( eOp & (WO_EQ) ){
115266 pNew->wsFlags |= WHERE_COLUMN_EQ;
115267 if( iCol<0 || (nInMul==0 && pNew->u.btree.nEq==pProbe->nKeyCol-1) ){
115268 if( iCol>=0 && !IsUniqueIndex(pProbe) ){
115269 pNew->wsFlags |= WHERE_UNQ_WANTED;
115270 }else{
115271 pNew->wsFlags |= WHERE_ONEROW;
115272 }
115273 }
@@ -114610,11 +115324,10 @@
115324 testcase( eOp & WO_ISNULL );
115325 rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut);
115326 }else{
115327 rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut);
115328 }
 
115329 if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
115330 if( rc!=SQLITE_OK ) break; /* Jump out of the pTerm loop */
115331 if( nOut ){
115332 pNew->nOut = sqlite3LogEst(nOut);
115333 if( pNew->nOut>saved_nOut ) pNew->nOut = saved_nOut;
@@ -114642,10 +115355,11 @@
115355 rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow;
115356 pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx);
115357 if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
115358 pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16);
115359 }
115360 ApplyCostMultiplier(pNew->rRun, pProbe->pTable->costMult);
115361
115362 nOutUnadjusted = pNew->nOut;
115363 pNew->rRun += nInMul + nIn;
115364 pNew->nOut += nInMul + nIn;
115365 whereLoopOutputAdjust(pBuilder->pWC, pNew);
@@ -114761,10 +115475,18 @@
115475 ** cost = nSeek * (log(nRow) + (K+3.0) * nVisit) // non-covering index
115476 **
115477 ** Normally, nSeek is 1. nSeek values greater than 1 come about if the
115478 ** WHERE clause includes "x IN (....)" terms used in place of "x=?". Or when
115479 ** implicit "x IN (SELECT x FROM tbl)" terms are added for skip-scans.
115480 **
115481 ** The estimated values (nRow, nVisit, nSeek) often contain a large amount
115482 ** of uncertainty. For this reason, scoring is designed to pick plans that
115483 ** "do the least harm" if the estimates are inaccurate. For example, a
115484 ** log(nRow) factor is omitted from a non-covering index scan in order to
115485 ** bias the scoring in favor of using an index, since the worst-case
115486 ** performance of using an index is far better than the worst-case performance
115487 ** of a full table scan.
115488 */
115489 static int whereLoopAddBtree(
115490 WhereLoopBuilder *pBuilder, /* WHERE clause information */
115491 Bitmask mExtra /* Extra prerequesites for using this table */
115492 ){
@@ -114848,10 +115570,11 @@
115570 pNew->aLTerm[0] = pTerm;
115571 /* TUNING: One-time cost for computing the automatic index is
115572 ** approximately 7*N*log2(N) where N is the number of rows in
115573 ** the table being indexed. */
115574 pNew->rSetup = rLogSize + rSize + 28; assert( 28==sqlite3LogEst(7) );
115575 ApplyCostMultiplier(pNew->rSetup, pTab->costMult);
115576 /* TUNING: Each index lookup yields 20 rows in the table. This
115577 ** is more than the usual guess of 10 rows, since we have no way
115578 ** of knowning how selective the index will ultimately be. It would
115579 ** not be unreasonable to make this value much larger. */
115580 pNew->nOut = 43; assert( 43==sqlite3LogEst(20) );
@@ -114889,10 +115612,11 @@
115612
115613 /* Full table scan */
115614 pNew->iSortIdx = b ? iSortIdx : 0;
115615 /* TUNING: Cost of full table scan is (N*3.0). */
115616 pNew->rRun = rSize + 16;
115617 ApplyCostMultiplier(pNew->rRun, pTab->costMult);
115618 whereLoopOutputAdjust(pWC, pNew);
115619 rc = whereLoopInsert(pBuilder, pNew);
115620 pNew->nOut = rSize;
115621 if( rc ) break;
115622 }else{
@@ -114924,11 +115648,11 @@
115648 ** also add the cost of visiting table rows (N*3.0). */
115649 pNew->rRun = rSize + 1 + (15*pProbe->szIdxRow)/pTab->szTabRow;
115650 if( m!=0 ){
115651 pNew->rRun = sqlite3LogEstAdd(pNew->rRun, rSize+16);
115652 }
115653 ApplyCostMultiplier(pNew->rRun, pTab->costMult);
115654 whereLoopOutputAdjust(pWC, pNew);
115655 rc = whereLoopInsert(pBuilder, pNew);
115656 pNew->nOut = rSize;
115657 if( rc ) break;
115658 }
@@ -115394,11 +116118,11 @@
116118 }else{
116119 nKeyCol = pIndex->nKeyCol;
116120 nColumn = pIndex->nColumn;
116121 assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) );
116122 assert( pIndex->aiColumn[nColumn-1]==(-1) || !HasRowid(pIndex->pTable));
116123 isOrderDistinct = IsUniqueIndex(pIndex);
116124 }
116125
116126 /* Loop through all columns of the index and deal with the ones
116127 ** that are not constrained by == or IN.
116128 */
@@ -115562,10 +116286,49 @@
116286 if( pLast ) zName[i++] = pLast->cId;
116287 zName[i] = 0;
116288 return zName;
116289 }
116290 #endif
116291
116292 /*
116293 ** Return the cost of sorting nRow rows, assuming that the keys have
116294 ** nOrderby columns and that the first nSorted columns are already in
116295 ** order.
116296 */
116297 static LogEst whereSortingCost(
116298 WhereInfo *pWInfo,
116299 LogEst nRow,
116300 int nOrderBy,
116301 int nSorted
116302 ){
116303 /* TUNING: Estimated cost of a full external sort, where N is
116304 ** the number of rows to sort is:
116305 **
116306 ** cost = (3.0 * N * log(N)).
116307 **
116308 ** Or, if the order-by clause has X terms but only the last Y
116309 ** terms are out of order, then block-sorting will reduce the
116310 ** sorting cost to:
116311 **
116312 ** cost = (3.0 * N * log(N)) * (Y/X)
116313 **
116314 ** The (Y/X) term is implemented using stack variable rScale
116315 ** below. */
116316 LogEst rScale, rSortCost;
116317 assert( nOrderBy>0 && 66==sqlite3LogEst(100) );
116318 rScale = sqlite3LogEst((nOrderBy-nSorted)*100/nOrderBy) - 66;
116319 rSortCost = nRow + estLog(nRow) + rScale + 16;
116320
116321 /* TUNING: The cost of implementing DISTINCT using a B-TREE is
116322 ** similar but with a larger constant of proportionality.
116323 ** Multiply by an additional factor of 3.0. */
116324 if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
116325 rSortCost += 16;
116326 }
116327
116328 return rSortCost;
116329 }
116330
116331 /*
116332 ** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
116333 ** attempts to find the lowest cost path that visits each WhereLoop
116334 ** once. This path is then loaded into the pWInfo->a[].pWLoop fields.
@@ -115584,139 +116347,170 @@
116347 sqlite3 *db; /* The database connection */
116348 int iLoop; /* Loop counter over the terms of the join */
116349 int ii, jj; /* Loop counters */
116350 int mxI = 0; /* Index of next entry to replace */
116351 int nOrderBy; /* Number of ORDER BY clause terms */
 
 
116352 LogEst mxCost = 0; /* Maximum cost of a set of paths */
116353 LogEst mxUnsorted = 0; /* Maximum unsorted cost of a set of path */
116354 int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
116355 WherePath *aFrom; /* All nFrom paths at the previous level */
116356 WherePath *aTo; /* The nTo best paths at the current level */
116357 WherePath *pFrom; /* An element of aFrom[] that we are working on */
116358 WherePath *pTo; /* An element of aTo[] that we are working on */
116359 WhereLoop *pWLoop; /* One of the WhereLoop objects */
116360 WhereLoop **pX; /* Used to divy up the pSpace memory */
116361 LogEst *aSortCost = 0; /* Sorting and partial sorting costs */
116362 char *pSpace; /* Temporary memory used by this routine */
116363 int nSpace; /* Bytes of space allocated at pSpace */
116364
116365 pParse = pWInfo->pParse;
116366 db = pParse->db;
116367 nLoop = pWInfo->nLevel;
116368 /* TUNING: For simple queries, only the best path is tracked.
116369 ** For 2-way joins, the 5 best paths are followed.
116370 ** For joins of 3 or more tables, track the 10 best paths */
116371 mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10);
116372 assert( nLoop<=pWInfo->pTabList->nSrc );
116373 WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d)\n", nRowEst));
116374
116375 /* If nRowEst is zero and there is an ORDER BY clause, ignore it. In this
116376 ** case the purpose of this call is to estimate the number of rows returned
116377 ** by the overall query. Once this estimate has been obtained, the caller
116378 ** will invoke this function a second time, passing the estimate as the
116379 ** nRowEst parameter. */
116380 if( pWInfo->pOrderBy==0 || nRowEst==0 ){
116381 nOrderBy = 0;
116382 }else{
116383 nOrderBy = pWInfo->pOrderBy->nExpr;
116384 }
116385
116386 /* Allocate and initialize space for aTo, aFrom and aSortCost[] */
116387 nSpace = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
116388 nSpace += sizeof(LogEst) * nOrderBy;
116389 pSpace = sqlite3DbMallocRaw(db, nSpace);
116390 if( pSpace==0 ) return SQLITE_NOMEM;
116391 aTo = (WherePath*)pSpace;
116392 aFrom = aTo+mxChoice;
116393 memset(aFrom, 0, sizeof(aFrom[0]));
116394 pX = (WhereLoop**)(aFrom+mxChoice);
116395 for(ii=mxChoice*2, pFrom=aTo; ii>0; ii--, pFrom++, pX += nLoop){
116396 pFrom->aLoop = pX;
116397 }
116398 if( nOrderBy ){
116399 /* If there is an ORDER BY clause and it is not being ignored, set up
116400 ** space for the aSortCost[] array. Each element of the aSortCost array
116401 ** is either zero - meaning it has not yet been initialized - or the
116402 ** cost of sorting nRowEst rows of data where the first X terms of
116403 ** the ORDER BY clause are already in order, where X is the array
116404 ** index. */
116405 aSortCost = (LogEst*)pX;
116406 memset(aSortCost, 0, sizeof(LogEst) * nOrderBy);
116407 }
116408 assert( aSortCost==0 || &pSpace[nSpace]==(char*)&aSortCost[nOrderBy] );
116409 assert( aSortCost!=0 || &pSpace[nSpace]==(char*)pX );
116410
116411 /* Seed the search with a single WherePath containing zero WhereLoops.
116412 **
116413 ** TUNING: Do not let the number of iterations go above 25. If the cost
116414 ** of computing an automatic index is not paid back within the first 25
116415 ** rows, then do not use the automatic index. */
116416 aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==sqlite3LogEst(25) );
116417 nFrom = 1;
116418 assert( aFrom[0].isOrdered==0 );
116419 if( nOrderBy ){
116420 /* If nLoop is zero, then there are no FROM terms in the query. Since
116421 ** in this case the query may return a maximum of one row, the results
116422 ** are already in the requested order. Set isOrdered to nOrderBy to
116423 ** indicate this. Or, if nLoop is greater than zero, set isOrdered to
116424 ** -1, indicating that the result set may or may not be ordered,
116425 ** depending on the loops added to the current plan. */
116426 aFrom[0].isOrdered = nLoop>0 ? -1 : nOrderBy;
116427 }
116428
116429 /* Compute successively longer WherePaths using the previous generation
116430 ** of WherePaths as the basis for the next. Keep track of the mxChoice
116431 ** best paths at each generation */
116432 for(iLoop=0; iLoop<nLoop; iLoop++){
116433 nTo = 0;
116434 for(ii=0, pFrom=aFrom; ii<nFrom; ii++, pFrom++){
116435 for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
116436 LogEst nOut; /* Rows visited by (pFrom+pWLoop) */
116437 LogEst rCost; /* Cost of path (pFrom+pWLoop) */
116438 LogEst rUnsorted; /* Unsorted cost of (pFrom+pWLoop) */
116439 i8 isOrdered = pFrom->isOrdered; /* isOrdered for (pFrom+pWLoop) */
116440 Bitmask maskNew; /* Mask of src visited by (..) */
116441 Bitmask revMask = 0; /* Mask of rev-order loops for (..) */
116442
116443 if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
116444 if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
116445 /* At this point, pWLoop is a candidate to be the next loop.
116446 ** Compute its cost */
116447 rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
116448 rUnsorted = sqlite3LogEstAdd(rUnsorted, pFrom->rUnsorted);
116449 nOut = pFrom->nRow + pWLoop->nOut;
116450 maskNew = pFrom->maskLoop | pWLoop->maskSelf;
116451 if( isOrdered<0 ){
116452 isOrdered = wherePathSatisfiesOrderBy(pWInfo,
116453 pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
116454 iLoop, pWLoop, &revMask);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116455 }else{
116456 revMask = pFrom->revLoop;
116457 }
116458 if( isOrdered>=0 && isOrdered<nOrderBy ){
116459 if( aSortCost[isOrdered]==0 ){
116460 aSortCost[isOrdered] = whereSortingCost(
116461 pWInfo, nRowEst, nOrderBy, isOrdered
116462 );
116463 }
116464 rCost = sqlite3LogEstAdd(rUnsorted, aSortCost[isOrdered]);
116465
116466 WHERETRACE(0x002,
116467 ("---- sort cost=%-3d (%d/%d) increases cost %3d to %-3d\n",
116468 aSortCost[isOrdered], (nOrderBy-isOrdered), nOrderBy,
116469 rUnsorted, rCost));
116470 }else{
116471 rCost = rUnsorted;
116472 }
116473
116474 /* Check to see if pWLoop should be added to the set of
116475 ** mxChoice best-so-far paths.
116476 **
116477 ** First look for an existing path among best-so-far paths
116478 ** that covers the same set of loops and has the same isOrdered
116479 ** setting as the current path candidate.
116480 **
116481 ** The term "((pTo->isOrdered^isOrdered)&0x80)==0" is equivalent
116482 ** to (pTo->isOrdered==(-1))==(isOrdered==(-1))" for the range
116483 ** of legal values for isOrdered, -1..64.
116484 */
116485 for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
116486 if( pTo->maskLoop==maskNew
116487 && ((pTo->isOrdered^isOrdered)&0x80)==0
116488 ){
116489 testcase( jj==nTo-1 );
116490 break;
116491 }
116492 }
116493 if( jj>=nTo ){
116494 /* None of the existing best-so-far paths match the candidate. */
116495 if( nTo>=mxChoice
116496 && (rCost>mxCost || (rCost==mxCost && rUnsorted>=mxUnsorted))
116497 ){
116498 /* The current candidate is no better than any of the mxChoice
116499 ** paths currently in the best-so-far buffer. So discard
116500 ** this candidate as not viable. */
116501 #ifdef WHERETRACE_ENABLED /* 0x4 */
116502 if( sqlite3WhereTrace&0x4 ){
116503 sqlite3DebugPrintf("Skip %s cost=%-3d,%3d order=%c\n",
116504 wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
116505 isOrdered>=0 ? isOrdered+'0' : '?');
116506 }
116507 #endif
116508 continue;
116509 }
116510 /* If we reach this points it means that the new candidate path
116511 ** needs to be added to the set of best-so-far paths. */
116512 if( nTo<mxChoice ){
116513 /* Increase the size of the aTo set by one */
116514 jj = nTo++;
116515 }else{
116516 /* New path replaces the prior worst to keep count below mxChoice */
@@ -115729,11 +116523,15 @@
116523 wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
116524 isOrdered>=0 ? isOrdered+'0' : '?');
116525 }
116526 #endif
116527 }else{
116528 /* Control reaches here if best-so-far path pTo=aTo[jj] covers the
116529 ** same set of loops and has the sam isOrdered setting as the
116530 ** candidate path. Check to see if the candidate should replace
116531 ** pTo or if the candidate should be skipped */
116532 if( pTo->rCost<rCost || (pTo->rCost==rCost && pTo->nRow<=nOut) ){
116533 #ifdef WHERETRACE_ENABLED /* 0x4 */
116534 if( sqlite3WhereTrace&0x4 ){
116535 sqlite3DebugPrintf(
116536 "Skip %s cost=%-3d,%3d order=%c",
116537 wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
@@ -115741,15 +116539,17 @@
116539 sqlite3DebugPrintf(" vs %s cost=%-3d,%d order=%c\n",
116540 wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
116541 pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
116542 }
116543 #endif
116544 /* Discard the candidate path from further consideration */
116545 testcase( pTo->rCost==rCost );
116546 continue;
116547 }
116548 testcase( pTo->rCost==rCost+1 );
116549 /* Control reaches here if the candidate path is better than the
116550 ** pTo path. Replace pTo with the candidate. */
116551 #ifdef WHERETRACE_ENABLED /* 0x4 */
116552 if( sqlite3WhereTrace&0x4 ){
116553 sqlite3DebugPrintf(
116554 "Update %s cost=%-3d,%3d order=%c",
116555 wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
@@ -115763,19 +116563,24 @@
116563 /* pWLoop is a winner. Add it to the set of best so far */
116564 pTo->maskLoop = pFrom->maskLoop | pWLoop->maskSelf;
116565 pTo->revLoop = revMask;
116566 pTo->nRow = nOut;
116567 pTo->rCost = rCost;
116568 pTo->rUnsorted = rUnsorted;
116569 pTo->isOrdered = isOrdered;
116570 memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop);
116571 pTo->aLoop[iLoop] = pWLoop;
116572 if( nTo>=mxChoice ){
116573 mxI = 0;
116574 mxCost = aTo[0].rCost;
116575 mxUnsorted = aTo[0].nRow;
116576 for(jj=1, pTo=&aTo[1]; jj<mxChoice; jj++, pTo++){
116577 if( pTo->rCost>mxCost
116578 || (pTo->rCost==mxCost && pTo->rUnsorted>mxUnsorted)
116579 ){
116580 mxCost = pTo->rCost;
116581 mxUnsorted = pTo->rUnsorted;
116582 mxI = jj;
116583 }
116584 }
116585 }
116586 }
@@ -115909,11 +116714,11 @@
116714 pLoop->rRun = 33; /* 33==sqlite3LogEst(10) */
116715 }else{
116716 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
116717 assert( pLoop->aLTermSpace==pLoop->aLTerm );
116718 assert( ArraySize(pLoop->aLTermSpace)==4 );
116719 if( !IsUniqueIndex(pIdx)
116720 || pIdx->pPartIdxWhere!=0
116721 || pIdx->nKeyCol>ArraySize(pLoop->aLTermSpace)
116722 ) continue;
116723 for(j=0; j<pIdx->nKeyCol; j++){
116724 pTerm = findTerm(pWC, iCur, pIdx->aiColumn[j], 0, WO_EQ, pIdx);
@@ -116399,10 +117204,11 @@
117204 }
117205 op = OP_OpenWrite;
117206 pWInfo->aiCurOnePass[1] = iIndexCur;
117207 }else if( iIdxCur && (wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ){
117208 iIndexCur = iIdxCur;
117209 if( wctrlFlags & WHERE_REOPEN_IDX ) op = OP_ReopenIdx;
117210 }else{
117211 iIndexCur = pParse->nTab++;
117212 }
117213 pLevel->iIdxCur = iIndexCur;
117214 assert( pIx->pSchema==pTab->pSchema );
@@ -120723,10 +121529,16 @@
121529 testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' );
121530 testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' );
121531 testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' );
121532 testcase( z[0]=='9' );
121533 *tokenType = TK_INTEGER;
121534 #ifndef SQLITE_OMIT_HEX_INTEGER
121535 if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){
121536 for(i=3; sqlite3Isxdigit(z[i]); i++){}
121537 return i;
121538 }
121539 #endif
121540 for(i=0; sqlite3Isdigit(z[i]); i++){}
121541 #ifndef SQLITE_OMIT_FLOATING_POINT
121542 if( z[i]=='.' ){
121543 i++;
121544 while( sqlite3Isdigit(z[i]) ){ i++; }
@@ -122170,10 +122982,12 @@
122982 /*
122983 ** Close an existing SQLite database
122984 */
122985 static int sqlite3Close(sqlite3 *db, int forceZombie){
122986 if( !db ){
122987 /* EVIDENCE-OF: R-63257-11740 Calling sqlite3_close() or
122988 ** sqlite3_close_v2() with a NULL pointer argument is a harmless no-op. */
122989 return SQLITE_OK;
122990 }
122991 if( !sqlite3SafetyCheckSickOrOk(db) ){
122992 return SQLITE_MISUSE_BKPT;
122993 }
@@ -122399,11 +123213,11 @@
123213
123214 /*
123215 ** Return a static string containing the name corresponding to the error code
123216 ** specified in the argument.
123217 */
123218 #if (defined(SQLITE_DEBUG) && SQLITE_OS_WIN) || defined(SQLITE_TEST)
123219 SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
123220 const char *zName = 0;
123221 int i, origRc = rc;
123222 for(i=0; i<2 && zName==0; i++, rc &= 0xff){
123223 switch( rc ){
@@ -122434,11 +123248,10 @@
123248 case SQLITE_IOERR_TRUNCATE: zName = "SQLITE_IOERR_TRUNCATE"; break;
123249 case SQLITE_IOERR_FSTAT: zName = "SQLITE_IOERR_FSTAT"; break;
123250 case SQLITE_IOERR_UNLOCK: zName = "SQLITE_IOERR_UNLOCK"; break;
123251 case SQLITE_IOERR_RDLOCK: zName = "SQLITE_IOERR_RDLOCK"; break;
123252 case SQLITE_IOERR_DELETE: zName = "SQLITE_IOERR_DELETE"; break;
 
123253 case SQLITE_IOERR_NOMEM: zName = "SQLITE_IOERR_NOMEM"; break;
123254 case SQLITE_IOERR_ACCESS: zName = "SQLITE_IOERR_ACCESS"; break;
123255 case SQLITE_IOERR_CHECKRESERVEDLOCK:
123256 zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
123257 case SQLITE_IOERR_LOCK: zName = "SQLITE_IOERR_LOCK"; break;
@@ -123419,11 +124232,11 @@
124232 SQLITE_MAX_COMPOUND_SELECT,
124233 SQLITE_MAX_VDBE_OP,
124234 SQLITE_MAX_FUNCTION_ARG,
124235 SQLITE_MAX_ATTACHED,
124236 SQLITE_MAX_LIKE_PATTERN_LENGTH,
124237 SQLITE_MAX_VARIABLE_NUMBER, /* IMP: R-38091-32352 */
124238 SQLITE_MAX_TRIGGER_DEPTH,
124239 };
124240
124241 /*
124242 ** Make sure the hard limits are set to reasonable values
@@ -123444,12 +124257,12 @@
124257 # error SQLITE_MAX_VDBE_OP must be at least 40
124258 #endif
124259 #if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>1000
124260 # error SQLITE_MAX_FUNCTION_ARG must be between 0 and 1000
124261 #endif
124262 #if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>125
124263 # error SQLITE_MAX_ATTACHED must be between 0 and 125
124264 #endif
124265 #if SQLITE_MAX_LIKE_PATTERN_LENGTH<1
124266 # error SQLITE_MAX_LIKE_PATTERN_LENGTH must be at least 1
124267 #endif
124268 #if SQLITE_MAX_COLUMN>32767
@@ -124704,10 +125517,20 @@
125517 sqlite3GlobalConfig.pVdbeBranchArg = va_arg(ap,void*);
125518 #endif
125519 break;
125520 }
125521
125522 /* sqlite3_test_control(SQLITE_TESTCTRL_ISINIT);
125523 **
125524 ** Return SQLITE_OK if SQLite has been initialized and SQLITE_ERROR if
125525 ** not.
125526 */
125527 case SQLITE_TESTCTRL_ISINIT: {
125528 if( sqlite3GlobalConfig.isInit==0 ) rc = SQLITE_ERROR;
125529 break;
125530 }
125531
125532 }
125533 va_end(ap);
125534 #endif /* SQLITE_OMIT_BUILTIN_TEST */
125535 return rc;
125536 }
@@ -124752,11 +125575,11 @@
125575 const char *zParam, /* URI parameter sought */
125576 sqlite3_int64 bDflt /* return if parameter is missing */
125577 ){
125578 const char *z = sqlite3_uri_parameter(zFilename, zParam);
125579 sqlite3_int64 v;
125580 if( z && sqlite3DecOrHexToI64(z, &v)==SQLITE_OK ){
125581 bDflt = v;
125582 }
125583 return bDflt;
125584 }
125585
@@ -126283,11 +127106,11 @@
127106
127107 /* fts3_tokenize_vtab.c */
127108 SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *);
127109
127110 /* fts3_unicode2.c (functions generated by parsing unicode text files) */
127111 #ifndef SQLITE_DISABLE_FTS3_UNICODE
127112 SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int, int);
127113 SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int);
127114 SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int);
127115 #endif
127116
@@ -129753,11 +130576,11 @@
130576 ** to by the argument to point to the "simple" tokenizer implementation.
130577 ** And so on.
130578 */
130579 SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule);
130580 SQLITE_PRIVATE void sqlite3Fts3PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule);
130581 #ifndef SQLITE_DISABLE_FTS3_UNICODE
130582 SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const**ppModule);
130583 #endif
130584 #ifdef SQLITE_ENABLE_ICU
130585 SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule);
130586 #endif
@@ -129771,20 +130594,20 @@
130594 SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){
130595 int rc = SQLITE_OK;
130596 Fts3Hash *pHash = 0;
130597 const sqlite3_tokenizer_module *pSimple = 0;
130598 const sqlite3_tokenizer_module *pPorter = 0;
130599 #ifndef SQLITE_DISABLE_FTS3_UNICODE
130600 const sqlite3_tokenizer_module *pUnicode = 0;
130601 #endif
130602
130603 #ifdef SQLITE_ENABLE_ICU
130604 const sqlite3_tokenizer_module *pIcu = 0;
130605 sqlite3Fts3IcuTokenizerModule(&pIcu);
130606 #endif
130607
130608 #ifndef SQLITE_DISABLE_FTS3_UNICODE
130609 sqlite3Fts3UnicodeTokenizer(&pUnicode);
130610 #endif
130611
130612 #ifdef SQLITE_TEST
130613 rc = sqlite3Fts3InitTerm(db);
@@ -129808,11 +130631,11 @@
130631 /* Load the built-in tokenizers into the hash table */
130632 if( rc==SQLITE_OK ){
130633 if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple)
130634 || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter)
130635
130636 #ifndef SQLITE_DISABLE_FTS3_UNICODE
130637 || sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode)
130638 #endif
130639 #ifdef SQLITE_ENABLE_ICU
130640 || (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu))
130641 #endif
@@ -143068,11 +143891,11 @@
143891 ******************************************************************************
143892 **
143893 ** Implementation of the "unicode" full-text-search tokenizer.
143894 */
143895
143896 #ifndef SQLITE_DISABLE_FTS3_UNICODE
143897
143898 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
143899
143900 /* #include <assert.h> */
143901 /* #include <stdlib.h> */
@@ -143284,11 +144107,11 @@
144107 memset(pNew, 0, sizeof(unicode_tokenizer));
144108 pNew->bRemoveDiacritic = 1;
144109
144110 for(i=0; rc==SQLITE_OK && i<nArg; i++){
144111 const char *z = azArg[i];
144112 int n = (int)strlen(z);
144113
144114 if( n==19 && memcmp("remove_diacritics=1", z, 19)==0 ){
144115 pNew->bRemoveDiacritic = 1;
144116 }
144117 else if( n==19 && memcmp("remove_diacritics=0", z, 19)==0 ){
@@ -143371,11 +144194,11 @@
144194 int *piEnd, /* OUT: Ending offset of token */
144195 int *piPos /* OUT: Position integer of token */
144196 ){
144197 unicode_cursor *pCsr = (unicode_cursor *)pC;
144198 unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer);
144199 int iCode = 0;
144200 char *zOut;
144201 const unsigned char *z = &pCsr->aInput[pCsr->iOff];
144202 const unsigned char *zStart = z;
144203 const unsigned char *zEnd;
144204 const unsigned char *zTerm = &pCsr->aInput[pCsr->nInput];
@@ -143416,15 +144239,15 @@
144239 }while( unicodeIsAlnum(p, iCode)
144240 || sqlite3FtsUnicodeIsdiacritic(iCode)
144241 );
144242
144243 /* Set the output variables and return. */
144244 pCsr->iOff = (int)(z - pCsr->aInput);
144245 *paToken = pCsr->zToken;
144246 *pnToken = (int)(zOut - pCsr->zToken);
144247 *piStart = (int)(zStart - pCsr->aInput);
144248 *piEnd = (int)(zEnd - pCsr->aInput);
144249 *piPos = pCsr->iToken++;
144250 return SQLITE_OK;
144251 }
144252
144253 /*
@@ -143443,11 +144266,11 @@
144266 };
144267 *ppModule = &module;
144268 }
144269
144270 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
144271 #endif /* ifndef SQLITE_DISABLE_FTS3_UNICODE */
144272
144273 /************** End of fts3_unicode.c ****************************************/
144274 /************** Begin file fts3_unicode2.c ***********************************/
144275 /*
144276 ** 2012 May 25
@@ -143464,11 +144287,11 @@
144287
144288 /*
144289 ** DO NOT EDIT THIS MACHINE GENERATED FILE.
144290 */
144291
144292 #ifndef SQLITE_DISABLE_FTS3_UNICODE
144293 #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
144294
144295 /* #include <assert.h> */
144296
144297 /*
@@ -143488,11 +144311,11 @@
144311 ** the size of the range (always at least 1). In other words, the value
144312 ** ((C<<22) + N) represents a range of N codepoints starting with codepoint
144313 ** C. It is not possible to represent a range larger than 1023 codepoints
144314 ** using this format.
144315 */
144316 static const unsigned int aEntry[] = {
144317 0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07,
144318 0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01,
144319 0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401,
144320 0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01,
144321 0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163C01,
@@ -143580,11 +144403,11 @@
144403
144404 if( c<128 ){
144405 return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
144406 }else if( c<(1<<22) ){
144407 unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
144408 int iRes = 0;
144409 int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
144410 int iLo = 0;
144411 while( iHi>=iLo ){
144412 int iTest = (iHi + iLo) / 2;
144413 if( key >= aEntry[iTest] ){
@@ -143651,11 +144474,11 @@
144474 iHi = iTest-1;
144475 }
144476 }
144477 assert( key>=aDia[iRes] );
144478 return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
144479 }
144480
144481
144482 /*
144483 ** Return true if the argument interpreted as a unicode codepoint
144484 ** is a diacritical modifier character.
@@ -143811,11 +144634,11 @@
144634 }
144635
144636 return ret;
144637 }
144638 #endif /* defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) */
144639 #endif /* !defined(SQLITE_DISABLE_FTS3_UNICODE) */
144640
144641 /************** End of fts3_unicode2.c ***************************************/
144642 /************** Begin file rtree.c *******************************************/
144643 /*
144644 ** 2001 September 15
@@ -145348,13 +146171,17 @@
146171 int rc = SQLITE_OK;
146172 int iCell = 0;
146173
146174 rtreeReference(pRtree);
146175
146176 /* Reset the cursor to the same state as rtreeOpen() leaves it in. */
146177 freeCursorConstraints(pCsr);
146178 sqlite3_free(pCsr->aPoint);
146179 memset(pCsr, 0, sizeof(RtreeCursor));
146180 pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
146181
146182 pCsr->iStrategy = idxNum;
 
146183 if( idxNum==1 ){
146184 /* Special case - lookup by rowid. */
146185 RtreeNode *pLeaf; /* Leaf on which the required cell resides */
146186 RtreeSearchPoint *p; /* Search point for the the leaf */
146187 i64 iRowid = sqlite3_value_int64(argv[0]);
146188
+73 -57
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -107,11 +107,11 @@
107107
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108108
** [sqlite_version()] and [sqlite_source_id()].
109109
*/
110110
#define SQLITE_VERSION "3.8.6"
111111
#define SQLITE_VERSION_NUMBER 3008006
112
-#define SQLITE_SOURCE_ID "2014-07-01 11:54:02 21981e35062cc6b30e9576786cbf55265a7a4d41"
112
+#define SQLITE_SOURCE_ID "2014-08-12 16:13:37 6715991296886c2a02b9a285a1e61189ad1f79c0"
113113
114114
/*
115115
** CAPI3REF: Run-Time Library Version Numbers
116116
** KEYWORDS: sqlite3_version, sqlite3_sourceid
117117
**
@@ -267,19 +267,19 @@
267267
/*
268268
** CAPI3REF: Closing A Database Connection
269269
**
270270
** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
271271
** for the [sqlite3] object.
272
-** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if
272
+** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
273273
** the [sqlite3] object is successfully destroyed and all associated
274274
** resources are deallocated.
275275
**
276276
** ^If the database connection is associated with unfinalized prepared
277277
** statements or unfinished sqlite3_backup objects then sqlite3_close()
278278
** will leave the database connection open and return [SQLITE_BUSY].
279279
** ^If sqlite3_close_v2() is called with unfinalized prepared statements
280
-** and unfinished sqlite3_backups, then the database connection becomes
280
+** and/or unfinished sqlite3_backups, then the database connection becomes
281281
** an unusable "zombie" which will automatically be deallocated when the
282282
** last prepared statement is finalized or the last sqlite3_backup is
283283
** finished. The sqlite3_close_v2() interface is intended for use with
284284
** host languages that are garbage collected, and where the order in which
285285
** destructors are called is arbitrary.
@@ -288,11 +288,11 @@
288288
** [sqlite3_blob_close | close] all [BLOB handles], and
289289
** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
290290
** with the [sqlite3] object prior to attempting to close the object. ^If
291291
** sqlite3_close_v2() is called on a [database connection] that still has
292292
** outstanding [prepared statements], [BLOB handles], and/or
293
-** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation
293
+** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
294294
** of resources is deferred until all [prepared statements], [BLOB handles],
295295
** and [sqlite3_backup] objects are also destroyed.
296296
**
297297
** ^If an [sqlite3] object is destroyed while a transaction is open,
298298
** the transaction is automatically rolled back.
@@ -384,20 +384,18 @@
384384
char **errmsg /* Error msg written here */
385385
);
386386
387387
/*
388388
** CAPI3REF: Result Codes
389
-** KEYWORDS: SQLITE_OK {error code} {error codes}
390
-** KEYWORDS: {result code} {result codes}
389
+** KEYWORDS: {result code definitions}
391390
**
392391
** Many SQLite functions return an integer result code from the set shown
393392
** here in order to indicate success or failure.
394393
**
395394
** New error codes may be added in future versions of SQLite.
396395
**
397
-** See also: [SQLITE_IOERR_READ | extended result codes],
398
-** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
396
+** See also: [extended result code definitions]
399397
*/
400398
#define SQLITE_OK 0 /* Successful result */
401399
/* beginning-of-error-codes */
402400
#define SQLITE_ERROR 1 /* SQL error or missing database */
403401
#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
@@ -431,30 +429,23 @@
431429
#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */
432430
/* end-of-error-codes */
433431
434432
/*
435433
** CAPI3REF: Extended Result Codes
436
-** KEYWORDS: {extended error code} {extended error codes}
437
-** KEYWORDS: {extended result code} {extended result codes}
434
+** KEYWORDS: {extended result code definitions}
438435
**
439
-** In its default configuration, SQLite API routines return one of 26 integer
440
-** [SQLITE_OK | result codes]. However, experience has shown that many of
436
+** In its default configuration, SQLite API routines return one of 30 integer
437
+** [result codes]. However, experience has shown that many of
441438
** these result codes are too coarse-grained. They do not provide as
442439
** much information about problems as programmers might like. In an effort to
443440
** address this, newer versions of SQLite (version 3.3.8 and later) include
444441
** support for additional result codes that provide more detailed information
445
-** about errors. The extended result codes are enabled or disabled
442
+** about errors. These [extended result codes] are enabled or disabled
446443
** on a per database connection basis using the
447
-** [sqlite3_extended_result_codes()] API.
448
-**
449
-** Some of the available extended result codes are listed here.
450
-** One may expect the number of extended result codes will increase
451
-** over time. Software that uses extended result codes should expect
452
-** to see new result codes in future releases of SQLite.
453
-**
454
-** The SQLITE_OK result code will never be extended. It will always
455
-** be exactly zero.
444
+** [sqlite3_extended_result_codes()] API. Or, the extended code for
445
+** the most recent error can be obtained using
446
+** [sqlite3_extended_errcode()].
456447
*/
457448
#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
458449
#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
459450
#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8))
460451
#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8))
@@ -683,11 +674,11 @@
683674
** write return values. Potential uses for xFileControl() might be
684675
** functions to enable blocking locks with timeouts, to change the
685676
** locking strategy (for example to use dot-file locks), to inquire
686677
** about the status of a lock, or to break stale locks. The SQLite
687678
** core reserves all opcodes less than 100 for its own use.
688
-** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available.
679
+** A [file control opcodes | list of opcodes] less than 100 is available.
689680
** Applications that define a custom xFileControl method should use opcodes
690681
** greater than 100 to avoid conflicts. VFS implementations should
691682
** return [SQLITE_NOTFOUND] for file control opcodes that they do not
692683
** recognize.
693684
**
@@ -756,10 +747,11 @@
756747
/* Additional methods may be added in future releases */
757748
};
758749
759750
/*
760751
** CAPI3REF: Standard File Control Opcodes
752
+** KEYWORDS: {file control opcodes} {file control opcode}
761753
**
762754
** These integer constants are opcodes for the xFileControl method
763755
** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
764756
** interface.
765757
**
@@ -2035,31 +2027,37 @@
20352027
SQLITE_API int sqlite3_complete16(const void *sql);
20362028
20372029
/*
20382030
** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
20392031
**
2040
-** ^This routine sets a callback function that might be invoked whenever
2041
-** an attempt is made to open a database table that another thread
2042
-** or process has locked.
2032
+** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
2033
+** that might be invoked with argument P whenever
2034
+** an attempt is made to access a database table associated with
2035
+** [database connection] D when another thread
2036
+** or process has the table locked.
2037
+** The sqlite3_busy_handler() interface is used to implement
2038
+** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout].
20432039
**
2044
-** ^If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]
2040
+** ^If the busy callback is NULL, then [SQLITE_BUSY]
20452041
** is returned immediately upon encountering the lock. ^If the busy callback
20462042
** is not NULL, then the callback might be invoked with two arguments.
20472043
**
20482044
** ^The first argument to the busy handler is a copy of the void* pointer which
20492045
** is the third argument to sqlite3_busy_handler(). ^The second argument to
20502046
** the busy handler callback is the number of times that the busy handler has
2051
-** been invoked for this locking event. ^If the
2047
+** been invoked for the same locking event. ^If the
20522048
** busy callback returns 0, then no additional attempts are made to
2053
-** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned.
2049
+** access the database and [SQLITE_BUSY] is returned
2050
+** to the application.
20542051
** ^If the callback returns non-zero, then another attempt
2055
-** is made to open the database for reading and the cycle repeats.
2052
+** is made to access the database and the cycle repeats.
20562053
**
20572054
** The presence of a busy handler does not guarantee that it will be invoked
20582055
** when there is lock contention. ^If SQLite determines that invoking the busy
20592056
** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY]
2060
-** or [SQLITE_IOERR_BLOCKED] instead of invoking the busy handler.
2057
+** to the application instead of invoking the
2058
+** busy handler.
20612059
** Consider a scenario where one process is holding a read lock that
20622060
** it is trying to promote to a reserved lock and
20632061
** a second process is holding a reserved lock that it is trying
20642062
** to promote to an exclusive lock. The first process cannot proceed
20652063
** because it is blocked by the second and the second process cannot
@@ -2069,32 +2067,19 @@
20692067
** will induce the first process to release its read lock and allow
20702068
** the second process to proceed.
20712069
**
20722070
** ^The default busy callback is NULL.
20732071
**
2074
-** ^The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED]
2075
-** when SQLite is in the middle of a large transaction where all the
2076
-** changes will not fit into the in-memory cache. SQLite will
2077
-** already hold a RESERVED lock on the database file, but it needs
2078
-** to promote this lock to EXCLUSIVE so that it can spill cache
2079
-** pages into the database file without harm to concurrent
2080
-** readers. ^If it is unable to promote the lock, then the in-memory
2081
-** cache will be left in an inconsistent state and so the error
2082
-** code is promoted from the relatively benign [SQLITE_BUSY] to
2083
-** the more severe [SQLITE_IOERR_BLOCKED]. ^This error code promotion
2084
-** forces an automatic rollback of the changes. See the
2085
-** <a href="/cvstrac/wiki?p=CorruptionFollowingBusyError">
2086
-** CorruptionFollowingBusyError</a> wiki page for a discussion of why
2087
-** this is important.
2088
-**
20892072
** ^(There can only be a single busy handler defined for each
20902073
** [database connection]. Setting a new busy handler clears any
20912074
** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()]
2092
-** will also set or clear the busy handler.
2075
+** or evaluating [PRAGMA busy_timeout=N] will change the
2076
+** busy handler and thus clear any previously set busy handler.
20932077
**
20942078
** The busy callback should not take any actions which modify the
2095
-** database connection that invoked the busy handler. Any such actions
2079
+** database connection that invoked the busy handler. In other words,
2080
+** the busy handler is not reentrant. Any such actions
20962081
** result in undefined behavior.
20972082
**
20982083
** A busy handler must not close the database connection
20992084
** or [prepared statement] that invoked the busy handler.
21002085
*/
@@ -2106,19 +2091,21 @@
21062091
** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps
21072092
** for a specified amount of time when a table is locked. ^The handler
21082093
** will sleep multiple times until at least "ms" milliseconds of sleeping
21092094
** have accumulated. ^After at least "ms" milliseconds of sleeping,
21102095
** the handler returns 0 which causes [sqlite3_step()] to return
2111
-** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED].
2096
+** [SQLITE_BUSY].
21122097
**
21132098
** ^Calling this routine with an argument less than or equal to zero
21142099
** turns off all busy handlers.
21152100
**
21162101
** ^(There can only be a single busy handler for a particular
21172102
** [database connection] any any given moment. If another busy handler
21182103
** was defined (using [sqlite3_busy_handler()]) prior to calling
21192104
** this routine, that other busy handler is cleared.)^
2105
+**
2106
+** See also: [PRAGMA busy_timeout]
21202107
*/
21212108
SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
21222109
21232110
/*
21242111
** CAPI3REF: Convenience Routines For Running Queries
@@ -2516,12 +2503,12 @@
25162503
** return either [SQLITE_OK] or one of these two constants in order
25172504
** to signal SQLite whether or not the action is permitted. See the
25182505
** [sqlite3_set_authorizer | authorizer documentation] for additional
25192506
** information.
25202507
**
2521
-** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
2522
-** from the [sqlite3_vtab_on_conflict()] interface.
2508
+** Note that SQLITE_IGNORE is also used as a [conflict resolution mode]
2509
+** returned from the [sqlite3_vtab_on_conflict()] interface.
25232510
*/
25242511
#define SQLITE_DENY 1 /* Abort the SQL statement with an error */
25252512
#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
25262513
25272514
/*
@@ -4703,10 +4690,17 @@
47034690
** the name of a folder (a.k.a. directory), then all temporary files
47044691
** created by SQLite when using a built-in [sqlite3_vfs | VFS]
47054692
** will be placed in that directory.)^ ^If this variable
47064693
** is a NULL pointer, then SQLite performs a search for an appropriate
47074694
** temporary file directory.
4695
+**
4696
+** Applications are strongly discouraged from using this global variable.
4697
+** It is required to set a temporary folder on Windows Runtime (WinRT).
4698
+** But for all other platforms, it is highly recommended that applications
4699
+** neither read nor write this variable. This global variable is a relic
4700
+** that exists for backwards compatibility of legacy applications and should
4701
+** be avoided in new projects.
47084702
**
47094703
** It is not safe to read or modify this variable in more than one
47104704
** thread at a time. It is not safe to read or modify this variable
47114705
** if a [database connection] is being used at the same time in a separate
47124706
** thread.
@@ -4722,10 +4716,15 @@
47224716
** [sqlite3_malloc] and the pragma may attempt to free that memory
47234717
** using [sqlite3_free].
47244718
** Hence, if this variable is modified directly, either it should be
47254719
** made NULL or made to point to memory obtained from [sqlite3_malloc]
47264720
** or else the use of the [temp_store_directory pragma] should be avoided.
4721
+** Except when requested by the [temp_store_directory pragma], SQLite
4722
+** does not free the memory that sqlite3_temp_directory points to. If
4723
+** the application wants that memory to be freed, it must do
4724
+** so itself, taking care to only do so after all [database connection]
4725
+** objects have been destroyed.
47274726
**
47284727
** <b>Note to Windows Runtime users:</b> The temporary directory must be set
47294728
** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various
47304729
** features that require the use of temporary files may fail. Here is an
47314730
** example of how to do this using C++ with the Windows Runtime:
@@ -5856,14 +5855,16 @@
58565855
** <ul>
58575856
** <li> SQLITE_MUTEX_FAST
58585857
** <li> SQLITE_MUTEX_RECURSIVE
58595858
** <li> SQLITE_MUTEX_STATIC_MASTER
58605859
** <li> SQLITE_MUTEX_STATIC_MEM
5861
-** <li> SQLITE_MUTEX_STATIC_MEM2
5860
+** <li> SQLITE_MUTEX_STATIC_OPEN
58625861
** <li> SQLITE_MUTEX_STATIC_PRNG
58635862
** <li> SQLITE_MUTEX_STATIC_LRU
5864
-** <li> SQLITE_MUTEX_STATIC_LRU2
5863
+** <li> SQLITE_MUTEX_STATIC_PMEM
5864
+** <li> SQLITE_MUTEX_STATIC_APP1
5865
+** <li> SQLITE_MUTEX_STATIC_APP2
58655866
** </ul>)^
58665867
**
58675868
** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
58685869
** cause sqlite3_mutex_alloc() to create
58695870
** a new mutex. ^The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
@@ -6063,10 +6064,13 @@
60636064
#define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */
60646065
#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */
60656066
#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
60666067
#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */
60676068
#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */
6069
+#define SQLITE_MUTEX_STATIC_APP1 8 /* For use by application */
6070
+#define SQLITE_MUTEX_STATIC_APP2 9 /* For use by application */
6071
+#define SQLITE_MUTEX_STATIC_APP3 10 /* For use by application */
60686072
60696073
/*
60706074
** CAPI3REF: Retrieve the mutex for a database connection
60716075
**
60726076
** ^This interface returns a pointer the [sqlite3_mutex] object that
@@ -6158,11 +6162,12 @@
61586162
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
61596163
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19
61606164
#define SQLITE_TESTCTRL_NEVER_CORRUPT 20
61616165
#define SQLITE_TESTCTRL_VDBE_COVERAGE 21
61626166
#define SQLITE_TESTCTRL_BYTEORDER 22
6163
-#define SQLITE_TESTCTRL_LAST 22
6167
+#define SQLITE_TESTCTRL_ISINIT 23
6168
+#define SQLITE_TESTCTRL_LAST 23
61646169
61656170
/*
61666171
** CAPI3REF: SQLite Runtime Status
61676172
**
61686173
** ^This interface is used to retrieve runtime status information
@@ -7141,10 +7146,13 @@
71417146
** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism
71427147
** configured by this function.
71437148
**
71447149
** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
71457150
** from SQL.
7151
+**
7152
+** ^Checkpoints initiated by this mechanism are
7153
+** [sqlite3_wal_checkpoint_v2|PASSIVE].
71467154
**
71477155
** ^Every new [database connection] defaults to having the auto-checkpoint
71487156
** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
71497157
** pages. The use of this interface
71507158
** is only necessary if the default setting is found to be suboptimal
@@ -7158,10 +7166,14 @@
71587166
** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X
71597167
** on [database connection] D to be [checkpointed]. ^If X is NULL or an
71607168
** empty string, then a checkpoint is run on all databases of
71617169
** connection D. ^If the database connection D is not in
71627170
** [WAL | write-ahead log mode] then this interface is a harmless no-op.
7171
+** ^The [sqlite3_wal_checkpoint(D,X)] interface initiates a
7172
+** [sqlite3_wal_checkpoint_v2|PASSIVE] checkpoint.
7173
+** Use the [sqlite3_wal_checkpoint_v2()] interface to get a FULL
7174
+** or RESET checkpoint.
71637175
**
71647176
** ^The [wal_checkpoint pragma] can be used to invoke this interface
71657177
** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the
71667178
** [wal_autocheckpoint pragma] can be used to cause this interface to be
71677179
** run whenever the WAL reaches a certain size threshold.
@@ -7180,22 +7192,25 @@
71807192
** <dl>
71817193
** <dt>SQLITE_CHECKPOINT_PASSIVE<dd>
71827194
** Checkpoint as many frames as possible without waiting for any database
71837195
** readers or writers to finish. Sync the db file if all frames in the log
71847196
** are checkpointed. This mode is the same as calling
7185
-** sqlite3_wal_checkpoint(). The busy-handler callback is never invoked.
7197
+** sqlite3_wal_checkpoint(). The [sqlite3_busy_handler|busy-handler callback]
7198
+** is never invoked.
71867199
**
71877200
** <dt>SQLITE_CHECKPOINT_FULL<dd>
7188
-** This mode blocks (calls the busy-handler callback) until there is no
7201
+** This mode blocks (it invokes the
7202
+** [sqlite3_busy_handler|busy-handler callback]) until there is no
71897203
** database writer and all readers are reading from the most recent database
71907204
** snapshot. It then checkpoints all frames in the log file and syncs the
71917205
** database file. This call blocks database writers while it is running,
71927206
** but not database readers.
71937207
**
71947208
** <dt>SQLITE_CHECKPOINT_RESTART<dd>
71957209
** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after
7196
-** checkpointing the log file it blocks (calls the busy-handler callback)
7210
+** checkpointing the log file it blocks (calls the
7211
+** [sqlite3_busy_handler|busy-handler callback])
71977212
** until all readers are reading from the database file only. This ensures
71987213
** that the next client to write to the database file restarts the log file
71997214
** from the beginning. This call blocks database writers while it is running,
72007215
** but not database readers.
72017216
** </dl>
@@ -7329,10 +7344,11 @@
73297344
*/
73307345
SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
73317346
73327347
/*
73337348
** CAPI3REF: Conflict resolution modes
7349
+** KEYWORDS: {conflict resolution mode}
73347350
**
73357351
** These constants are returned by [sqlite3_vtab_on_conflict()] to
73367352
** inform a [virtual table] implementation what the [ON CONFLICT] mode
73377353
** is for the SQL statement being evaluated.
73387354
**
73397355
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -107,11 +107,11 @@
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.8.6"
111 #define SQLITE_VERSION_NUMBER 3008006
112 #define SQLITE_SOURCE_ID "2014-07-01 11:54:02 21981e35062cc6b30e9576786cbf55265a7a4d41"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
@@ -267,19 +267,19 @@
267 /*
268 ** CAPI3REF: Closing A Database Connection
269 **
270 ** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
271 ** for the [sqlite3] object.
272 ** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if
273 ** the [sqlite3] object is successfully destroyed and all associated
274 ** resources are deallocated.
275 **
276 ** ^If the database connection is associated with unfinalized prepared
277 ** statements or unfinished sqlite3_backup objects then sqlite3_close()
278 ** will leave the database connection open and return [SQLITE_BUSY].
279 ** ^If sqlite3_close_v2() is called with unfinalized prepared statements
280 ** and unfinished sqlite3_backups, then the database connection becomes
281 ** an unusable "zombie" which will automatically be deallocated when the
282 ** last prepared statement is finalized or the last sqlite3_backup is
283 ** finished. The sqlite3_close_v2() interface is intended for use with
284 ** host languages that are garbage collected, and where the order in which
285 ** destructors are called is arbitrary.
@@ -288,11 +288,11 @@
288 ** [sqlite3_blob_close | close] all [BLOB handles], and
289 ** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
290 ** with the [sqlite3] object prior to attempting to close the object. ^If
291 ** sqlite3_close_v2() is called on a [database connection] that still has
292 ** outstanding [prepared statements], [BLOB handles], and/or
293 ** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation
294 ** of resources is deferred until all [prepared statements], [BLOB handles],
295 ** and [sqlite3_backup] objects are also destroyed.
296 **
297 ** ^If an [sqlite3] object is destroyed while a transaction is open,
298 ** the transaction is automatically rolled back.
@@ -384,20 +384,18 @@
384 char **errmsg /* Error msg written here */
385 );
386
387 /*
388 ** CAPI3REF: Result Codes
389 ** KEYWORDS: SQLITE_OK {error code} {error codes}
390 ** KEYWORDS: {result code} {result codes}
391 **
392 ** Many SQLite functions return an integer result code from the set shown
393 ** here in order to indicate success or failure.
394 **
395 ** New error codes may be added in future versions of SQLite.
396 **
397 ** See also: [SQLITE_IOERR_READ | extended result codes],
398 ** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
399 */
400 #define SQLITE_OK 0 /* Successful result */
401 /* beginning-of-error-codes */
402 #define SQLITE_ERROR 1 /* SQL error or missing database */
403 #define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
@@ -431,30 +429,23 @@
431 #define SQLITE_DONE 101 /* sqlite3_step() has finished executing */
432 /* end-of-error-codes */
433
434 /*
435 ** CAPI3REF: Extended Result Codes
436 ** KEYWORDS: {extended error code} {extended error codes}
437 ** KEYWORDS: {extended result code} {extended result codes}
438 **
439 ** In its default configuration, SQLite API routines return one of 26 integer
440 ** [SQLITE_OK | result codes]. However, experience has shown that many of
441 ** these result codes are too coarse-grained. They do not provide as
442 ** much information about problems as programmers might like. In an effort to
443 ** address this, newer versions of SQLite (version 3.3.8 and later) include
444 ** support for additional result codes that provide more detailed information
445 ** about errors. The extended result codes are enabled or disabled
446 ** on a per database connection basis using the
447 ** [sqlite3_extended_result_codes()] API.
448 **
449 ** Some of the available extended result codes are listed here.
450 ** One may expect the number of extended result codes will increase
451 ** over time. Software that uses extended result codes should expect
452 ** to see new result codes in future releases of SQLite.
453 **
454 ** The SQLITE_OK result code will never be extended. It will always
455 ** be exactly zero.
456 */
457 #define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
458 #define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
459 #define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8))
460 #define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8))
@@ -683,11 +674,11 @@
683 ** write return values. Potential uses for xFileControl() might be
684 ** functions to enable blocking locks with timeouts, to change the
685 ** locking strategy (for example to use dot-file locks), to inquire
686 ** about the status of a lock, or to break stale locks. The SQLite
687 ** core reserves all opcodes less than 100 for its own use.
688 ** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available.
689 ** Applications that define a custom xFileControl method should use opcodes
690 ** greater than 100 to avoid conflicts. VFS implementations should
691 ** return [SQLITE_NOTFOUND] for file control opcodes that they do not
692 ** recognize.
693 **
@@ -756,10 +747,11 @@
756 /* Additional methods may be added in future releases */
757 };
758
759 /*
760 ** CAPI3REF: Standard File Control Opcodes
 
761 **
762 ** These integer constants are opcodes for the xFileControl method
763 ** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
764 ** interface.
765 **
@@ -2035,31 +2027,37 @@
2035 SQLITE_API int sqlite3_complete16(const void *sql);
2036
2037 /*
2038 ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
2039 **
2040 ** ^This routine sets a callback function that might be invoked whenever
2041 ** an attempt is made to open a database table that another thread
2042 ** or process has locked.
 
 
 
 
2043 **
2044 ** ^If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]
2045 ** is returned immediately upon encountering the lock. ^If the busy callback
2046 ** is not NULL, then the callback might be invoked with two arguments.
2047 **
2048 ** ^The first argument to the busy handler is a copy of the void* pointer which
2049 ** is the third argument to sqlite3_busy_handler(). ^The second argument to
2050 ** the busy handler callback is the number of times that the busy handler has
2051 ** been invoked for this locking event. ^If the
2052 ** busy callback returns 0, then no additional attempts are made to
2053 ** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned.
 
2054 ** ^If the callback returns non-zero, then another attempt
2055 ** is made to open the database for reading and the cycle repeats.
2056 **
2057 ** The presence of a busy handler does not guarantee that it will be invoked
2058 ** when there is lock contention. ^If SQLite determines that invoking the busy
2059 ** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY]
2060 ** or [SQLITE_IOERR_BLOCKED] instead of invoking the busy handler.
 
2061 ** Consider a scenario where one process is holding a read lock that
2062 ** it is trying to promote to a reserved lock and
2063 ** a second process is holding a reserved lock that it is trying
2064 ** to promote to an exclusive lock. The first process cannot proceed
2065 ** because it is blocked by the second and the second process cannot
@@ -2069,32 +2067,19 @@
2069 ** will induce the first process to release its read lock and allow
2070 ** the second process to proceed.
2071 **
2072 ** ^The default busy callback is NULL.
2073 **
2074 ** ^The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED]
2075 ** when SQLite is in the middle of a large transaction where all the
2076 ** changes will not fit into the in-memory cache. SQLite will
2077 ** already hold a RESERVED lock on the database file, but it needs
2078 ** to promote this lock to EXCLUSIVE so that it can spill cache
2079 ** pages into the database file without harm to concurrent
2080 ** readers. ^If it is unable to promote the lock, then the in-memory
2081 ** cache will be left in an inconsistent state and so the error
2082 ** code is promoted from the relatively benign [SQLITE_BUSY] to
2083 ** the more severe [SQLITE_IOERR_BLOCKED]. ^This error code promotion
2084 ** forces an automatic rollback of the changes. See the
2085 ** <a href="/cvstrac/wiki?p=CorruptionFollowingBusyError">
2086 ** CorruptionFollowingBusyError</a> wiki page for a discussion of why
2087 ** this is important.
2088 **
2089 ** ^(There can only be a single busy handler defined for each
2090 ** [database connection]. Setting a new busy handler clears any
2091 ** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()]
2092 ** will also set or clear the busy handler.
 
2093 **
2094 ** The busy callback should not take any actions which modify the
2095 ** database connection that invoked the busy handler. Any such actions
 
2096 ** result in undefined behavior.
2097 **
2098 ** A busy handler must not close the database connection
2099 ** or [prepared statement] that invoked the busy handler.
2100 */
@@ -2106,19 +2091,21 @@
2106 ** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps
2107 ** for a specified amount of time when a table is locked. ^The handler
2108 ** will sleep multiple times until at least "ms" milliseconds of sleeping
2109 ** have accumulated. ^After at least "ms" milliseconds of sleeping,
2110 ** the handler returns 0 which causes [sqlite3_step()] to return
2111 ** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED].
2112 **
2113 ** ^Calling this routine with an argument less than or equal to zero
2114 ** turns off all busy handlers.
2115 **
2116 ** ^(There can only be a single busy handler for a particular
2117 ** [database connection] any any given moment. If another busy handler
2118 ** was defined (using [sqlite3_busy_handler()]) prior to calling
2119 ** this routine, that other busy handler is cleared.)^
 
 
2120 */
2121 SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
2122
2123 /*
2124 ** CAPI3REF: Convenience Routines For Running Queries
@@ -2516,12 +2503,12 @@
2516 ** return either [SQLITE_OK] or one of these two constants in order
2517 ** to signal SQLite whether or not the action is permitted. See the
2518 ** [sqlite3_set_authorizer | authorizer documentation] for additional
2519 ** information.
2520 **
2521 ** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
2522 ** from the [sqlite3_vtab_on_conflict()] interface.
2523 */
2524 #define SQLITE_DENY 1 /* Abort the SQL statement with an error */
2525 #define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
2526
2527 /*
@@ -4703,10 +4690,17 @@
4703 ** the name of a folder (a.k.a. directory), then all temporary files
4704 ** created by SQLite when using a built-in [sqlite3_vfs | VFS]
4705 ** will be placed in that directory.)^ ^If this variable
4706 ** is a NULL pointer, then SQLite performs a search for an appropriate
4707 ** temporary file directory.
 
 
 
 
 
 
 
4708 **
4709 ** It is not safe to read or modify this variable in more than one
4710 ** thread at a time. It is not safe to read or modify this variable
4711 ** if a [database connection] is being used at the same time in a separate
4712 ** thread.
@@ -4722,10 +4716,15 @@
4722 ** [sqlite3_malloc] and the pragma may attempt to free that memory
4723 ** using [sqlite3_free].
4724 ** Hence, if this variable is modified directly, either it should be
4725 ** made NULL or made to point to memory obtained from [sqlite3_malloc]
4726 ** or else the use of the [temp_store_directory pragma] should be avoided.
 
 
 
 
 
4727 **
4728 ** <b>Note to Windows Runtime users:</b> The temporary directory must be set
4729 ** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various
4730 ** features that require the use of temporary files may fail. Here is an
4731 ** example of how to do this using C++ with the Windows Runtime:
@@ -5856,14 +5855,16 @@
5856 ** <ul>
5857 ** <li> SQLITE_MUTEX_FAST
5858 ** <li> SQLITE_MUTEX_RECURSIVE
5859 ** <li> SQLITE_MUTEX_STATIC_MASTER
5860 ** <li> SQLITE_MUTEX_STATIC_MEM
5861 ** <li> SQLITE_MUTEX_STATIC_MEM2
5862 ** <li> SQLITE_MUTEX_STATIC_PRNG
5863 ** <li> SQLITE_MUTEX_STATIC_LRU
5864 ** <li> SQLITE_MUTEX_STATIC_LRU2
 
 
5865 ** </ul>)^
5866 **
5867 ** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
5868 ** cause sqlite3_mutex_alloc() to create
5869 ** a new mutex. ^The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
@@ -6063,10 +6064,13 @@
6063 #define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */
6064 #define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */
6065 #define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
6066 #define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */
6067 #define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */
 
 
 
6068
6069 /*
6070 ** CAPI3REF: Retrieve the mutex for a database connection
6071 **
6072 ** ^This interface returns a pointer the [sqlite3_mutex] object that
@@ -6158,11 +6162,12 @@
6158 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
6159 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19
6160 #define SQLITE_TESTCTRL_NEVER_CORRUPT 20
6161 #define SQLITE_TESTCTRL_VDBE_COVERAGE 21
6162 #define SQLITE_TESTCTRL_BYTEORDER 22
6163 #define SQLITE_TESTCTRL_LAST 22
 
6164
6165 /*
6166 ** CAPI3REF: SQLite Runtime Status
6167 **
6168 ** ^This interface is used to retrieve runtime status information
@@ -7141,10 +7146,13 @@
7141 ** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism
7142 ** configured by this function.
7143 **
7144 ** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
7145 ** from SQL.
 
 
 
7146 **
7147 ** ^Every new [database connection] defaults to having the auto-checkpoint
7148 ** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
7149 ** pages. The use of this interface
7150 ** is only necessary if the default setting is found to be suboptimal
@@ -7158,10 +7166,14 @@
7158 ** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X
7159 ** on [database connection] D to be [checkpointed]. ^If X is NULL or an
7160 ** empty string, then a checkpoint is run on all databases of
7161 ** connection D. ^If the database connection D is not in
7162 ** [WAL | write-ahead log mode] then this interface is a harmless no-op.
 
 
 
 
7163 **
7164 ** ^The [wal_checkpoint pragma] can be used to invoke this interface
7165 ** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the
7166 ** [wal_autocheckpoint pragma] can be used to cause this interface to be
7167 ** run whenever the WAL reaches a certain size threshold.
@@ -7180,22 +7192,25 @@
7180 ** <dl>
7181 ** <dt>SQLITE_CHECKPOINT_PASSIVE<dd>
7182 ** Checkpoint as many frames as possible without waiting for any database
7183 ** readers or writers to finish. Sync the db file if all frames in the log
7184 ** are checkpointed. This mode is the same as calling
7185 ** sqlite3_wal_checkpoint(). The busy-handler callback is never invoked.
 
7186 **
7187 ** <dt>SQLITE_CHECKPOINT_FULL<dd>
7188 ** This mode blocks (calls the busy-handler callback) until there is no
 
7189 ** database writer and all readers are reading from the most recent database
7190 ** snapshot. It then checkpoints all frames in the log file and syncs the
7191 ** database file. This call blocks database writers while it is running,
7192 ** but not database readers.
7193 **
7194 ** <dt>SQLITE_CHECKPOINT_RESTART<dd>
7195 ** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after
7196 ** checkpointing the log file it blocks (calls the busy-handler callback)
 
7197 ** until all readers are reading from the database file only. This ensures
7198 ** that the next client to write to the database file restarts the log file
7199 ** from the beginning. This call blocks database writers while it is running,
7200 ** but not database readers.
7201 ** </dl>
@@ -7329,10 +7344,11 @@
7329 */
7330 SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
7331
7332 /*
7333 ** CAPI3REF: Conflict resolution modes
 
7334 **
7335 ** These constants are returned by [sqlite3_vtab_on_conflict()] to
7336 ** inform a [virtual table] implementation what the [ON CONFLICT] mode
7337 ** is for the SQL statement being evaluated.
7338 **
7339
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -107,11 +107,11 @@
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.8.6"
111 #define SQLITE_VERSION_NUMBER 3008006
112 #define SQLITE_SOURCE_ID "2014-08-12 16:13:37 6715991296886c2a02b9a285a1e61189ad1f79c0"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
@@ -267,19 +267,19 @@
267 /*
268 ** CAPI3REF: Closing A Database Connection
269 **
270 ** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
271 ** for the [sqlite3] object.
272 ** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
273 ** the [sqlite3] object is successfully destroyed and all associated
274 ** resources are deallocated.
275 **
276 ** ^If the database connection is associated with unfinalized prepared
277 ** statements or unfinished sqlite3_backup objects then sqlite3_close()
278 ** will leave the database connection open and return [SQLITE_BUSY].
279 ** ^If sqlite3_close_v2() is called with unfinalized prepared statements
280 ** and/or unfinished sqlite3_backups, then the database connection becomes
281 ** an unusable "zombie" which will automatically be deallocated when the
282 ** last prepared statement is finalized or the last sqlite3_backup is
283 ** finished. The sqlite3_close_v2() interface is intended for use with
284 ** host languages that are garbage collected, and where the order in which
285 ** destructors are called is arbitrary.
@@ -288,11 +288,11 @@
288 ** [sqlite3_blob_close | close] all [BLOB handles], and
289 ** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
290 ** with the [sqlite3] object prior to attempting to close the object. ^If
291 ** sqlite3_close_v2() is called on a [database connection] that still has
292 ** outstanding [prepared statements], [BLOB handles], and/or
293 ** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
294 ** of resources is deferred until all [prepared statements], [BLOB handles],
295 ** and [sqlite3_backup] objects are also destroyed.
296 **
297 ** ^If an [sqlite3] object is destroyed while a transaction is open,
298 ** the transaction is automatically rolled back.
@@ -384,20 +384,18 @@
384 char **errmsg /* Error msg written here */
385 );
386
387 /*
388 ** CAPI3REF: Result Codes
389 ** KEYWORDS: {result code definitions}
 
390 **
391 ** Many SQLite functions return an integer result code from the set shown
392 ** here in order to indicate success or failure.
393 **
394 ** New error codes may be added in future versions of SQLite.
395 **
396 ** See also: [extended result code definitions]
 
397 */
398 #define SQLITE_OK 0 /* Successful result */
399 /* beginning-of-error-codes */
400 #define SQLITE_ERROR 1 /* SQL error or missing database */
401 #define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
@@ -431,30 +429,23 @@
429 #define SQLITE_DONE 101 /* sqlite3_step() has finished executing */
430 /* end-of-error-codes */
431
432 /*
433 ** CAPI3REF: Extended Result Codes
434 ** KEYWORDS: {extended result code definitions}
 
435 **
436 ** In its default configuration, SQLite API routines return one of 30 integer
437 ** [result codes]. However, experience has shown that many of
438 ** these result codes are too coarse-grained. They do not provide as
439 ** much information about problems as programmers might like. In an effort to
440 ** address this, newer versions of SQLite (version 3.3.8 and later) include
441 ** support for additional result codes that provide more detailed information
442 ** about errors. These [extended result codes] are enabled or disabled
443 ** on a per database connection basis using the
444 ** [sqlite3_extended_result_codes()] API. Or, the extended code for
445 ** the most recent error can be obtained using
446 ** [sqlite3_extended_errcode()].
 
 
 
 
 
 
447 */
448 #define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
449 #define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
450 #define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8))
451 #define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8))
@@ -683,11 +674,11 @@
674 ** write return values. Potential uses for xFileControl() might be
675 ** functions to enable blocking locks with timeouts, to change the
676 ** locking strategy (for example to use dot-file locks), to inquire
677 ** about the status of a lock, or to break stale locks. The SQLite
678 ** core reserves all opcodes less than 100 for its own use.
679 ** A [file control opcodes | list of opcodes] less than 100 is available.
680 ** Applications that define a custom xFileControl method should use opcodes
681 ** greater than 100 to avoid conflicts. VFS implementations should
682 ** return [SQLITE_NOTFOUND] for file control opcodes that they do not
683 ** recognize.
684 **
@@ -756,10 +747,11 @@
747 /* Additional methods may be added in future releases */
748 };
749
750 /*
751 ** CAPI3REF: Standard File Control Opcodes
752 ** KEYWORDS: {file control opcodes} {file control opcode}
753 **
754 ** These integer constants are opcodes for the xFileControl method
755 ** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
756 ** interface.
757 **
@@ -2035,31 +2027,37 @@
2027 SQLITE_API int sqlite3_complete16(const void *sql);
2028
2029 /*
2030 ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
2031 **
2032 ** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
2033 ** that might be invoked with argument P whenever
2034 ** an attempt is made to access a database table associated with
2035 ** [database connection] D when another thread
2036 ** or process has the table locked.
2037 ** The sqlite3_busy_handler() interface is used to implement
2038 ** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout].
2039 **
2040 ** ^If the busy callback is NULL, then [SQLITE_BUSY]
2041 ** is returned immediately upon encountering the lock. ^If the busy callback
2042 ** is not NULL, then the callback might be invoked with two arguments.
2043 **
2044 ** ^The first argument to the busy handler is a copy of the void* pointer which
2045 ** is the third argument to sqlite3_busy_handler(). ^The second argument to
2046 ** the busy handler callback is the number of times that the busy handler has
2047 ** been invoked for the same locking event. ^If the
2048 ** busy callback returns 0, then no additional attempts are made to
2049 ** access the database and [SQLITE_BUSY] is returned
2050 ** to the application.
2051 ** ^If the callback returns non-zero, then another attempt
2052 ** is made to access the database and the cycle repeats.
2053 **
2054 ** The presence of a busy handler does not guarantee that it will be invoked
2055 ** when there is lock contention. ^If SQLite determines that invoking the busy
2056 ** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY]
2057 ** to the application instead of invoking the
2058 ** busy handler.
2059 ** Consider a scenario where one process is holding a read lock that
2060 ** it is trying to promote to a reserved lock and
2061 ** a second process is holding a reserved lock that it is trying
2062 ** to promote to an exclusive lock. The first process cannot proceed
2063 ** because it is blocked by the second and the second process cannot
@@ -2069,32 +2067,19 @@
2067 ** will induce the first process to release its read lock and allow
2068 ** the second process to proceed.
2069 **
2070 ** ^The default busy callback is NULL.
2071 **
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2072 ** ^(There can only be a single busy handler defined for each
2073 ** [database connection]. Setting a new busy handler clears any
2074 ** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()]
2075 ** or evaluating [PRAGMA busy_timeout=N] will change the
2076 ** busy handler and thus clear any previously set busy handler.
2077 **
2078 ** The busy callback should not take any actions which modify the
2079 ** database connection that invoked the busy handler. In other words,
2080 ** the busy handler is not reentrant. Any such actions
2081 ** result in undefined behavior.
2082 **
2083 ** A busy handler must not close the database connection
2084 ** or [prepared statement] that invoked the busy handler.
2085 */
@@ -2106,19 +2091,21 @@
2091 ** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps
2092 ** for a specified amount of time when a table is locked. ^The handler
2093 ** will sleep multiple times until at least "ms" milliseconds of sleeping
2094 ** have accumulated. ^After at least "ms" milliseconds of sleeping,
2095 ** the handler returns 0 which causes [sqlite3_step()] to return
2096 ** [SQLITE_BUSY].
2097 **
2098 ** ^Calling this routine with an argument less than or equal to zero
2099 ** turns off all busy handlers.
2100 **
2101 ** ^(There can only be a single busy handler for a particular
2102 ** [database connection] any any given moment. If another busy handler
2103 ** was defined (using [sqlite3_busy_handler()]) prior to calling
2104 ** this routine, that other busy handler is cleared.)^
2105 **
2106 ** See also: [PRAGMA busy_timeout]
2107 */
2108 SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
2109
2110 /*
2111 ** CAPI3REF: Convenience Routines For Running Queries
@@ -2516,12 +2503,12 @@
2503 ** return either [SQLITE_OK] or one of these two constants in order
2504 ** to signal SQLite whether or not the action is permitted. See the
2505 ** [sqlite3_set_authorizer | authorizer documentation] for additional
2506 ** information.
2507 **
2508 ** Note that SQLITE_IGNORE is also used as a [conflict resolution mode]
2509 ** returned from the [sqlite3_vtab_on_conflict()] interface.
2510 */
2511 #define SQLITE_DENY 1 /* Abort the SQL statement with an error */
2512 #define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
2513
2514 /*
@@ -4703,10 +4690,17 @@
4690 ** the name of a folder (a.k.a. directory), then all temporary files
4691 ** created by SQLite when using a built-in [sqlite3_vfs | VFS]
4692 ** will be placed in that directory.)^ ^If this variable
4693 ** is a NULL pointer, then SQLite performs a search for an appropriate
4694 ** temporary file directory.
4695 **
4696 ** Applications are strongly discouraged from using this global variable.
4697 ** It is required to set a temporary folder on Windows Runtime (WinRT).
4698 ** But for all other platforms, it is highly recommended that applications
4699 ** neither read nor write this variable. This global variable is a relic
4700 ** that exists for backwards compatibility of legacy applications and should
4701 ** be avoided in new projects.
4702 **
4703 ** It is not safe to read or modify this variable in more than one
4704 ** thread at a time. It is not safe to read or modify this variable
4705 ** if a [database connection] is being used at the same time in a separate
4706 ** thread.
@@ -4722,10 +4716,15 @@
4716 ** [sqlite3_malloc] and the pragma may attempt to free that memory
4717 ** using [sqlite3_free].
4718 ** Hence, if this variable is modified directly, either it should be
4719 ** made NULL or made to point to memory obtained from [sqlite3_malloc]
4720 ** or else the use of the [temp_store_directory pragma] should be avoided.
4721 ** Except when requested by the [temp_store_directory pragma], SQLite
4722 ** does not free the memory that sqlite3_temp_directory points to. If
4723 ** the application wants that memory to be freed, it must do
4724 ** so itself, taking care to only do so after all [database connection]
4725 ** objects have been destroyed.
4726 **
4727 ** <b>Note to Windows Runtime users:</b> The temporary directory must be set
4728 ** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various
4729 ** features that require the use of temporary files may fail. Here is an
4730 ** example of how to do this using C++ with the Windows Runtime:
@@ -5856,14 +5855,16 @@
5855 ** <ul>
5856 ** <li> SQLITE_MUTEX_FAST
5857 ** <li> SQLITE_MUTEX_RECURSIVE
5858 ** <li> SQLITE_MUTEX_STATIC_MASTER
5859 ** <li> SQLITE_MUTEX_STATIC_MEM
5860 ** <li> SQLITE_MUTEX_STATIC_OPEN
5861 ** <li> SQLITE_MUTEX_STATIC_PRNG
5862 ** <li> SQLITE_MUTEX_STATIC_LRU
5863 ** <li> SQLITE_MUTEX_STATIC_PMEM
5864 ** <li> SQLITE_MUTEX_STATIC_APP1
5865 ** <li> SQLITE_MUTEX_STATIC_APP2
5866 ** </ul>)^
5867 **
5868 ** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
5869 ** cause sqlite3_mutex_alloc() to create
5870 ** a new mutex. ^The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
@@ -6063,10 +6064,13 @@
6064 #define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */
6065 #define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */
6066 #define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
6067 #define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */
6068 #define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */
6069 #define SQLITE_MUTEX_STATIC_APP1 8 /* For use by application */
6070 #define SQLITE_MUTEX_STATIC_APP2 9 /* For use by application */
6071 #define SQLITE_MUTEX_STATIC_APP3 10 /* For use by application */
6072
6073 /*
6074 ** CAPI3REF: Retrieve the mutex for a database connection
6075 **
6076 ** ^This interface returns a pointer the [sqlite3_mutex] object that
@@ -6158,11 +6162,12 @@
6162 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
6163 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19
6164 #define SQLITE_TESTCTRL_NEVER_CORRUPT 20
6165 #define SQLITE_TESTCTRL_VDBE_COVERAGE 21
6166 #define SQLITE_TESTCTRL_BYTEORDER 22
6167 #define SQLITE_TESTCTRL_ISINIT 23
6168 #define SQLITE_TESTCTRL_LAST 23
6169
6170 /*
6171 ** CAPI3REF: SQLite Runtime Status
6172 **
6173 ** ^This interface is used to retrieve runtime status information
@@ -7141,10 +7146,13 @@
7146 ** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism
7147 ** configured by this function.
7148 **
7149 ** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
7150 ** from SQL.
7151 **
7152 ** ^Checkpoints initiated by this mechanism are
7153 ** [sqlite3_wal_checkpoint_v2|PASSIVE].
7154 **
7155 ** ^Every new [database connection] defaults to having the auto-checkpoint
7156 ** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
7157 ** pages. The use of this interface
7158 ** is only necessary if the default setting is found to be suboptimal
@@ -7158,10 +7166,14 @@
7166 ** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X
7167 ** on [database connection] D to be [checkpointed]. ^If X is NULL or an
7168 ** empty string, then a checkpoint is run on all databases of
7169 ** connection D. ^If the database connection D is not in
7170 ** [WAL | write-ahead log mode] then this interface is a harmless no-op.
7171 ** ^The [sqlite3_wal_checkpoint(D,X)] interface initiates a
7172 ** [sqlite3_wal_checkpoint_v2|PASSIVE] checkpoint.
7173 ** Use the [sqlite3_wal_checkpoint_v2()] interface to get a FULL
7174 ** or RESET checkpoint.
7175 **
7176 ** ^The [wal_checkpoint pragma] can be used to invoke this interface
7177 ** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the
7178 ** [wal_autocheckpoint pragma] can be used to cause this interface to be
7179 ** run whenever the WAL reaches a certain size threshold.
@@ -7180,22 +7192,25 @@
7192 ** <dl>
7193 ** <dt>SQLITE_CHECKPOINT_PASSIVE<dd>
7194 ** Checkpoint as many frames as possible without waiting for any database
7195 ** readers or writers to finish. Sync the db file if all frames in the log
7196 ** are checkpointed. This mode is the same as calling
7197 ** sqlite3_wal_checkpoint(). The [sqlite3_busy_handler|busy-handler callback]
7198 ** is never invoked.
7199 **
7200 ** <dt>SQLITE_CHECKPOINT_FULL<dd>
7201 ** This mode blocks (it invokes the
7202 ** [sqlite3_busy_handler|busy-handler callback]) until there is no
7203 ** database writer and all readers are reading from the most recent database
7204 ** snapshot. It then checkpoints all frames in the log file and syncs the
7205 ** database file. This call blocks database writers while it is running,
7206 ** but not database readers.
7207 **
7208 ** <dt>SQLITE_CHECKPOINT_RESTART<dd>
7209 ** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after
7210 ** checkpointing the log file it blocks (calls the
7211 ** [sqlite3_busy_handler|busy-handler callback])
7212 ** until all readers are reading from the database file only. This ensures
7213 ** that the next client to write to the database file restarts the log file
7214 ** from the beginning. This call blocks database writers while it is running,
7215 ** but not database readers.
7216 ** </dl>
@@ -7329,10 +7344,11 @@
7344 */
7345 SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
7346
7347 /*
7348 ** CAPI3REF: Conflict resolution modes
7349 ** KEYWORDS: {conflict resolution mode}
7350 **
7351 ** These constants are returned by [sqlite3_vtab_on_conflict()] to
7352 ** inform a [virtual table] implementation what the [ON CONFLICT] mode
7353 ** is for the SQL statement being evaluated.
7354 **
7355
+4
--- src/stat.c
+++ src/stat.c
@@ -172,10 +172,14 @@
172172
const int colWidth = -19 /* printf alignment/width for left column */;
173173
const char *p;
174174
175175
brief = find_option("brief", "b",0)!=0;
176176
db_find_and_open_repository(0,0);
177
+
178
+ /* We should be done with options.. */
179
+ verify_all_options();
180
+
177181
fsize = file_size(g.zRepositoryName);
178182
bigSizeName(sizeof(zBuf), zBuf, fsize);
179183
fossil_print( "%*s%s\n", colWidth, "repository-size:", zBuf );
180184
if( !brief ){
181185
n = db_int(0, "SELECT count(*) FROM blob");
182186
--- src/stat.c
+++ src/stat.c
@@ -172,10 +172,14 @@
172 const int colWidth = -19 /* printf alignment/width for left column */;
173 const char *p;
174
175 brief = find_option("brief", "b",0)!=0;
176 db_find_and_open_repository(0,0);
 
 
 
 
177 fsize = file_size(g.zRepositoryName);
178 bigSizeName(sizeof(zBuf), zBuf, fsize);
179 fossil_print( "%*s%s\n", colWidth, "repository-size:", zBuf );
180 if( !brief ){
181 n = db_int(0, "SELECT count(*) FROM blob");
182
--- src/stat.c
+++ src/stat.c
@@ -172,10 +172,14 @@
172 const int colWidth = -19 /* printf alignment/width for left column */;
173 const char *p;
174
175 brief = find_option("brief", "b",0)!=0;
176 db_find_and_open_repository(0,0);
177
178 /* We should be done with options.. */
179 verify_all_options();
180
181 fsize = file_size(g.zRepositoryName);
182 bigSizeName(sizeof(zBuf), zBuf, fsize);
183 fossil_print( "%*s%s\n", colWidth, "repository-size:", zBuf );
184 if( !brief ){
185 n = db_int(0, "SELECT count(*) FROM blob");
186
+16
--- src/sync.c
+++ src/sync.c
@@ -186,10 +186,14 @@
186186
*/
187187
void pull_cmd(void){
188188
unsigned configFlags = 0;
189189
unsigned syncFlags = SYNC_PULL;
190190
process_sync_args(&configFlags, &syncFlags);
191
+
192
+ /* We should be done with options.. */
193
+ verify_all_options();
194
+
191195
client_sync(syncFlags, configFlags, 0);
192196
}
193197
194198
/*
195199
** COMMAND: push
@@ -217,10 +221,14 @@
217221
*/
218222
void push_cmd(void){
219223
unsigned configFlags = 0;
220224
unsigned syncFlags = SYNC_PUSH;
221225
process_sync_args(&configFlags, &syncFlags);
226
+
227
+ /* We should be done with options.. */
228
+ verify_all_options();
229
+
222230
if( db_get_boolean("dont-push",0) ){
223231
fossil_fatal("pushing is prohibited: the 'dont-push' option is set");
224232
}
225233
client_sync(syncFlags, 0, 0);
226234
}
@@ -253,10 +261,14 @@
253261
*/
254262
void sync_cmd(void){
255263
unsigned configFlags = 0;
256264
unsigned syncFlags = SYNC_PUSH|SYNC_PULL;
257265
process_sync_args(&configFlags, &syncFlags);
266
+
267
+ /* We should be done with options.. */
268
+ verify_all_options();
269
+
258270
if( db_get_boolean("dont-push",0) ) syncFlags &= ~SYNC_PUSH;
259271
client_sync(syncFlags, configFlags, 0);
260272
if( (syncFlags & SYNC_PUSH)==0 ){
261273
fossil_warning("pull only: the 'dont-push' option is set");
262274
}
@@ -280,10 +292,14 @@
280292
** See also: clone, push, pull, sync
281293
*/
282294
void remote_url_cmd(void){
283295
char *zUrl;
284296
db_find_and_open_repository(0, 0);
297
+
298
+ /* We should be done with options.. */
299
+ verify_all_options();
300
+
285301
if( g.argc!=2 && g.argc!=3 ){
286302
usage("remote-url ?URL|off?");
287303
}
288304
if( g.argc==3 ){
289305
db_unset("last-sync-url", 0);
290306
--- src/sync.c
+++ src/sync.c
@@ -186,10 +186,14 @@
186 */
187 void pull_cmd(void){
188 unsigned configFlags = 0;
189 unsigned syncFlags = SYNC_PULL;
190 process_sync_args(&configFlags, &syncFlags);
 
 
 
 
191 client_sync(syncFlags, configFlags, 0);
192 }
193
194 /*
195 ** COMMAND: push
@@ -217,10 +221,14 @@
217 */
218 void push_cmd(void){
219 unsigned configFlags = 0;
220 unsigned syncFlags = SYNC_PUSH;
221 process_sync_args(&configFlags, &syncFlags);
 
 
 
 
222 if( db_get_boolean("dont-push",0) ){
223 fossil_fatal("pushing is prohibited: the 'dont-push' option is set");
224 }
225 client_sync(syncFlags, 0, 0);
226 }
@@ -253,10 +261,14 @@
253 */
254 void sync_cmd(void){
255 unsigned configFlags = 0;
256 unsigned syncFlags = SYNC_PUSH|SYNC_PULL;
257 process_sync_args(&configFlags, &syncFlags);
 
 
 
 
258 if( db_get_boolean("dont-push",0) ) syncFlags &= ~SYNC_PUSH;
259 client_sync(syncFlags, configFlags, 0);
260 if( (syncFlags & SYNC_PUSH)==0 ){
261 fossil_warning("pull only: the 'dont-push' option is set");
262 }
@@ -280,10 +292,14 @@
280 ** See also: clone, push, pull, sync
281 */
282 void remote_url_cmd(void){
283 char *zUrl;
284 db_find_and_open_repository(0, 0);
 
 
 
 
285 if( g.argc!=2 && g.argc!=3 ){
286 usage("remote-url ?URL|off?");
287 }
288 if( g.argc==3 ){
289 db_unset("last-sync-url", 0);
290
--- src/sync.c
+++ src/sync.c
@@ -186,10 +186,14 @@
186 */
187 void pull_cmd(void){
188 unsigned configFlags = 0;
189 unsigned syncFlags = SYNC_PULL;
190 process_sync_args(&configFlags, &syncFlags);
191
192 /* We should be done with options.. */
193 verify_all_options();
194
195 client_sync(syncFlags, configFlags, 0);
196 }
197
198 /*
199 ** COMMAND: push
@@ -217,10 +221,14 @@
221 */
222 void push_cmd(void){
223 unsigned configFlags = 0;
224 unsigned syncFlags = SYNC_PUSH;
225 process_sync_args(&configFlags, &syncFlags);
226
227 /* We should be done with options.. */
228 verify_all_options();
229
230 if( db_get_boolean("dont-push",0) ){
231 fossil_fatal("pushing is prohibited: the 'dont-push' option is set");
232 }
233 client_sync(syncFlags, 0, 0);
234 }
@@ -253,10 +261,14 @@
261 */
262 void sync_cmd(void){
263 unsigned configFlags = 0;
264 unsigned syncFlags = SYNC_PUSH|SYNC_PULL;
265 process_sync_args(&configFlags, &syncFlags);
266
267 /* We should be done with options.. */
268 verify_all_options();
269
270 if( db_get_boolean("dont-push",0) ) syncFlags &= ~SYNC_PUSH;
271 client_sync(syncFlags, configFlags, 0);
272 if( (syncFlags & SYNC_PUSH)==0 ){
273 fossil_warning("pull only: the 'dont-push' option is set");
274 }
@@ -280,10 +292,14 @@
292 ** See also: clone, push, pull, sync
293 */
294 void remote_url_cmd(void){
295 char *zUrl;
296 db_find_and_open_repository(0, 0);
297
298 /* We should be done with options.. */
299 verify_all_options();
300
301 if( g.argc!=2 && g.argc!=3 ){
302 usage("remote-url ?URL|off?");
303 }
304 if( g.argc==3 ){
305 db_unset("last-sync-url", 0);
306
+8 -8
--- src/tag.c
+++ src/tag.c
@@ -50,11 +50,11 @@
5050
5151
/* Query for children of :pid to which to propagate the tag.
5252
** Three returns: (1) rid of the child. (2) timestamp of child.
5353
** (3) True to propagate or false to block.
5454
*/
55
- db_prepare(&s,
55
+ db_prepare(&s,
5656
"SELECT cid, plink.mtime,"
5757
" coalesce(srcid=0 AND tagxref.mtime<:mtime, %d) AS doit"
5858
" FROM plink LEFT JOIN tagxref ON cid=rid AND tagid=%d"
5959
" WHERE pid=:pid AND isprim",
6060
tagType==2, tagid
@@ -179,11 +179,11 @@
179179
db_finalize(&s);
180180
if( rc==SQLITE_ROW ){
181181
/* Another entry that is more recent already exists. Do nothing */
182182
return tagid;
183183
}
184
- db_prepare(&s,
184
+ db_prepare(&s,
185185
"REPLACE INTO tagxref(tagid,tagtype,srcId,origid,value,mtime,rid)"
186186
" VALUES(%d,%d,%d,%d,%Q,:mtime,%d)",
187187
tagid, tagtype, srcId, rid, zValue, rid
188188
);
189189
db_bind_double(&s, ":mtime", mtime);
@@ -256,11 +256,11 @@
256256
zTag = g.argv[2];
257257
switch( zTag[0] ){
258258
case '+': tagtype = 1; break;
259259
case '*': tagtype = 2; break;
260260
case '-': tagtype = 0; break;
261
- default:
261
+ default:
262262
fossil_fatal("tag should begin with '+', '*', or '-'");
263263
return;
264264
}
265265
rid = name_to_rid(g.argv[3]);
266266
if( rid==0 ){
@@ -378,22 +378,22 @@
378378
**
379379
** fossil update tag:decaf
380380
**
381381
** will assume that "decaf" is a tag/branch name.
382382
**
383
-** only allow --date-override and --user-override in
383
+** only allow --date-override and --user-override in
384384
** %fossil tag add --date-override 'YYYY-MMM-DD HH:MM:SS' \\
385
-** --user-override user
385
+** --user-override user
386386
** in order to import history from other scm systems
387387
*/
388388
void tag_cmd(void){
389389
int n;
390390
int fRaw = find_option("raw","",0)!=0;
391391
int fPropagate = find_option("propagate","",0)!=0;
392392
const char *zPrefix = fRaw ? "" : "sym-";
393
- char const * zFindLimit = find_option("limit","n",1);
394
- int const nFindLimit = zFindLimit ? atoi(zFindLimit) : -2000;
393
+ const char *zFindLimit = find_option("limit","n",1);
394
+ const int nFindLimit = zFindLimit ? atoi(zFindLimit) : -2000;
395395
396396
db_find_and_open_repository(0, 0);
397397
if( g.argc<3 ){
398398
goto tag_cmd_usage;
399399
}
@@ -478,11 +478,11 @@
478478
}else
479479
480480
if( strncmp(g.argv[2],"list",n)==0 ){
481481
Stmt q;
482482
if( g.argc==3 ){
483
- db_prepare(&q,
483
+ db_prepare(&q,
484484
"SELECT tagname FROM tag"
485485
" WHERE EXISTS(SELECT 1 FROM tagxref"
486486
" WHERE tagid=tag.tagid"
487487
" AND tagtype>0)"
488488
" ORDER BY tagname"
489489
--- src/tag.c
+++ src/tag.c
@@ -50,11 +50,11 @@
50
51 /* Query for children of :pid to which to propagate the tag.
52 ** Three returns: (1) rid of the child. (2) timestamp of child.
53 ** (3) True to propagate or false to block.
54 */
55 db_prepare(&s,
56 "SELECT cid, plink.mtime,"
57 " coalesce(srcid=0 AND tagxref.mtime<:mtime, %d) AS doit"
58 " FROM plink LEFT JOIN tagxref ON cid=rid AND tagid=%d"
59 " WHERE pid=:pid AND isprim",
60 tagType==2, tagid
@@ -179,11 +179,11 @@
179 db_finalize(&s);
180 if( rc==SQLITE_ROW ){
181 /* Another entry that is more recent already exists. Do nothing */
182 return tagid;
183 }
184 db_prepare(&s,
185 "REPLACE INTO tagxref(tagid,tagtype,srcId,origid,value,mtime,rid)"
186 " VALUES(%d,%d,%d,%d,%Q,:mtime,%d)",
187 tagid, tagtype, srcId, rid, zValue, rid
188 );
189 db_bind_double(&s, ":mtime", mtime);
@@ -256,11 +256,11 @@
256 zTag = g.argv[2];
257 switch( zTag[0] ){
258 case '+': tagtype = 1; break;
259 case '*': tagtype = 2; break;
260 case '-': tagtype = 0; break;
261 default:
262 fossil_fatal("tag should begin with '+', '*', or '-'");
263 return;
264 }
265 rid = name_to_rid(g.argv[3]);
266 if( rid==0 ){
@@ -378,22 +378,22 @@
378 **
379 ** fossil update tag:decaf
380 **
381 ** will assume that "decaf" is a tag/branch name.
382 **
383 ** only allow --date-override and --user-override in
384 ** %fossil tag add --date-override 'YYYY-MMM-DD HH:MM:SS' \\
385 ** --user-override user
386 ** in order to import history from other scm systems
387 */
388 void tag_cmd(void){
389 int n;
390 int fRaw = find_option("raw","",0)!=0;
391 int fPropagate = find_option("propagate","",0)!=0;
392 const char *zPrefix = fRaw ? "" : "sym-";
393 char const * zFindLimit = find_option("limit","n",1);
394 int const nFindLimit = zFindLimit ? atoi(zFindLimit) : -2000;
395
396 db_find_and_open_repository(0, 0);
397 if( g.argc<3 ){
398 goto tag_cmd_usage;
399 }
@@ -478,11 +478,11 @@
478 }else
479
480 if( strncmp(g.argv[2],"list",n)==0 ){
481 Stmt q;
482 if( g.argc==3 ){
483 db_prepare(&q,
484 "SELECT tagname FROM tag"
485 " WHERE EXISTS(SELECT 1 FROM tagxref"
486 " WHERE tagid=tag.tagid"
487 " AND tagtype>0)"
488 " ORDER BY tagname"
489
--- src/tag.c
+++ src/tag.c
@@ -50,11 +50,11 @@
50
51 /* Query for children of :pid to which to propagate the tag.
52 ** Three returns: (1) rid of the child. (2) timestamp of child.
53 ** (3) True to propagate or false to block.
54 */
55 db_prepare(&s,
56 "SELECT cid, plink.mtime,"
57 " coalesce(srcid=0 AND tagxref.mtime<:mtime, %d) AS doit"
58 " FROM plink LEFT JOIN tagxref ON cid=rid AND tagid=%d"
59 " WHERE pid=:pid AND isprim",
60 tagType==2, tagid
@@ -179,11 +179,11 @@
179 db_finalize(&s);
180 if( rc==SQLITE_ROW ){
181 /* Another entry that is more recent already exists. Do nothing */
182 return tagid;
183 }
184 db_prepare(&s,
185 "REPLACE INTO tagxref(tagid,tagtype,srcId,origid,value,mtime,rid)"
186 " VALUES(%d,%d,%d,%d,%Q,:mtime,%d)",
187 tagid, tagtype, srcId, rid, zValue, rid
188 );
189 db_bind_double(&s, ":mtime", mtime);
@@ -256,11 +256,11 @@
256 zTag = g.argv[2];
257 switch( zTag[0] ){
258 case '+': tagtype = 1; break;
259 case '*': tagtype = 2; break;
260 case '-': tagtype = 0; break;
261 default:
262 fossil_fatal("tag should begin with '+', '*', or '-'");
263 return;
264 }
265 rid = name_to_rid(g.argv[3]);
266 if( rid==0 ){
@@ -378,22 +378,22 @@
378 **
379 ** fossil update tag:decaf
380 **
381 ** will assume that "decaf" is a tag/branch name.
382 **
383 ** only allow --date-override and --user-override in
384 ** %fossil tag add --date-override 'YYYY-MMM-DD HH:MM:SS' \\
385 ** --user-override user
386 ** in order to import history from other scm systems
387 */
388 void tag_cmd(void){
389 int n;
390 int fRaw = find_option("raw","",0)!=0;
391 int fPropagate = find_option("propagate","",0)!=0;
392 const char *zPrefix = fRaw ? "" : "sym-";
393 const char *zFindLimit = find_option("limit","n",1);
394 const int nFindLimit = zFindLimit ? atoi(zFindLimit) : -2000;
395
396 db_find_and_open_repository(0, 0);
397 if( g.argc<3 ){
398 goto tag_cmd_usage;
399 }
@@ -478,11 +478,11 @@
478 }else
479
480 if( strncmp(g.argv[2],"list",n)==0 ){
481 Stmt q;
482 if( g.argc==3 ){
483 db_prepare(&q,
484 "SELECT tagname FROM tag"
485 " WHERE EXISTS(SELECT 1 FROM tagxref"
486 " WHERE tagid=tag.tagid"
487 " AND tagtype>0)"
488 " ORDER BY tagname"
489
+24 -5
--- src/tar.c
+++ src/tar.c
@@ -526,24 +526,32 @@
526526
}
527527
528528
/*
529529
** COMMAND: tarball*
530530
**
531
-** Usage: %fossil tarball VERSION OUTPUTFILE [--name DIRECTORYNAME] [-R|--repository REPO]
531
+** Usage: %fossil tarball VERSION OUTPUTFILE
532532
**
533533
** Generate a compressed tarball for a specified version. If the --name
534534
** option is used, its argument becomes the name of the top-level directory
535535
** in the resulting tarball. If --name is omitted, the top-level directory
536536
** named is derived from the project name, the check-in date and time, and
537537
** the artifact ID of the check-in.
538
+**
539
+** Options:
540
+** --name DIRECTORYNAME The name of the top-level directory in the archive
541
+** -R REPOSITORY Specify a Fossil repository
538542
*/
539543
void tarball_cmd(void){
540544
int rid;
541545
Blob tarball;
542546
const char *zName;
543547
zName = find_option("name", 0, 1);
544548
db_find_and_open_repository(0, 0);
549
+
550
+ /* We should be done with options.. */
551
+ verify_all_options();
552
+
545553
if( g.argc!=4 ){
546554
usage("VERSION OUTPUTFILE");
547555
}
548556
rid = name_to_typed_rid(g.argv[2], "ci");
549557
if( rid==0 ){
@@ -574,15 +582,17 @@
574582
** Generate a compressed tarball for a checkin.
575583
** Return that tarball as the HTTP reply content.
576584
**
577585
** Optional URL Parameters:
578586
**
579
-** - name=base name of the output file. Defaults to
580
-** something project/version-specific.
587
+** - name=NAME[.tar.gz] is base name of the output file. Defaults to
588
+** something project/version-specific. The prefix of the name, up to
589
+** the last '.', are used as the top-most directory name in the tar
590
+** output.
581591
**
582592
** - uuid=the version to tar (may be a tag/branch name).
583
-** Defaults to trunk.
593
+** Defaults to "trunk".
584594
**
585595
*/
586596
void tarball_page(void){
587597
int rid;
588598
char *zName, *zRid, *zKey;
@@ -614,11 +624,20 @@
614624
if( rid==0 ){
615625
@ Not found
616626
return;
617627
}
618628
if( nRid==0 && nName>10 ) zName[10] = 0;
619
- zKey = db_text(0, "SELECT '/tarball/'||uuid||'/%q' FROM blob WHERE rid=%d",zName,rid);
629
+ zKey = db_text(0, "SELECT '/tarball/'||uuid||'/%q'"
630
+ " FROM blob WHERE rid=%d",zName,rid);
631
+ if( P("debug")!=0 ){
632
+ style_header("Tarball Generator Debug Screen");
633
+ @ zName = "%h(zName)"<br>
634
+ @ rid = %d(rid)<br>
635
+ @ zKey = "%h(zKey)"
636
+ style_footer();
637
+ return;
638
+ }
620639
blob_zero(&tarball);
621640
if( cache_read(&tarball, zKey)==0 ){
622641
tarball_of_checkin(rid, &tarball, zName);
623642
cache_write(&tarball, zKey);
624643
}
625644
--- src/tar.c
+++ src/tar.c
@@ -526,24 +526,32 @@
526 }
527
528 /*
529 ** COMMAND: tarball*
530 **
531 ** Usage: %fossil tarball VERSION OUTPUTFILE [--name DIRECTORYNAME] [-R|--repository REPO]
532 **
533 ** Generate a compressed tarball for a specified version. If the --name
534 ** option is used, its argument becomes the name of the top-level directory
535 ** in the resulting tarball. If --name is omitted, the top-level directory
536 ** named is derived from the project name, the check-in date and time, and
537 ** the artifact ID of the check-in.
 
 
 
 
538 */
539 void tarball_cmd(void){
540 int rid;
541 Blob tarball;
542 const char *zName;
543 zName = find_option("name", 0, 1);
544 db_find_and_open_repository(0, 0);
 
 
 
 
545 if( g.argc!=4 ){
546 usage("VERSION OUTPUTFILE");
547 }
548 rid = name_to_typed_rid(g.argv[2], "ci");
549 if( rid==0 ){
@@ -574,15 +582,17 @@
574 ** Generate a compressed tarball for a checkin.
575 ** Return that tarball as the HTTP reply content.
576 **
577 ** Optional URL Parameters:
578 **
579 ** - name=base name of the output file. Defaults to
580 ** something project/version-specific.
 
 
581 **
582 ** - uuid=the version to tar (may be a tag/branch name).
583 ** Defaults to trunk.
584 **
585 */
586 void tarball_page(void){
587 int rid;
588 char *zName, *zRid, *zKey;
@@ -614,11 +624,20 @@
614 if( rid==0 ){
615 @ Not found
616 return;
617 }
618 if( nRid==0 && nName>10 ) zName[10] = 0;
619 zKey = db_text(0, "SELECT '/tarball/'||uuid||'/%q' FROM blob WHERE rid=%d",zName,rid);
 
 
 
 
 
 
 
 
 
620 blob_zero(&tarball);
621 if( cache_read(&tarball, zKey)==0 ){
622 tarball_of_checkin(rid, &tarball, zName);
623 cache_write(&tarball, zKey);
624 }
625
--- src/tar.c
+++ src/tar.c
@@ -526,24 +526,32 @@
526 }
527
528 /*
529 ** COMMAND: tarball*
530 **
531 ** Usage: %fossil tarball VERSION OUTPUTFILE
532 **
533 ** Generate a compressed tarball for a specified version. If the --name
534 ** option is used, its argument becomes the name of the top-level directory
535 ** in the resulting tarball. If --name is omitted, the top-level directory
536 ** named is derived from the project name, the check-in date and time, and
537 ** the artifact ID of the check-in.
538 **
539 ** Options:
540 ** --name DIRECTORYNAME The name of the top-level directory in the archive
541 ** -R REPOSITORY Specify a Fossil repository
542 */
543 void tarball_cmd(void){
544 int rid;
545 Blob tarball;
546 const char *zName;
547 zName = find_option("name", 0, 1);
548 db_find_and_open_repository(0, 0);
549
550 /* We should be done with options.. */
551 verify_all_options();
552
553 if( g.argc!=4 ){
554 usage("VERSION OUTPUTFILE");
555 }
556 rid = name_to_typed_rid(g.argv[2], "ci");
557 if( rid==0 ){
@@ -574,15 +582,17 @@
582 ** Generate a compressed tarball for a checkin.
583 ** Return that tarball as the HTTP reply content.
584 **
585 ** Optional URL Parameters:
586 **
587 ** - name=NAME[.tar.gz] is base name of the output file. Defaults to
588 ** something project/version-specific. The prefix of the name, up to
589 ** the last '.', are used as the top-most directory name in the tar
590 ** output.
591 **
592 ** - uuid=the version to tar (may be a tag/branch name).
593 ** Defaults to "trunk".
594 **
595 */
596 void tarball_page(void){
597 int rid;
598 char *zName, *zRid, *zKey;
@@ -614,11 +624,20 @@
624 if( rid==0 ){
625 @ Not found
626 return;
627 }
628 if( nRid==0 && nName>10 ) zName[10] = 0;
629 zKey = db_text(0, "SELECT '/tarball/'||uuid||'/%q'"
630 " FROM blob WHERE rid=%d",zName,rid);
631 if( P("debug")!=0 ){
632 style_header("Tarball Generator Debug Screen");
633 @ zName = "%h(zName)"<br>
634 @ rid = %d(rid)<br>
635 @ zKey = "%h(zKey)"
636 style_footer();
637 return;
638 }
639 blob_zero(&tarball);
640 if( cache_read(&tarball, zKey)==0 ){
641 tarball_of_checkin(rid, &tarball, zName);
642 cache_write(&tarball, zKey);
643 }
644
+2
--- src/th.c
+++ src/th.c
@@ -511,16 +511,18 @@
511511
}
512512
iEnd++;
513513
}
514514
if( nBrace>0 || nSq>0 ){
515515
/* Parse error */
516
+ Th_SetResult(interp, "parse error", -1);
516517
return TH_ERROR;
517518
}
518519
}
519520
520521
if( iEnd>nInput ){
521522
/* Parse error */
523
+ Th_SetResult(interp, "parse error", -1);
522524
return TH_ERROR;
523525
}
524526
*pnWord = iEnd;
525527
return TH_OK;
526528
}
527529
--- src/th.c
+++ src/th.c
@@ -511,16 +511,18 @@
511 }
512 iEnd++;
513 }
514 if( nBrace>0 || nSq>0 ){
515 /* Parse error */
 
516 return TH_ERROR;
517 }
518 }
519
520 if( iEnd>nInput ){
521 /* Parse error */
 
522 return TH_ERROR;
523 }
524 *pnWord = iEnd;
525 return TH_OK;
526 }
527
--- src/th.c
+++ src/th.c
@@ -511,16 +511,18 @@
511 }
512 iEnd++;
513 }
514 if( nBrace>0 || nSq>0 ){
515 /* Parse error */
516 Th_SetResult(interp, "parse error", -1);
517 return TH_ERROR;
518 }
519 }
520
521 if( iEnd>nInput ){
522 /* Parse error */
523 Th_SetResult(interp, "parse error", -1);
524 return TH_ERROR;
525 }
526 *pnWord = iEnd;
527 return TH_OK;
528 }
529
+30 -25
--- src/timeline.c
+++ src/timeline.c
@@ -996,19 +996,20 @@
996996
** d=UUID artifact and up to COUNT descendants
997997
** dp=UUID The same as d=UUID&p=UUID
998998
** t=TAGID show only check-ins with the given tagid
999999
** r=TAGID show check-ins related to tagid
10001000
** u=USER only if belonging to this user
1001
-** y=TYPE 'ci', 'w', 't', 'e'
1001
+** y=TYPE 'ci', 'w', 't', 'e', or (default) 'all'
10021002
** s=TEXT string search (comment and brief)
10031003
** ng Suppress the graph if present
10041004
** nd Suppress "divider" lines
10051005
** v Show details of files changed
10061006
** f=UUID Show family (immediate parents and children) of UUID
10071007
** from=UUID Path from...
10081008
** to=UUID ... to this
10091009
** nomerge ... avoid merge links on the path
1010
+** shortest ... show only the shortest path
10101011
** uf=FUUID Show only checkins that use given file version
10111012
** brbg Background color from branch name
10121013
** ubg Background color from user
10131014
** namechng Show only checkins that filename changes
10141015
** ym=YYYY-MM Shown only events for the given year/month.
@@ -1360,11 +1361,11 @@
13601361
blob_appendf(&sql, " AND (event.user=%Q OR event.euser=%Q)",
13611362
zUser, zUser);
13621363
url_add_parameter(&url, "u", zUser);
13631364
zThisUser = zUser;
13641365
}
1365
- if ( zSearch ){
1366
+ if( zSearch ){
13661367
blob_appendf(&sql,
13671368
" AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')",
13681369
zSearch, zSearch);
13691370
url_add_parameter(&url, "s", zSearch);
13701371
}
@@ -1760,11 +1761,11 @@
17601761
}
17611762
db_find_and_open_repository(0, 0);
17621763
zLimit = find_option("limit","n",1);
17631764
zWidth = find_option("width","W",1);
17641765
zType = find_option("type","t",1);
1765
- if ( !zLimit ){
1766
+ if( !zLimit ){
17661767
zLimit = find_option("count",0,1);
17671768
}
17681769
if( zLimit ){
17691770
n = atoi(zLimit);
17701771
}else{
@@ -1778,10 +1779,14 @@
17781779
}else{
17791780
width = -1;
17801781
}
17811782
zOffset = find_option("offset",0,1);
17821783
iOffset = zOffset ? atoi(zOffset) : 0;
1784
+
1785
+ /* We should be done with options.. */
1786
+ verify_all_options();
1787
+
17831788
if( g.argc>=4 ){
17841789
k = strlen(g.argv[2]);
17851790
if( strncmp(g.argv[2],"before",k)==0 ){
17861791
mode = 1;
17871792
}else if( strncmp(g.argv[2],"after",k)==0 && k>1 ){
@@ -1964,11 +1969,11 @@
19641969
19651970
/*
19661971
** Set by stats_report_init_view() to one of the y=XXXX values
19671972
** accepted by /timeline?y=XXXX.
19681973
*/
1969
-static const char * statsReportTimelineYFlag = NULL;
1974
+static const char *statsReportTimelineYFlag = NULL;
19701975
19711976
/*
19721977
** Creates a TEMP VIEW named v_reports which is a wrapper around the
19731978
** EVENT table filtered on event.type. It looks for the request
19741979
** parameter 'type' (reminder: we "should" use 'y' for consistency
@@ -1985,12 +1990,12 @@
19851990
** Returns one of: 'c', 'w', 'g', 't', 'e', representing the type of
19861991
** filter it applies, or '*' if no filter is applied (i.e. if "all" is
19871992
** used).
19881993
*/
19891994
static int stats_report_init_view(){
1990
- const char * zType = PD("type","*"); /* analog to /timeline?y=... */
1991
- const char * zRealType = NULL; /* normalized form of zType */
1995
+ const char *zType = PD("type","*"); /* analog to /timeline?y=... */
1996
+ const char *zRealType = NULL; /* normalized form of zType */
19921997
int rc = 0; /* result code */
19931998
assert( !statsReportType && "Must not be called more than once." );
19941999
switch( (zType && *zType) ? *zType : 0 ){
19952000
case 'c':
19962001
case 'C':
@@ -2039,11 +2044,11 @@
20392044
** Returns a string suitable (for a given value of suitable) for
20402045
** use in a label with the header of the /reports pages, dependent
20412046
** on the 'type' flag. See stats_report_init_view().
20422047
** The returned bytes are static.
20432048
*/
2044
-static const char * stats_report_label_for_type(){
2049
+static const char *stats_report_label_for_type(){
20452050
assert( statsReportType && "Must call stats_report_init_view() first." );
20462051
switch( statsReportType ){
20472052
case 'c':
20482053
return "checkins";
20492054
case 'e':
@@ -2066,13 +2071,13 @@
20662071
** time this is called. e.g. if called from the 'byuser' view then
20672072
** zCurrentViewName must be "byuser". Any URL parameters which need to
20682073
** be added to the generated URLs should be passed in zParam. The
20692074
** caller is expected to have already encoded any zParam in the %T or
20702075
** %t encoding. */
2071
-static void stats_report_event_types_menu(const char * zCurrentViewName,
2072
- const char * zParam){
2073
- char * zTop;
2076
+static void stats_report_event_types_menu(const char *zCurrentViewName,
2077
+ const char *zParam){
2078
+ char *zTop;
20742079
if(zParam && !*zParam){
20752080
zParam = NULL;
20762081
}
20772082
zTop = mprintf("%s/reports?view=%s%s%s", g.zTop, zCurrentViewName,
20782083
zParam ? "&" : "", zParam);
@@ -2116,11 +2121,11 @@
21162121
/*
21172122
** Helper for stats_report_by_month_year(), which generates a list of
21182123
** week numbers. zTimeframe should be either a timeframe in the form YYYY
21192124
** or YYYY-MM.
21202125
*/
2121
-static void stats_report_output_week_links(const char * zTimeframe){
2126
+static void stats_report_output_week_links(const char *zTimeframe){
21222127
Stmt stWeek = empty_Stmt;
21232128
char yearPart[5] = {0,0,0,0,0};
21242129
memcpy(yearPart, zTimeframe, 4);
21252130
db_prepare(&stWeek,
21262131
"SELECT DISTINCT strftime('%%W',mtime) AS wk, "
@@ -2130,11 +2135,11 @@
21302135
"WHERE ym=%Q AND mtime < current_timestamp "
21312136
"GROUP BY wk ORDER BY wk",
21322137
strlen(zTimeframe),
21332138
zTimeframe);
21342139
while( SQLITE_ROW == db_step(&stWeek) ){
2135
- const char * zWeek = db_column_text(&stWeek,0);
2140
+ const char *zWeek = db_column_text(&stWeek,0);
21362141
const int nCount = db_column_int(&stWeek,1);
21372142
cgi_printf("<a href='%s/timeline?"
21382143
"yw=%t-%t&n=%d&y=%s'>%s</a>",
21392144
g.zTop, yearPart, zWeek,
21402145
nCount, statsReportTimelineYFlag, zWeek);
@@ -2149,18 +2154,18 @@
21492154
** then the report is restricted to events created by the named user
21502155
** account.
21512156
*/
21522157
static void stats_report_by_month_year(char includeMonth,
21532158
char includeWeeks,
2154
- const char * zUserName){
2159
+ const char *zUserName){
21552160
Stmt query = empty_Stmt;
21562161
int nRowNumber = 0; /* current TR number */
21572162
int nEventTotal = 0; /* Total event count */
21582163
int rowClass = 0; /* counter for alternating
21592164
row colors */
21602165
Blob sql = empty_blob; /* SQL */
2161
- const char * zTimeLabel = includeMonth ? "Year/Month" : "Year";
2166
+ const char *zTimeLabel = includeMonth ? "Year/Month" : "Year";
21622167
char zPrevYear[5] = {0}; /* For keeping track of when
21632168
we change years while looping */
21642169
int nEventsPerYear = 0; /* Total event count for the
21652170
current year */
21662171
char showYearTotal = 0; /* Flag telling us when to show
@@ -2211,11 +2216,11 @@
22112216
}
22122217
++iterations;
22132218
}
22142219
db_reset(&query);
22152220
while( SQLITE_ROW == db_step(&query) ){
2216
- const char * zTimeframe = db_column_text(&query, 0);
2221
+ const char *zTimeframe = db_column_text(&query, 0);
22172222
const int nCount = db_column_int(&query, 1);
22182223
int nSize = nCount
22192224
? (int)(100 * nCount / nMaxEvents)
22202225
: 1;
22212226
showYearTotal = 0;
@@ -2296,11 +2301,11 @@
22962301
@ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td>
22972302
@</tr>
22982303
}
22992304
@ </tbody></table>
23002305
if(nEventTotal){
2301
- const char * zAvgLabel = includeMonth ? "month" : "year";
2306
+ const char *zAvgLabel = includeMonth ? "month" : "year";
23022307
int nAvg = iterations ? (nEventTotal/iterations) : 0;
23032308
@ <br><div>Total events: %d(nEventTotal)
23042309
@ <br>Average per active %s(zAvgLabel): %d(nAvg)
23052310
@ </div>
23062311
}
@@ -2346,11 +2351,11 @@
23462351
nMaxEvents = nCount;
23472352
}
23482353
}
23492354
db_reset(&query);
23502355
while( SQLITE_ROW == db_step(&query) ){
2351
- const char * zUser = db_column_text(&query, 0);
2356
+ const char *zUser = db_column_text(&query, 0);
23522357
const int nCount = db_column_int(&query, 1);
23532358
int nSize = nCount
23542359
? (int)(100 * nCount / nMaxEvents)
23552360
: 0;
23562361
if(!nCount) continue /* arguable! Possible? */;
@@ -2386,11 +2391,11 @@
23862391
int rowClass = 0; /* counter for alternating
23872392
row colors */
23882393
Blob sql = empty_blob; /* SQL */
23892394
int nMaxEvents = 1; /* max number of events for
23902395
all rows. */
2391
- static const char * const daysOfWeek[] = {
2396
+ static const char *const daysOfWeek[] = {
23922397
"Monday", "Tuesday", "Wednesday", "Thursday",
23932398
"Friday", "Saturday", "Sunday"
23942399
};
23952400
23962401
stats_report_init_view();
@@ -2419,11 +2424,11 @@
24192424
nMaxEvents = nCount;
24202425
}
24212426
}
24222427
db_reset(&query);
24232428
while( SQLITE_ROW == db_step(&query) ){
2424
- int const dayNum =db_column_int(&query, 0);
2429
+ const int dayNum =db_column_int(&query, 0);
24252430
const int nCount = db_column_int(&query, 1);
24262431
int nSize = nCount
24272432
? (int)(100 * nCount / nMaxEvents)
24282433
: 0;
24292434
if(!nCount) continue /* arguable! Possible? */;
@@ -2449,16 +2454,16 @@
24492454
/*
24502455
** Helper for stats_report_by_month_year(), which generates a list of
24512456
** week numbers. zTimeframe should be either a timeframe in the form YYYY
24522457
** or YYYY-MM.
24532458
*/
2454
-static void stats_report_year_weeks(const char * zUserName){
2455
- const char * zYear = P("y");
2459
+static void stats_report_year_weeks(const char *zUserName){
2460
+ const char *zYear = P("y");
24562461
int nYear = zYear ? strlen(zYear) : 0;
24572462
int i = 0;
24582463
Stmt qYears = empty_Stmt;
2459
- char * zDefaultYear = NULL;
2464
+ char *zDefaultYear = NULL;
24602465
Blob sql = empty_blob;
24612466
int nMaxEvents = 1; /* max number of events for
24622467
all rows. */
24632468
int iterations = 0; /* # of active time periods. */
24642469
stats_report_init_view();
@@ -2479,11 +2484,11 @@
24792484
blob_append(&sql,"GROUP BY y ORDER BY y", -1);
24802485
db_prepare(&qYears, blob_str(&sql));
24812486
blob_reset(&sql);
24822487
cgi_printf("Select year: ");
24832488
while( SQLITE_ROW == db_step(&qYears) ){
2484
- const char * zT = db_column_text(&qYears, 0);
2489
+ const char *zT = db_column_text(&qYears, 0);
24852490
if( i++ ){
24862491
cgi_printf(" ");
24872492
}
24882493
cgi_printf("<a href='?view=byweek&y=%s&type=%c", zT,
24892494
(char)statsReportType);
@@ -2539,11 +2544,11 @@
25392544
}
25402545
++iterations;
25412546
}
25422547
db_reset(&stWeek);
25432548
while( SQLITE_ROW == db_step(&stWeek) ){
2544
- const char * zWeek = db_column_text(&stWeek,0);
2549
+ const char *zWeek = db_column_text(&stWeek,0);
25452550
const int nCount = db_column_int(&stWeek,1);
25462551
int nSize = nCount
25472552
? (int)(100 * nCount / nMaxEvents)
25482553
: 0;
25492554
if(!nSize) nSize = 1;
@@ -2599,11 +2604,11 @@
25992604
** y=YYYY The year to report (default is the server's
26002605
** current year).
26012606
*/
26022607
void stats_report_page(){
26032608
HQuery url; /* URL for various branch links */
2604
- const char * zView = P("view"); /* Which view/report to show. */
2609
+ const char *zView = P("view"); /* Which view/report to show. */
26052610
const char *zUserName = P("user");
26062611
26072612
login_check_credentials();
26082613
if( !g.perm.Read ){ login_needed(); return; }
26092614
if(!zUserName) zUserName = P("u");
26102615
--- src/timeline.c
+++ src/timeline.c
@@ -996,19 +996,20 @@
996 ** d=UUID artifact and up to COUNT descendants
997 ** dp=UUID The same as d=UUID&p=UUID
998 ** t=TAGID show only check-ins with the given tagid
999 ** r=TAGID show check-ins related to tagid
1000 ** u=USER only if belonging to this user
1001 ** y=TYPE 'ci', 'w', 't', 'e'
1002 ** s=TEXT string search (comment and brief)
1003 ** ng Suppress the graph if present
1004 ** nd Suppress "divider" lines
1005 ** v Show details of files changed
1006 ** f=UUID Show family (immediate parents and children) of UUID
1007 ** from=UUID Path from...
1008 ** to=UUID ... to this
1009 ** nomerge ... avoid merge links on the path
 
1010 ** uf=FUUID Show only checkins that use given file version
1011 ** brbg Background color from branch name
1012 ** ubg Background color from user
1013 ** namechng Show only checkins that filename changes
1014 ** ym=YYYY-MM Shown only events for the given year/month.
@@ -1360,11 +1361,11 @@
1360 blob_appendf(&sql, " AND (event.user=%Q OR event.euser=%Q)",
1361 zUser, zUser);
1362 url_add_parameter(&url, "u", zUser);
1363 zThisUser = zUser;
1364 }
1365 if ( zSearch ){
1366 blob_appendf(&sql,
1367 " AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')",
1368 zSearch, zSearch);
1369 url_add_parameter(&url, "s", zSearch);
1370 }
@@ -1760,11 +1761,11 @@
1760 }
1761 db_find_and_open_repository(0, 0);
1762 zLimit = find_option("limit","n",1);
1763 zWidth = find_option("width","W",1);
1764 zType = find_option("type","t",1);
1765 if ( !zLimit ){
1766 zLimit = find_option("count",0,1);
1767 }
1768 if( zLimit ){
1769 n = atoi(zLimit);
1770 }else{
@@ -1778,10 +1779,14 @@
1778 }else{
1779 width = -1;
1780 }
1781 zOffset = find_option("offset",0,1);
1782 iOffset = zOffset ? atoi(zOffset) : 0;
 
 
 
 
1783 if( g.argc>=4 ){
1784 k = strlen(g.argv[2]);
1785 if( strncmp(g.argv[2],"before",k)==0 ){
1786 mode = 1;
1787 }else if( strncmp(g.argv[2],"after",k)==0 && k>1 ){
@@ -1964,11 +1969,11 @@
1964
1965 /*
1966 ** Set by stats_report_init_view() to one of the y=XXXX values
1967 ** accepted by /timeline?y=XXXX.
1968 */
1969 static const char * statsReportTimelineYFlag = NULL;
1970
1971 /*
1972 ** Creates a TEMP VIEW named v_reports which is a wrapper around the
1973 ** EVENT table filtered on event.type. It looks for the request
1974 ** parameter 'type' (reminder: we "should" use 'y' for consistency
@@ -1985,12 +1990,12 @@
1985 ** Returns one of: 'c', 'w', 'g', 't', 'e', representing the type of
1986 ** filter it applies, or '*' if no filter is applied (i.e. if "all" is
1987 ** used).
1988 */
1989 static int stats_report_init_view(){
1990 const char * zType = PD("type","*"); /* analog to /timeline?y=... */
1991 const char * zRealType = NULL; /* normalized form of zType */
1992 int rc = 0; /* result code */
1993 assert( !statsReportType && "Must not be called more than once." );
1994 switch( (zType && *zType) ? *zType : 0 ){
1995 case 'c':
1996 case 'C':
@@ -2039,11 +2044,11 @@
2039 ** Returns a string suitable (for a given value of suitable) for
2040 ** use in a label with the header of the /reports pages, dependent
2041 ** on the 'type' flag. See stats_report_init_view().
2042 ** The returned bytes are static.
2043 */
2044 static const char * stats_report_label_for_type(){
2045 assert( statsReportType && "Must call stats_report_init_view() first." );
2046 switch( statsReportType ){
2047 case 'c':
2048 return "checkins";
2049 case 'e':
@@ -2066,13 +2071,13 @@
2066 ** time this is called. e.g. if called from the 'byuser' view then
2067 ** zCurrentViewName must be "byuser". Any URL parameters which need to
2068 ** be added to the generated URLs should be passed in zParam. The
2069 ** caller is expected to have already encoded any zParam in the %T or
2070 ** %t encoding. */
2071 static void stats_report_event_types_menu(const char * zCurrentViewName,
2072 const char * zParam){
2073 char * zTop;
2074 if(zParam && !*zParam){
2075 zParam = NULL;
2076 }
2077 zTop = mprintf("%s/reports?view=%s%s%s", g.zTop, zCurrentViewName,
2078 zParam ? "&" : "", zParam);
@@ -2116,11 +2121,11 @@
2116 /*
2117 ** Helper for stats_report_by_month_year(), which generates a list of
2118 ** week numbers. zTimeframe should be either a timeframe in the form YYYY
2119 ** or YYYY-MM.
2120 */
2121 static void stats_report_output_week_links(const char * zTimeframe){
2122 Stmt stWeek = empty_Stmt;
2123 char yearPart[5] = {0,0,0,0,0};
2124 memcpy(yearPart, zTimeframe, 4);
2125 db_prepare(&stWeek,
2126 "SELECT DISTINCT strftime('%%W',mtime) AS wk, "
@@ -2130,11 +2135,11 @@
2130 "WHERE ym=%Q AND mtime < current_timestamp "
2131 "GROUP BY wk ORDER BY wk",
2132 strlen(zTimeframe),
2133 zTimeframe);
2134 while( SQLITE_ROW == db_step(&stWeek) ){
2135 const char * zWeek = db_column_text(&stWeek,0);
2136 const int nCount = db_column_int(&stWeek,1);
2137 cgi_printf("<a href='%s/timeline?"
2138 "yw=%t-%t&n=%d&y=%s'>%s</a>",
2139 g.zTop, yearPart, zWeek,
2140 nCount, statsReportTimelineYFlag, zWeek);
@@ -2149,18 +2154,18 @@
2149 ** then the report is restricted to events created by the named user
2150 ** account.
2151 */
2152 static void stats_report_by_month_year(char includeMonth,
2153 char includeWeeks,
2154 const char * zUserName){
2155 Stmt query = empty_Stmt;
2156 int nRowNumber = 0; /* current TR number */
2157 int nEventTotal = 0; /* Total event count */
2158 int rowClass = 0; /* counter for alternating
2159 row colors */
2160 Blob sql = empty_blob; /* SQL */
2161 const char * zTimeLabel = includeMonth ? "Year/Month" : "Year";
2162 char zPrevYear[5] = {0}; /* For keeping track of when
2163 we change years while looping */
2164 int nEventsPerYear = 0; /* Total event count for the
2165 current year */
2166 char showYearTotal = 0; /* Flag telling us when to show
@@ -2211,11 +2216,11 @@
2211 }
2212 ++iterations;
2213 }
2214 db_reset(&query);
2215 while( SQLITE_ROW == db_step(&query) ){
2216 const char * zTimeframe = db_column_text(&query, 0);
2217 const int nCount = db_column_int(&query, 1);
2218 int nSize = nCount
2219 ? (int)(100 * nCount / nMaxEvents)
2220 : 1;
2221 showYearTotal = 0;
@@ -2296,11 +2301,11 @@
2296 @ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td>
2297 @</tr>
2298 }
2299 @ </tbody></table>
2300 if(nEventTotal){
2301 const char * zAvgLabel = includeMonth ? "month" : "year";
2302 int nAvg = iterations ? (nEventTotal/iterations) : 0;
2303 @ <br><div>Total events: %d(nEventTotal)
2304 @ <br>Average per active %s(zAvgLabel): %d(nAvg)
2305 @ </div>
2306 }
@@ -2346,11 +2351,11 @@
2346 nMaxEvents = nCount;
2347 }
2348 }
2349 db_reset(&query);
2350 while( SQLITE_ROW == db_step(&query) ){
2351 const char * zUser = db_column_text(&query, 0);
2352 const int nCount = db_column_int(&query, 1);
2353 int nSize = nCount
2354 ? (int)(100 * nCount / nMaxEvents)
2355 : 0;
2356 if(!nCount) continue /* arguable! Possible? */;
@@ -2386,11 +2391,11 @@
2386 int rowClass = 0; /* counter for alternating
2387 row colors */
2388 Blob sql = empty_blob; /* SQL */
2389 int nMaxEvents = 1; /* max number of events for
2390 all rows. */
2391 static const char * const daysOfWeek[] = {
2392 "Monday", "Tuesday", "Wednesday", "Thursday",
2393 "Friday", "Saturday", "Sunday"
2394 };
2395
2396 stats_report_init_view();
@@ -2419,11 +2424,11 @@
2419 nMaxEvents = nCount;
2420 }
2421 }
2422 db_reset(&query);
2423 while( SQLITE_ROW == db_step(&query) ){
2424 int const dayNum =db_column_int(&query, 0);
2425 const int nCount = db_column_int(&query, 1);
2426 int nSize = nCount
2427 ? (int)(100 * nCount / nMaxEvents)
2428 : 0;
2429 if(!nCount) continue /* arguable! Possible? */;
@@ -2449,16 +2454,16 @@
2449 /*
2450 ** Helper for stats_report_by_month_year(), which generates a list of
2451 ** week numbers. zTimeframe should be either a timeframe in the form YYYY
2452 ** or YYYY-MM.
2453 */
2454 static void stats_report_year_weeks(const char * zUserName){
2455 const char * zYear = P("y");
2456 int nYear = zYear ? strlen(zYear) : 0;
2457 int i = 0;
2458 Stmt qYears = empty_Stmt;
2459 char * zDefaultYear = NULL;
2460 Blob sql = empty_blob;
2461 int nMaxEvents = 1; /* max number of events for
2462 all rows. */
2463 int iterations = 0; /* # of active time periods. */
2464 stats_report_init_view();
@@ -2479,11 +2484,11 @@
2479 blob_append(&sql,"GROUP BY y ORDER BY y", -1);
2480 db_prepare(&qYears, blob_str(&sql));
2481 blob_reset(&sql);
2482 cgi_printf("Select year: ");
2483 while( SQLITE_ROW == db_step(&qYears) ){
2484 const char * zT = db_column_text(&qYears, 0);
2485 if( i++ ){
2486 cgi_printf(" ");
2487 }
2488 cgi_printf("<a href='?view=byweek&y=%s&type=%c", zT,
2489 (char)statsReportType);
@@ -2539,11 +2544,11 @@
2539 }
2540 ++iterations;
2541 }
2542 db_reset(&stWeek);
2543 while( SQLITE_ROW == db_step(&stWeek) ){
2544 const char * zWeek = db_column_text(&stWeek,0);
2545 const int nCount = db_column_int(&stWeek,1);
2546 int nSize = nCount
2547 ? (int)(100 * nCount / nMaxEvents)
2548 : 0;
2549 if(!nSize) nSize = 1;
@@ -2599,11 +2604,11 @@
2599 ** y=YYYY The year to report (default is the server's
2600 ** current year).
2601 */
2602 void stats_report_page(){
2603 HQuery url; /* URL for various branch links */
2604 const char * zView = P("view"); /* Which view/report to show. */
2605 const char *zUserName = P("user");
2606
2607 login_check_credentials();
2608 if( !g.perm.Read ){ login_needed(); return; }
2609 if(!zUserName) zUserName = P("u");
2610
--- src/timeline.c
+++ src/timeline.c
@@ -996,19 +996,20 @@
996 ** d=UUID artifact and up to COUNT descendants
997 ** dp=UUID The same as d=UUID&p=UUID
998 ** t=TAGID show only check-ins with the given tagid
999 ** r=TAGID show check-ins related to tagid
1000 ** u=USER only if belonging to this user
1001 ** y=TYPE 'ci', 'w', 't', 'e', or (default) 'all'
1002 ** s=TEXT string search (comment and brief)
1003 ** ng Suppress the graph if present
1004 ** nd Suppress "divider" lines
1005 ** v Show details of files changed
1006 ** f=UUID Show family (immediate parents and children) of UUID
1007 ** from=UUID Path from...
1008 ** to=UUID ... to this
1009 ** nomerge ... avoid merge links on the path
1010 ** shortest ... show only the shortest path
1011 ** uf=FUUID Show only checkins that use given file version
1012 ** brbg Background color from branch name
1013 ** ubg Background color from user
1014 ** namechng Show only checkins that filename changes
1015 ** ym=YYYY-MM Shown only events for the given year/month.
@@ -1360,11 +1361,11 @@
1361 blob_appendf(&sql, " AND (event.user=%Q OR event.euser=%Q)",
1362 zUser, zUser);
1363 url_add_parameter(&url, "u", zUser);
1364 zThisUser = zUser;
1365 }
1366 if( zSearch ){
1367 blob_appendf(&sql,
1368 " AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')",
1369 zSearch, zSearch);
1370 url_add_parameter(&url, "s", zSearch);
1371 }
@@ -1760,11 +1761,11 @@
1761 }
1762 db_find_and_open_repository(0, 0);
1763 zLimit = find_option("limit","n",1);
1764 zWidth = find_option("width","W",1);
1765 zType = find_option("type","t",1);
1766 if( !zLimit ){
1767 zLimit = find_option("count",0,1);
1768 }
1769 if( zLimit ){
1770 n = atoi(zLimit);
1771 }else{
@@ -1778,10 +1779,14 @@
1779 }else{
1780 width = -1;
1781 }
1782 zOffset = find_option("offset",0,1);
1783 iOffset = zOffset ? atoi(zOffset) : 0;
1784
1785 /* We should be done with options.. */
1786 verify_all_options();
1787
1788 if( g.argc>=4 ){
1789 k = strlen(g.argv[2]);
1790 if( strncmp(g.argv[2],"before",k)==0 ){
1791 mode = 1;
1792 }else if( strncmp(g.argv[2],"after",k)==0 && k>1 ){
@@ -1964,11 +1969,11 @@
1969
1970 /*
1971 ** Set by stats_report_init_view() to one of the y=XXXX values
1972 ** accepted by /timeline?y=XXXX.
1973 */
1974 static const char *statsReportTimelineYFlag = NULL;
1975
1976 /*
1977 ** Creates a TEMP VIEW named v_reports which is a wrapper around the
1978 ** EVENT table filtered on event.type. It looks for the request
1979 ** parameter 'type' (reminder: we "should" use 'y' for consistency
@@ -1985,12 +1990,12 @@
1990 ** Returns one of: 'c', 'w', 'g', 't', 'e', representing the type of
1991 ** filter it applies, or '*' if no filter is applied (i.e. if "all" is
1992 ** used).
1993 */
1994 static int stats_report_init_view(){
1995 const char *zType = PD("type","*"); /* analog to /timeline?y=... */
1996 const char *zRealType = NULL; /* normalized form of zType */
1997 int rc = 0; /* result code */
1998 assert( !statsReportType && "Must not be called more than once." );
1999 switch( (zType && *zType) ? *zType : 0 ){
2000 case 'c':
2001 case 'C':
@@ -2039,11 +2044,11 @@
2044 ** Returns a string suitable (for a given value of suitable) for
2045 ** use in a label with the header of the /reports pages, dependent
2046 ** on the 'type' flag. See stats_report_init_view().
2047 ** The returned bytes are static.
2048 */
2049 static const char *stats_report_label_for_type(){
2050 assert( statsReportType && "Must call stats_report_init_view() first." );
2051 switch( statsReportType ){
2052 case 'c':
2053 return "checkins";
2054 case 'e':
@@ -2066,13 +2071,13 @@
2071 ** time this is called. e.g. if called from the 'byuser' view then
2072 ** zCurrentViewName must be "byuser". Any URL parameters which need to
2073 ** be added to the generated URLs should be passed in zParam. The
2074 ** caller is expected to have already encoded any zParam in the %T or
2075 ** %t encoding. */
2076 static void stats_report_event_types_menu(const char *zCurrentViewName,
2077 const char *zParam){
2078 char *zTop;
2079 if(zParam && !*zParam){
2080 zParam = NULL;
2081 }
2082 zTop = mprintf("%s/reports?view=%s%s%s", g.zTop, zCurrentViewName,
2083 zParam ? "&" : "", zParam);
@@ -2116,11 +2121,11 @@
2121 /*
2122 ** Helper for stats_report_by_month_year(), which generates a list of
2123 ** week numbers. zTimeframe should be either a timeframe in the form YYYY
2124 ** or YYYY-MM.
2125 */
2126 static void stats_report_output_week_links(const char *zTimeframe){
2127 Stmt stWeek = empty_Stmt;
2128 char yearPart[5] = {0,0,0,0,0};
2129 memcpy(yearPart, zTimeframe, 4);
2130 db_prepare(&stWeek,
2131 "SELECT DISTINCT strftime('%%W',mtime) AS wk, "
@@ -2130,11 +2135,11 @@
2135 "WHERE ym=%Q AND mtime < current_timestamp "
2136 "GROUP BY wk ORDER BY wk",
2137 strlen(zTimeframe),
2138 zTimeframe);
2139 while( SQLITE_ROW == db_step(&stWeek) ){
2140 const char *zWeek = db_column_text(&stWeek,0);
2141 const int nCount = db_column_int(&stWeek,1);
2142 cgi_printf("<a href='%s/timeline?"
2143 "yw=%t-%t&n=%d&y=%s'>%s</a>",
2144 g.zTop, yearPart, zWeek,
2145 nCount, statsReportTimelineYFlag, zWeek);
@@ -2149,18 +2154,18 @@
2154 ** then the report is restricted to events created by the named user
2155 ** account.
2156 */
2157 static void stats_report_by_month_year(char includeMonth,
2158 char includeWeeks,
2159 const char *zUserName){
2160 Stmt query = empty_Stmt;
2161 int nRowNumber = 0; /* current TR number */
2162 int nEventTotal = 0; /* Total event count */
2163 int rowClass = 0; /* counter for alternating
2164 row colors */
2165 Blob sql = empty_blob; /* SQL */
2166 const char *zTimeLabel = includeMonth ? "Year/Month" : "Year";
2167 char zPrevYear[5] = {0}; /* For keeping track of when
2168 we change years while looping */
2169 int nEventsPerYear = 0; /* Total event count for the
2170 current year */
2171 char showYearTotal = 0; /* Flag telling us when to show
@@ -2211,11 +2216,11 @@
2216 }
2217 ++iterations;
2218 }
2219 db_reset(&query);
2220 while( SQLITE_ROW == db_step(&query) ){
2221 const char *zTimeframe = db_column_text(&query, 0);
2222 const int nCount = db_column_int(&query, 1);
2223 int nSize = nCount
2224 ? (int)(100 * nCount / nMaxEvents)
2225 : 1;
2226 showYearTotal = 0;
@@ -2296,11 +2301,11 @@
2301 @ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td>
2302 @</tr>
2303 }
2304 @ </tbody></table>
2305 if(nEventTotal){
2306 const char *zAvgLabel = includeMonth ? "month" : "year";
2307 int nAvg = iterations ? (nEventTotal/iterations) : 0;
2308 @ <br><div>Total events: %d(nEventTotal)
2309 @ <br>Average per active %s(zAvgLabel): %d(nAvg)
2310 @ </div>
2311 }
@@ -2346,11 +2351,11 @@
2351 nMaxEvents = nCount;
2352 }
2353 }
2354 db_reset(&query);
2355 while( SQLITE_ROW == db_step(&query) ){
2356 const char *zUser = db_column_text(&query, 0);
2357 const int nCount = db_column_int(&query, 1);
2358 int nSize = nCount
2359 ? (int)(100 * nCount / nMaxEvents)
2360 : 0;
2361 if(!nCount) continue /* arguable! Possible? */;
@@ -2386,11 +2391,11 @@
2391 int rowClass = 0; /* counter for alternating
2392 row colors */
2393 Blob sql = empty_blob; /* SQL */
2394 int nMaxEvents = 1; /* max number of events for
2395 all rows. */
2396 static const char *const daysOfWeek[] = {
2397 "Monday", "Tuesday", "Wednesday", "Thursday",
2398 "Friday", "Saturday", "Sunday"
2399 };
2400
2401 stats_report_init_view();
@@ -2419,11 +2424,11 @@
2424 nMaxEvents = nCount;
2425 }
2426 }
2427 db_reset(&query);
2428 while( SQLITE_ROW == db_step(&query) ){
2429 const int dayNum =db_column_int(&query, 0);
2430 const int nCount = db_column_int(&query, 1);
2431 int nSize = nCount
2432 ? (int)(100 * nCount / nMaxEvents)
2433 : 0;
2434 if(!nCount) continue /* arguable! Possible? */;
@@ -2449,16 +2454,16 @@
2454 /*
2455 ** Helper for stats_report_by_month_year(), which generates a list of
2456 ** week numbers. zTimeframe should be either a timeframe in the form YYYY
2457 ** or YYYY-MM.
2458 */
2459 static void stats_report_year_weeks(const char *zUserName){
2460 const char *zYear = P("y");
2461 int nYear = zYear ? strlen(zYear) : 0;
2462 int i = 0;
2463 Stmt qYears = empty_Stmt;
2464 char *zDefaultYear = NULL;
2465 Blob sql = empty_blob;
2466 int nMaxEvents = 1; /* max number of events for
2467 all rows. */
2468 int iterations = 0; /* # of active time periods. */
2469 stats_report_init_view();
@@ -2479,11 +2484,11 @@
2484 blob_append(&sql,"GROUP BY y ORDER BY y", -1);
2485 db_prepare(&qYears, blob_str(&sql));
2486 blob_reset(&sql);
2487 cgi_printf("Select year: ");
2488 while( SQLITE_ROW == db_step(&qYears) ){
2489 const char *zT = db_column_text(&qYears, 0);
2490 if( i++ ){
2491 cgi_printf(" ");
2492 }
2493 cgi_printf("<a href='?view=byweek&y=%s&type=%c", zT,
2494 (char)statsReportType);
@@ -2539,11 +2544,11 @@
2544 }
2545 ++iterations;
2546 }
2547 db_reset(&stWeek);
2548 while( SQLITE_ROW == db_step(&stWeek) ){
2549 const char *zWeek = db_column_text(&stWeek,0);
2550 const int nCount = db_column_int(&stWeek,1);
2551 int nSize = nCount
2552 ? (int)(100 * nCount / nMaxEvents)
2553 : 0;
2554 if(!nSize) nSize = 1;
@@ -2599,11 +2604,11 @@
2604 ** y=YYYY The year to report (default is the server's
2605 ** current year).
2606 */
2607 void stats_report_page(){
2608 HQuery url; /* URL for various branch links */
2609 const char *zView = P("view"); /* Which view/report to show. */
2610 const char *zUserName = P("user");
2611
2612 login_check_credentials();
2613 if( !g.perm.Read ){ login_needed(); return; }
2614 if(!zUserName) zUserName = P("u");
2615
+7 -7
--- src/tkt.c
+++ src/tkt.c
@@ -1207,11 +1207,11 @@
12071207
/* we just handle history separately here, does not get out */
12081208
if( eCmd==history ){
12091209
Stmt q;
12101210
int tagid;
12111211
1212
- if ( i != g.argc ){
1212
+ if( i != g.argc ){
12131213
fossil_fatal("no other parameters expected to %s!",g.argv[2]);
12141214
}
12151215
tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",
12161216
zTktUuid);
12171217
if( tagid==0 ){
@@ -1299,20 +1299,20 @@
12991299
if( tktEncoding == tktFossilize ){
13001300
zFValue=mprintf("%s",zFValue);
13011301
defossilize(zFValue);
13021302
}
13031303
append = (zFName[0] == '+');
1304
- if (append){
1304
+ if( append ){
13051305
zFName++;
13061306
}
13071307
j = fieldId(zFName);
13081308
if( j == -1 ){
13091309
fossil_fatal("unknown field name '%s'!",zFName);
13101310
}else{
1311
- if (append) {
1311
+ if( append ){
13121312
aField[j].zAppend = zFValue;
1313
- } else {
1313
+ }else{
13141314
aField[j].zValue = zFValue;
13151315
}
13161316
}
13171317
}
13181318
@@ -1323,17 +1323,17 @@
13231323
/* append defined elements */
13241324
for(i=0; i<nField; i++){
13251325
char *zValue = 0;
13261326
char *zPfx;
13271327
1328
- if (aField[i].zAppend && aField[i].zAppend[0] ){
1328
+ if( aField[i].zAppend && aField[i].zAppend[0] ){
13291329
zPfx = " +";
13301330
zValue = aField[i].zAppend;
1331
- } else if( aField[i].zValue && aField[i].zValue[0] ){
1331
+ }else if( aField[i].zValue && aField[i].zValue[0] ){
13321332
zPfx = " ";
13331333
zValue = aField[i].zValue;
1334
- } else {
1334
+ }else{
13351335
continue;
13361336
}
13371337
if( memcmp(aField[i].zName, "private_", 8)==0 ){
13381338
zValue = db_conceal(zValue, strlen(zValue));
13391339
blob_appendf(&tktchng, "J%s%s %s\n", zPfx, aField[i].zName, zValue);
13401340
--- src/tkt.c
+++ src/tkt.c
@@ -1207,11 +1207,11 @@
1207 /* we just handle history separately here, does not get out */
1208 if( eCmd==history ){
1209 Stmt q;
1210 int tagid;
1211
1212 if ( i != g.argc ){
1213 fossil_fatal("no other parameters expected to %s!",g.argv[2]);
1214 }
1215 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",
1216 zTktUuid);
1217 if( tagid==0 ){
@@ -1299,20 +1299,20 @@
1299 if( tktEncoding == tktFossilize ){
1300 zFValue=mprintf("%s",zFValue);
1301 defossilize(zFValue);
1302 }
1303 append = (zFName[0] == '+');
1304 if (append){
1305 zFName++;
1306 }
1307 j = fieldId(zFName);
1308 if( j == -1 ){
1309 fossil_fatal("unknown field name '%s'!",zFName);
1310 }else{
1311 if (append) {
1312 aField[j].zAppend = zFValue;
1313 } else {
1314 aField[j].zValue = zFValue;
1315 }
1316 }
1317 }
1318
@@ -1323,17 +1323,17 @@
1323 /* append defined elements */
1324 for(i=0; i<nField; i++){
1325 char *zValue = 0;
1326 char *zPfx;
1327
1328 if (aField[i].zAppend && aField[i].zAppend[0] ){
1329 zPfx = " +";
1330 zValue = aField[i].zAppend;
1331 } else if( aField[i].zValue && aField[i].zValue[0] ){
1332 zPfx = " ";
1333 zValue = aField[i].zValue;
1334 } else {
1335 continue;
1336 }
1337 if( memcmp(aField[i].zName, "private_", 8)==0 ){
1338 zValue = db_conceal(zValue, strlen(zValue));
1339 blob_appendf(&tktchng, "J%s%s %s\n", zPfx, aField[i].zName, zValue);
1340
--- src/tkt.c
+++ src/tkt.c
@@ -1207,11 +1207,11 @@
1207 /* we just handle history separately here, does not get out */
1208 if( eCmd==history ){
1209 Stmt q;
1210 int tagid;
1211
1212 if( i != g.argc ){
1213 fossil_fatal("no other parameters expected to %s!",g.argv[2]);
1214 }
1215 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",
1216 zTktUuid);
1217 if( tagid==0 ){
@@ -1299,20 +1299,20 @@
1299 if( tktEncoding == tktFossilize ){
1300 zFValue=mprintf("%s",zFValue);
1301 defossilize(zFValue);
1302 }
1303 append = (zFName[0] == '+');
1304 if( append ){
1305 zFName++;
1306 }
1307 j = fieldId(zFName);
1308 if( j == -1 ){
1309 fossil_fatal("unknown field name '%s'!",zFName);
1310 }else{
1311 if( append ){
1312 aField[j].zAppend = zFValue;
1313 }else{
1314 aField[j].zValue = zFValue;
1315 }
1316 }
1317 }
1318
@@ -1323,17 +1323,17 @@
1323 /* append defined elements */
1324 for(i=0; i<nField; i++){
1325 char *zValue = 0;
1326 char *zPfx;
1327
1328 if( aField[i].zAppend && aField[i].zAppend[0] ){
1329 zPfx = " +";
1330 zValue = aField[i].zAppend;
1331 }else if( aField[i].zValue && aField[i].zValue[0] ){
1332 zPfx = " ";
1333 zValue = aField[i].zValue;
1334 }else{
1335 continue;
1336 }
1337 if( memcmp(aField[i].zName, "private_", 8)==0 ){
1338 zValue = db_conceal(zValue, strlen(zValue));
1339 blob_appendf(&tktchng, "J%s%s %s\n", zPfx, aField[i].zName, zValue);
1340
+1 -1
--- src/unicode.c
+++ src/unicode.c
@@ -208,11 +208,11 @@
208208
iHi = iTest-1;
209209
}
210210
}
211211
assert( key>=aDia[iRes] );
212212
return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
213
-};
213
+}
214214
215215
216216
/*
217217
** Return true if the argument interpreted as a unicode codepoint
218218
** is a diacritical modifier character.
219219
--- src/unicode.c
+++ src/unicode.c
@@ -208,11 +208,11 @@
208 iHi = iTest-1;
209 }
210 }
211 assert( key>=aDia[iRes] );
212 return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
213 };
214
215
216 /*
217 ** Return true if the argument interpreted as a unicode codepoint
218 ** is a diacritical modifier character.
219
--- src/unicode.c
+++ src/unicode.c
@@ -208,11 +208,11 @@
208 iHi = iTest-1;
209 }
210 }
211 assert( key>=aDia[iRes] );
212 return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
213 }
214
215
216 /*
217 ** Return true if the argument interpreted as a unicode codepoint
218 ** is a diacritical modifier character.
219
+41 -29
--- src/update.c
+++ src/update.c
@@ -62,31 +62,37 @@
6262
/*
6363
** COMMAND: update
6464
**
6565
** Usage: %fossil update ?OPTIONS? ?VERSION? ?FILES...?
6666
**
67
-** Change the version of the current checkout to VERSION. Any uncommitted
68
-** changes are retained and applied to the new checkout.
67
+** Change the version of the current checkout to VERSION. Any
68
+** uncommitted changes are retained and applied to the new checkout.
6969
**
70
-** The VERSION argument can be a specific version or tag or branch name.
71
-** If the VERSION argument is omitted, then the leaf of the subtree
72
-** that begins at the current version is used, if there is only a single
73
-** leaf. VERSION can also be "current" to select the leaf of the current
74
-** version or "latest" to select the most recent check-in.
70
+** The VERSION argument can be a specific version or tag or branch
71
+** name. If the VERSION argument is omitted, then the leaf of the
72
+** subtree that begins at the current version is used, if there is
73
+** only a single leaf. VERSION can also be "current" to select the
74
+** leaf of the current version or "latest" to select the most recent
75
+** check-in.
7576
**
7677
** If one or more FILES are listed after the VERSION then only the
77
-** named files are candidates to be updated. If FILES is omitted, all
78
-** files in the current checkout are subject to be updated. Using
79
-** a directory name for one of the FILES arguments is the same as
80
-** using every subdirectory and file beneath that directory.
81
-**
82
-** The -n or --dry-run option causes this command to do a "dry run". It
83
-** prints out what would have happened but does not actually make any
84
-** changes to the current checkout or the repository.
85
-**
86
-** The -v or --verbose option prints status information about unchanged
87
-** files in addition to those file that actually do change.
78
+** named files are candidates to be updated, and any updates to them
79
+** will be treated as edits to the current version. Using a directory
80
+** name for one of the FILES arguments is the same as using every
81
+** subdirectory and file beneath that directory.
82
+**
83
+** If FILES is omitted, all files in the current checkout are subject
84
+** to being updated and the version of the current checkout is changed
85
+** to VERSION. Any uncommitted changes are retained and applied to the
86
+** new checkout.
87
+**
88
+** The -n or --dry-run option causes this command to do a "dry run".
89
+** It prints out what would have happened but does not actually make
90
+** any changes to the current checkout or the repository.
91
+**
92
+** The -v or --verbose option prints status information about
93
+** unchanged files in addition to those file that actually do change.
8894
**
8995
** Options:
9096
** --case-sensitive <BOOL> override case-sensitive setting
9197
** --debug print debug information on stdout
9298
** --latest acceptable in place of VERSION, update to latest version
@@ -139,10 +145,14 @@
139145
verboseFlag = find_option("verbose","v",0)!=0;
140146
forceMissingFlag = find_option("force-missing",0,0)!=0;
141147
debugFlag = find_option("debug",0,0)!=0;
142148
setmtimeFlag = find_option("setmtime",0,0)!=0;
143149
capture_case_sensitive_option();
150
+
151
+ /* We should be done with options.. */
152
+ verify_all_options();
153
+
144154
db_must_be_within_tree();
145155
vid = db_lget_int("checkout", 0);
146156
user_select();
147157
if( !dryRunFlag && !internalUpdate ){
148158
if( autosync_loop(SYNC_PULL + SYNC_VERBOSE*verboseFlag,
@@ -261,21 +271,23 @@
261271
);
262272
263273
/* Compute file name changes on V->T. Record name changes in files that
264274
** have changed locally.
265275
*/
266
- find_filename_changes(vid, tid, 1, &nChng, &aChng, debugFlag ? "V->T": 0);
267
- if( nChng ){
268
- for(i=0; i<nChng; i++){
269
- db_multi_exec(
270
- "UPDATE fv"
271
- " SET fnt=(SELECT name FROM filename WHERE fnid=%d)"
272
- " WHERE fn=(SELECT name FROM filename WHERE fnid=%d) AND chnged",
273
- aChng[i*2+1], aChng[i*2]
274
- );
275
- }
276
- fossil_free(aChng);
276
+ if( vid ){
277
+ find_filename_changes(vid, tid, 1, &nChng, &aChng, debugFlag ? "V->T": 0);
278
+ if( nChng ){
279
+ for(i=0; i<nChng; i++){
280
+ db_multi_exec(
281
+ "UPDATE fv"
282
+ " SET fnt=(SELECT name FROM filename WHERE fnid=%d)"
283
+ " WHERE fn=(SELECT name FROM filename WHERE fnid=%d) AND chnged",
284
+ aChng[i*2+1], aChng[i*2]
285
+ );
286
+ }
287
+ fossil_free(aChng);
288
+ }
277289
}
278290
279291
/* Add files found in the target version T but missing from the current
280292
** version V.
281293
*/
282294
--- src/update.c
+++ src/update.c
@@ -62,31 +62,37 @@
62 /*
63 ** COMMAND: update
64 **
65 ** Usage: %fossil update ?OPTIONS? ?VERSION? ?FILES...?
66 **
67 ** Change the version of the current checkout to VERSION. Any uncommitted
68 ** changes are retained and applied to the new checkout.
69 **
70 ** The VERSION argument can be a specific version or tag or branch name.
71 ** If the VERSION argument is omitted, then the leaf of the subtree
72 ** that begins at the current version is used, if there is only a single
73 ** leaf. VERSION can also be "current" to select the leaf of the current
74 ** version or "latest" to select the most recent check-in.
 
75 **
76 ** If one or more FILES are listed after the VERSION then only the
77 ** named files are candidates to be updated. If FILES is omitted, all
78 ** files in the current checkout are subject to be updated. Using
79 ** a directory name for one of the FILES arguments is the same as
80 ** using every subdirectory and file beneath that directory.
81 **
82 ** The -n or --dry-run option causes this command to do a "dry run". It
83 ** prints out what would have happened but does not actually make any
84 ** changes to the current checkout or the repository.
85 **
86 ** The -v or --verbose option prints status information about unchanged
87 ** files in addition to those file that actually do change.
 
 
 
 
 
88 **
89 ** Options:
90 ** --case-sensitive <BOOL> override case-sensitive setting
91 ** --debug print debug information on stdout
92 ** --latest acceptable in place of VERSION, update to latest version
@@ -139,10 +145,14 @@
139 verboseFlag = find_option("verbose","v",0)!=0;
140 forceMissingFlag = find_option("force-missing",0,0)!=0;
141 debugFlag = find_option("debug",0,0)!=0;
142 setmtimeFlag = find_option("setmtime",0,0)!=0;
143 capture_case_sensitive_option();
 
 
 
 
144 db_must_be_within_tree();
145 vid = db_lget_int("checkout", 0);
146 user_select();
147 if( !dryRunFlag && !internalUpdate ){
148 if( autosync_loop(SYNC_PULL + SYNC_VERBOSE*verboseFlag,
@@ -261,21 +271,23 @@
261 );
262
263 /* Compute file name changes on V->T. Record name changes in files that
264 ** have changed locally.
265 */
266 find_filename_changes(vid, tid, 1, &nChng, &aChng, debugFlag ? "V->T": 0);
267 if( nChng ){
268 for(i=0; i<nChng; i++){
269 db_multi_exec(
270 "UPDATE fv"
271 " SET fnt=(SELECT name FROM filename WHERE fnid=%d)"
272 " WHERE fn=(SELECT name FROM filename WHERE fnid=%d) AND chnged",
273 aChng[i*2+1], aChng[i*2]
274 );
275 }
276 fossil_free(aChng);
 
 
277 }
278
279 /* Add files found in the target version T but missing from the current
280 ** version V.
281 */
282
--- src/update.c
+++ src/update.c
@@ -62,31 +62,37 @@
62 /*
63 ** COMMAND: update
64 **
65 ** Usage: %fossil update ?OPTIONS? ?VERSION? ?FILES...?
66 **
67 ** Change the version of the current checkout to VERSION. Any
68 ** uncommitted changes are retained and applied to the new checkout.
69 **
70 ** The VERSION argument can be a specific version or tag or branch
71 ** name. If the VERSION argument is omitted, then the leaf of the
72 ** subtree that begins at the current version is used, if there is
73 ** only a single leaf. VERSION can also be "current" to select the
74 ** leaf of the current version or "latest" to select the most recent
75 ** check-in.
76 **
77 ** If one or more FILES are listed after the VERSION then only the
78 ** named files are candidates to be updated, and any updates to them
79 ** will be treated as edits to the current version. Using a directory
80 ** name for one of the FILES arguments is the same as using every
81 ** subdirectory and file beneath that directory.
82 **
83 ** If FILES is omitted, all files in the current checkout are subject
84 ** to being updated and the version of the current checkout is changed
85 ** to VERSION. Any uncommitted changes are retained and applied to the
86 ** new checkout.
87 **
88 ** The -n or --dry-run option causes this command to do a "dry run".
89 ** It prints out what would have happened but does not actually make
90 ** any changes to the current checkout or the repository.
91 **
92 ** The -v or --verbose option prints status information about
93 ** unchanged files in addition to those file that actually do change.
94 **
95 ** Options:
96 ** --case-sensitive <BOOL> override case-sensitive setting
97 ** --debug print debug information on stdout
98 ** --latest acceptable in place of VERSION, update to latest version
@@ -139,10 +145,14 @@
145 verboseFlag = find_option("verbose","v",0)!=0;
146 forceMissingFlag = find_option("force-missing",0,0)!=0;
147 debugFlag = find_option("debug",0,0)!=0;
148 setmtimeFlag = find_option("setmtime",0,0)!=0;
149 capture_case_sensitive_option();
150
151 /* We should be done with options.. */
152 verify_all_options();
153
154 db_must_be_within_tree();
155 vid = db_lget_int("checkout", 0);
156 user_select();
157 if( !dryRunFlag && !internalUpdate ){
158 if( autosync_loop(SYNC_PULL + SYNC_VERBOSE*verboseFlag,
@@ -261,21 +271,23 @@
271 );
272
273 /* Compute file name changes on V->T. Record name changes in files that
274 ** have changed locally.
275 */
276 if( vid ){
277 find_filename_changes(vid, tid, 1, &nChng, &aChng, debugFlag ? "V->T": 0);
278 if( nChng ){
279 for(i=0; i<nChng; i++){
280 db_multi_exec(
281 "UPDATE fv"
282 " SET fnt=(SELECT name FROM filename WHERE fnid=%d)"
283 " WHERE fn=(SELECT name FROM filename WHERE fnid=%d) AND chnged",
284 aChng[i*2+1], aChng[i*2]
285 );
286 }
287 fossil_free(aChng);
288 }
289 }
290
291 /* Add files found in the target version T but missing from the current
292 ** version V.
293 */
294
+2 -2
--- src/utf8.c
+++ src/utf8.c
@@ -127,11 +127,11 @@
127127
pUtf = qUtf = zUtf;
128128
while( *pUtf ) {
129129
if( *pUtf == (char)0xef ){
130130
wchar_t c = ((pUtf[1]&0x3f)<<6)|(pUtf[2]&0x3f);
131131
/* Only really convert it when the resulting char is in range. */
132
- if ( c && ((c < ' ') || wcschr(L"\"*:<>?|", c)) ){
132
+ if( c && ((c < ' ') || wcschr(L"\"*:<>?|", c)) ){
133133
*qUtf++ = c; pUtf+=3; continue;
134134
}
135135
}
136136
*qUtf++ = *pUtf++;
137137
}
@@ -241,11 +241,11 @@
241241
** characters in the Unicode private use area. This is what makes
242242
** Win32 fossil.exe work well in a Cygwin environment even when a
243243
** filename contains characters which are invalid for Win32.
244244
*/
245245
while( *wUnicode != '\0' ){
246
- if ( (*wUnicode < ' ') || wcschr(L"\"*:<>?|", *wUnicode) ){
246
+ if( (*wUnicode < ' ') || wcschr(L"\"*:<>?|", *wUnicode) ){
247247
*wUnicode |= 0xF000;
248248
}else if( *wUnicode == '/' ){
249249
*wUnicode = '\\';
250250
}
251251
++wUnicode;
252252
--- src/utf8.c
+++ src/utf8.c
@@ -127,11 +127,11 @@
127 pUtf = qUtf = zUtf;
128 while( *pUtf ) {
129 if( *pUtf == (char)0xef ){
130 wchar_t c = ((pUtf[1]&0x3f)<<6)|(pUtf[2]&0x3f);
131 /* Only really convert it when the resulting char is in range. */
132 if ( c && ((c < ' ') || wcschr(L"\"*:<>?|", c)) ){
133 *qUtf++ = c; pUtf+=3; continue;
134 }
135 }
136 *qUtf++ = *pUtf++;
137 }
@@ -241,11 +241,11 @@
241 ** characters in the Unicode private use area. This is what makes
242 ** Win32 fossil.exe work well in a Cygwin environment even when a
243 ** filename contains characters which are invalid for Win32.
244 */
245 while( *wUnicode != '\0' ){
246 if ( (*wUnicode < ' ') || wcschr(L"\"*:<>?|", *wUnicode) ){
247 *wUnicode |= 0xF000;
248 }else if( *wUnicode == '/' ){
249 *wUnicode = '\\';
250 }
251 ++wUnicode;
252
--- src/utf8.c
+++ src/utf8.c
@@ -127,11 +127,11 @@
127 pUtf = qUtf = zUtf;
128 while( *pUtf ) {
129 if( *pUtf == (char)0xef ){
130 wchar_t c = ((pUtf[1]&0x3f)<<6)|(pUtf[2]&0x3f);
131 /* Only really convert it when the resulting char is in range. */
132 if( c && ((c < ' ') || wcschr(L"\"*:<>?|", c)) ){
133 *qUtf++ = c; pUtf+=3; continue;
134 }
135 }
136 *qUtf++ = *pUtf++;
137 }
@@ -241,11 +241,11 @@
241 ** characters in the Unicode private use area. This is what makes
242 ** Win32 fossil.exe work well in a Cygwin environment even when a
243 ** filename contains characters which are invalid for Win32.
244 */
245 while( *wUnicode != '\0' ){
246 if( (*wUnicode < ' ') || wcschr(L"\"*:<>?|", *wUnicode) ){
247 *wUnicode |= 0xF000;
248 }else if( *wUnicode == '/' ){
249 *wUnicode = '\\';
250 }
251 ++wUnicode;
252
+2 -2
--- src/util.c
+++ src/util.c
@@ -295,11 +295,11 @@
295295
*/
296296
int fossil_timer_is_active( int timerId ){
297297
if(timerId<1 || timerId>FOSSIL_TIMER_COUNT){
298298
return 0;
299299
}else{
300
- int const rc = fossilTimerList[timerId-1].id;
300
+ const int rc = fossilTimerList[timerId-1].id;
301301
assert(!rc || (rc == timerId));
302302
return fossilTimerList[timerId-1].id;
303303
}
304304
}
305305
@@ -317,10 +317,10 @@
317317
318318
/*
319319
** Returns TRUE if zSym is exactly UUID_SIZE bytes long and contains
320320
** only lower-case ASCII hexadecimal values.
321321
*/
322
-int fossil_is_uuid(char const * zSym){
322
+int fossil_is_uuid(const char *zSym){
323323
return zSym
324324
&& (UUID_SIZE==strlen(zSym))
325325
&& validate16(zSym, UUID_SIZE);
326326
}
327327
--- src/util.c
+++ src/util.c
@@ -295,11 +295,11 @@
295 */
296 int fossil_timer_is_active( int timerId ){
297 if(timerId<1 || timerId>FOSSIL_TIMER_COUNT){
298 return 0;
299 }else{
300 int const rc = fossilTimerList[timerId-1].id;
301 assert(!rc || (rc == timerId));
302 return fossilTimerList[timerId-1].id;
303 }
304 }
305
@@ -317,10 +317,10 @@
317
318 /*
319 ** Returns TRUE if zSym is exactly UUID_SIZE bytes long and contains
320 ** only lower-case ASCII hexadecimal values.
321 */
322 int fossil_is_uuid(char const * zSym){
323 return zSym
324 && (UUID_SIZE==strlen(zSym))
325 && validate16(zSym, UUID_SIZE);
326 }
327
--- src/util.c
+++ src/util.c
@@ -295,11 +295,11 @@
295 */
296 int fossil_timer_is_active( int timerId ){
297 if(timerId<1 || timerId>FOSSIL_TIMER_COUNT){
298 return 0;
299 }else{
300 const int rc = fossilTimerList[timerId-1].id;
301 assert(!rc || (rc == timerId));
302 return fossilTimerList[timerId-1].id;
303 }
304 }
305
@@ -317,10 +317,10 @@
317
318 /*
319 ** Returns TRUE if zSym is exactly UUID_SIZE bytes long and contains
320 ** only lower-case ASCII hexadecimal values.
321 */
322 int fossil_is_uuid(const char *zSym){
323 return zSym
324 && (UUID_SIZE==strlen(zSym))
325 && validate16(zSym, UUID_SIZE);
326 }
327
+8 -8
--- src/wiki.c
+++ src/wiki.c
@@ -860,11 +860,11 @@
860860
** URL: /wfind?title=TITLE
861861
** List all wiki pages whose titles contain the search text
862862
*/
863863
void wfind_page(void){
864864
Stmt q;
865
- const char * zTitle;
865
+ const char *zTitle;
866866
login_check_credentials();
867867
if( !g.perm.RdWiki ){ login_needed(); return; }
868868
zTitle = PD("title","*");
869869
style_header("Wiki Pages Found");
870870
@ <ul>
@@ -960,18 +960,18 @@
960960
**
961961
** zMimeType specifies the N-card for the wiki page. If it is 0,
962962
** empty, or "text/x-fossil-wiki" (the default format) then it is
963963
** ignored.
964964
*/
965
-int wiki_cmd_commit(char const * zPageName, int isNew, Blob *pContent,
966
- char const * zMimeType){
965
+int wiki_cmd_commit(const char *zPageName, int isNew, Blob *pContent,
966
+ const char *zMimeType){
967967
Blob wiki; /* Wiki page content */
968968
Blob cksum; /* wiki checksum */
969969
int rid; /* artifact ID of parent page */
970970
char *zDate; /* timestamp */
971971
char *zUuid; /* uuid for rid */
972
-
972
+
973973
rid = db_int(0,
974974
"SELECT x.rid FROM tag t, tagxref x"
975975
" WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
976976
" ORDER BY x.mtime DESC LIMIT 1",
977977
zPageName
@@ -1058,12 +1058,12 @@
10581058
if( n==0 ){
10591059
goto wiki_cmd_usage;
10601060
}
10611061
10621062
if( strncmp(g.argv[2],"export",n)==0 ){
1063
- char const *zPageName; /* Name of the wiki page to export */
1064
- char const *zFile; /* Name of the output file (0=stdout) */
1063
+ const char *zPageName; /* Name of the wiki page to export */
1064
+ const char *zFile; /* Name of the output file (0=stdout) */
10651065
int rid; /* Artifact ID of the wiki page */
10661066
int i; /* Loop counter */
10671067
char *zBody = 0; /* Wiki page content */
10681068
Blob body; /* Wiki page content */
10691069
Manifest *pWiki = 0; /* Parsed wiki page content */
@@ -1091,15 +1091,15 @@
10911091
blob_reset(&body);
10921092
manifest_destroy(pWiki);
10931093
return;
10941094
}else if( strncmp(g.argv[2],"commit",n)==0
10951095
|| strncmp(g.argv[2],"create",n)==0 ){
1096
- char const *zPageName; /* page name */
1096
+ const char *zPageName; /* page name */
10971097
Blob content; /* Input content */
10981098
int rid;
10991099
Manifest *pWiki = 0; /* Parsed wiki page content */
1100
- char const * zMimeType = find_option("mimetype", "M", 1);
1100
+ const char *zMimeType = find_option("mimetype", "M", 1);
11011101
if( g.argc!=4 && g.argc!=5 ){
11021102
usage("commit|create PAGENAME ?FILE? [-mimetype TEXT-FORMAT]");
11031103
}
11041104
zPageName = g.argv[3];
11051105
if( g.argc==4 ){
11061106
--- src/wiki.c
+++ src/wiki.c
@@ -860,11 +860,11 @@
860 ** URL: /wfind?title=TITLE
861 ** List all wiki pages whose titles contain the search text
862 */
863 void wfind_page(void){
864 Stmt q;
865 const char * zTitle;
866 login_check_credentials();
867 if( !g.perm.RdWiki ){ login_needed(); return; }
868 zTitle = PD("title","*");
869 style_header("Wiki Pages Found");
870 @ <ul>
@@ -960,18 +960,18 @@
960 **
961 ** zMimeType specifies the N-card for the wiki page. If it is 0,
962 ** empty, or "text/x-fossil-wiki" (the default format) then it is
963 ** ignored.
964 */
965 int wiki_cmd_commit(char const * zPageName, int isNew, Blob *pContent,
966 char const * zMimeType){
967 Blob wiki; /* Wiki page content */
968 Blob cksum; /* wiki checksum */
969 int rid; /* artifact ID of parent page */
970 char *zDate; /* timestamp */
971 char *zUuid; /* uuid for rid */
972
973 rid = db_int(0,
974 "SELECT x.rid FROM tag t, tagxref x"
975 " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
976 " ORDER BY x.mtime DESC LIMIT 1",
977 zPageName
@@ -1058,12 +1058,12 @@
1058 if( n==0 ){
1059 goto wiki_cmd_usage;
1060 }
1061
1062 if( strncmp(g.argv[2],"export",n)==0 ){
1063 char const *zPageName; /* Name of the wiki page to export */
1064 char const *zFile; /* Name of the output file (0=stdout) */
1065 int rid; /* Artifact ID of the wiki page */
1066 int i; /* Loop counter */
1067 char *zBody = 0; /* Wiki page content */
1068 Blob body; /* Wiki page content */
1069 Manifest *pWiki = 0; /* Parsed wiki page content */
@@ -1091,15 +1091,15 @@
1091 blob_reset(&body);
1092 manifest_destroy(pWiki);
1093 return;
1094 }else if( strncmp(g.argv[2],"commit",n)==0
1095 || strncmp(g.argv[2],"create",n)==0 ){
1096 char const *zPageName; /* page name */
1097 Blob content; /* Input content */
1098 int rid;
1099 Manifest *pWiki = 0; /* Parsed wiki page content */
1100 char const * zMimeType = find_option("mimetype", "M", 1);
1101 if( g.argc!=4 && g.argc!=5 ){
1102 usage("commit|create PAGENAME ?FILE? [-mimetype TEXT-FORMAT]");
1103 }
1104 zPageName = g.argv[3];
1105 if( g.argc==4 ){
1106
--- src/wiki.c
+++ src/wiki.c
@@ -860,11 +860,11 @@
860 ** URL: /wfind?title=TITLE
861 ** List all wiki pages whose titles contain the search text
862 */
863 void wfind_page(void){
864 Stmt q;
865 const char *zTitle;
866 login_check_credentials();
867 if( !g.perm.RdWiki ){ login_needed(); return; }
868 zTitle = PD("title","*");
869 style_header("Wiki Pages Found");
870 @ <ul>
@@ -960,18 +960,18 @@
960 **
961 ** zMimeType specifies the N-card for the wiki page. If it is 0,
962 ** empty, or "text/x-fossil-wiki" (the default format) then it is
963 ** ignored.
964 */
965 int wiki_cmd_commit(const char *zPageName, int isNew, Blob *pContent,
966 const char *zMimeType){
967 Blob wiki; /* Wiki page content */
968 Blob cksum; /* wiki checksum */
969 int rid; /* artifact ID of parent page */
970 char *zDate; /* timestamp */
971 char *zUuid; /* uuid for rid */
972
973 rid = db_int(0,
974 "SELECT x.rid FROM tag t, tagxref x"
975 " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
976 " ORDER BY x.mtime DESC LIMIT 1",
977 zPageName
@@ -1058,12 +1058,12 @@
1058 if( n==0 ){
1059 goto wiki_cmd_usage;
1060 }
1061
1062 if( strncmp(g.argv[2],"export",n)==0 ){
1063 const char *zPageName; /* Name of the wiki page to export */
1064 const char *zFile; /* Name of the output file (0=stdout) */
1065 int rid; /* Artifact ID of the wiki page */
1066 int i; /* Loop counter */
1067 char *zBody = 0; /* Wiki page content */
1068 Blob body; /* Wiki page content */
1069 Manifest *pWiki = 0; /* Parsed wiki page content */
@@ -1091,15 +1091,15 @@
1091 blob_reset(&body);
1092 manifest_destroy(pWiki);
1093 return;
1094 }else if( strncmp(g.argv[2],"commit",n)==0
1095 || strncmp(g.argv[2],"create",n)==0 ){
1096 const char *zPageName; /* page name */
1097 Blob content; /* Input content */
1098 int rid;
1099 Manifest *pWiki = 0; /* Parsed wiki page content */
1100 const char *zMimeType = find_option("mimetype", "M", 1);
1101 if( g.argc!=4 && g.argc!=5 ){
1102 usage("commit|create PAGENAME ?FILE? [-mimetype TEXT-FORMAT]");
1103 }
1104 zPageName = g.argv[3];
1105 if( g.argc==4 ){
1106
+11 -6
--- src/winhttp.c
+++ src/winhttp.c
@@ -682,15 +682,20 @@
682682
683683
verify_all_options();
684684
if( g.argc==4 ){
685685
zSvcName = g.argv[3];
686686
}else if( g.argc>4 ){
687
- fossil_fatal("to much arguments for create method.");
687
+ fossil_fatal("too many arguments for create method.");
688688
}
689689
/* Process service creation specific options. */
690690
if( !zDisplay ){
691691
zDisplay = zSvcName;
692
+ }
693
+ /* Per MSDN, the password parameter cannot be NULL. Must use empty
694
+ ** string instead (i.e. in the call to CreateServiceW). */
695
+ if( !zPassword ){
696
+ zPassword = "";
692697
}
693698
if( zStart ){
694699
if( strncmp(zStart, "auto", strlen(zStart))==0 ){
695700
dwStartType = SERVICE_AUTO_START;
696701
}else if( strncmp(zStart, "manual", strlen(zStart))==0 ){
@@ -736,11 +741,11 @@
736741
SERVICE_ERROR_NORMAL, /* Error control */
737742
fossil_utf8_to_unicode(blob_str(&binPath)), /* Binary path */
738743
NULL, /* Load ordering group */
739744
NULL, /* Tag value */
740745
NULL, /* Service dependencies */
741
- fossil_utf8_to_unicode(zUsername), /* Service account */
746
+ zUsername ? fossil_utf8_to_unicode(zUsername) : 0, /* Account */
742747
fossil_utf8_to_unicode(zPassword) /* Account password */
743748
);
744749
if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
745750
/* Set the service description. */
746751
ChangeServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr);
@@ -756,11 +761,11 @@
756761
757762
verify_all_options();
758763
if( g.argc==4 ){
759764
zSvcName = g.argv[3];
760765
}else if( g.argc>4 ){
761
- fossil_fatal("to much arguments for delete method.");
766
+ fossil_fatal("too many arguments for delete method.");
762767
}
763768
hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
764769
if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
765770
hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName),
766771
SERVICE_ALL_ACCESS);
@@ -825,11 +830,11 @@
825830
826831
verify_all_options();
827832
if( g.argc==4 ){
828833
zSvcName = g.argv[3];
829834
}else if( g.argc>4 ){
830
- fossil_fatal("to much arguments for show method.");
835
+ fossil_fatal("too many arguments for show method.");
831836
}
832837
hScm = OpenSCManagerW(NULL, NULL, GENERIC_READ);
833838
if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
834839
hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), GENERIC_READ);
835840
if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
@@ -907,11 +912,11 @@
907912
908913
verify_all_options();
909914
if( g.argc==4 ){
910915
zSvcName = g.argv[3];
911916
}else if( g.argc>4 ){
912
- fossil_fatal("to much arguments for start method.");
917
+ fossil_fatal("too many arguments for start method.");
913918
}
914919
hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
915920
if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
916921
hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName),
917922
SERVICE_ALL_ACCESS);
@@ -944,11 +949,11 @@
944949
945950
verify_all_options();
946951
if( g.argc==4 ){
947952
zSvcName = g.argv[3];
948953
}else if( g.argc>4 ){
949
- fossil_fatal("to much arguments for stop method.");
954
+ fossil_fatal("too many arguments for stop method.");
950955
}
951956
hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
952957
if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
953958
hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName),
954959
SERVICE_ALL_ACCESS);
955960
--- src/winhttp.c
+++ src/winhttp.c
@@ -682,15 +682,20 @@
682
683 verify_all_options();
684 if( g.argc==4 ){
685 zSvcName = g.argv[3];
686 }else if( g.argc>4 ){
687 fossil_fatal("to much arguments for create method.");
688 }
689 /* Process service creation specific options. */
690 if( !zDisplay ){
691 zDisplay = zSvcName;
 
 
 
 
 
692 }
693 if( zStart ){
694 if( strncmp(zStart, "auto", strlen(zStart))==0 ){
695 dwStartType = SERVICE_AUTO_START;
696 }else if( strncmp(zStart, "manual", strlen(zStart))==0 ){
@@ -736,11 +741,11 @@
736 SERVICE_ERROR_NORMAL, /* Error control */
737 fossil_utf8_to_unicode(blob_str(&binPath)), /* Binary path */
738 NULL, /* Load ordering group */
739 NULL, /* Tag value */
740 NULL, /* Service dependencies */
741 fossil_utf8_to_unicode(zUsername), /* Service account */
742 fossil_utf8_to_unicode(zPassword) /* Account password */
743 );
744 if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
745 /* Set the service description. */
746 ChangeServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr);
@@ -756,11 +761,11 @@
756
757 verify_all_options();
758 if( g.argc==4 ){
759 zSvcName = g.argv[3];
760 }else if( g.argc>4 ){
761 fossil_fatal("to much arguments for delete method.");
762 }
763 hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
764 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
765 hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName),
766 SERVICE_ALL_ACCESS);
@@ -825,11 +830,11 @@
825
826 verify_all_options();
827 if( g.argc==4 ){
828 zSvcName = g.argv[3];
829 }else if( g.argc>4 ){
830 fossil_fatal("to much arguments for show method.");
831 }
832 hScm = OpenSCManagerW(NULL, NULL, GENERIC_READ);
833 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
834 hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), GENERIC_READ);
835 if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
@@ -907,11 +912,11 @@
907
908 verify_all_options();
909 if( g.argc==4 ){
910 zSvcName = g.argv[3];
911 }else if( g.argc>4 ){
912 fossil_fatal("to much arguments for start method.");
913 }
914 hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
915 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
916 hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName),
917 SERVICE_ALL_ACCESS);
@@ -944,11 +949,11 @@
944
945 verify_all_options();
946 if( g.argc==4 ){
947 zSvcName = g.argv[3];
948 }else if( g.argc>4 ){
949 fossil_fatal("to much arguments for stop method.");
950 }
951 hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
952 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
953 hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName),
954 SERVICE_ALL_ACCESS);
955
--- src/winhttp.c
+++ src/winhttp.c
@@ -682,15 +682,20 @@
682
683 verify_all_options();
684 if( g.argc==4 ){
685 zSvcName = g.argv[3];
686 }else if( g.argc>4 ){
687 fossil_fatal("too many arguments for create method.");
688 }
689 /* Process service creation specific options. */
690 if( !zDisplay ){
691 zDisplay = zSvcName;
692 }
693 /* Per MSDN, the password parameter cannot be NULL. Must use empty
694 ** string instead (i.e. in the call to CreateServiceW). */
695 if( !zPassword ){
696 zPassword = "";
697 }
698 if( zStart ){
699 if( strncmp(zStart, "auto", strlen(zStart))==0 ){
700 dwStartType = SERVICE_AUTO_START;
701 }else if( strncmp(zStart, "manual", strlen(zStart))==0 ){
@@ -736,11 +741,11 @@
741 SERVICE_ERROR_NORMAL, /* Error control */
742 fossil_utf8_to_unicode(blob_str(&binPath)), /* Binary path */
743 NULL, /* Load ordering group */
744 NULL, /* Tag value */
745 NULL, /* Service dependencies */
746 zUsername ? fossil_utf8_to_unicode(zUsername) : 0, /* Account */
747 fossil_utf8_to_unicode(zPassword) /* Account password */
748 );
749 if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
750 /* Set the service description. */
751 ChangeServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr);
@@ -756,11 +761,11 @@
761
762 verify_all_options();
763 if( g.argc==4 ){
764 zSvcName = g.argv[3];
765 }else if( g.argc>4 ){
766 fossil_fatal("too many arguments for delete method.");
767 }
768 hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
769 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
770 hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName),
771 SERVICE_ALL_ACCESS);
@@ -825,11 +830,11 @@
830
831 verify_all_options();
832 if( g.argc==4 ){
833 zSvcName = g.argv[3];
834 }else if( g.argc>4 ){
835 fossil_fatal("too many arguments for show method.");
836 }
837 hScm = OpenSCManagerW(NULL, NULL, GENERIC_READ);
838 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
839 hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), GENERIC_READ);
840 if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
@@ -907,11 +912,11 @@
912
913 verify_all_options();
914 if( g.argc==4 ){
915 zSvcName = g.argv[3];
916 }else if( g.argc>4 ){
917 fossil_fatal("too many arguments for start method.");
918 }
919 hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
920 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
921 hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName),
922 SERVICE_ALL_ACCESS);
@@ -944,11 +949,11 @@
949
950 verify_all_options();
951 if( g.argc==4 ){
952 zSvcName = g.argv[3];
953 }else if( g.argc>4 ){
954 fossil_fatal("too many arguments for stop method.");
955 }
956 hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
957 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
958 hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName),
959 SERVICE_ALL_ACCESS);
960
+13 -1
--- src/wysiwyg.c
+++ src/wysiwyg.c
@@ -251,11 +251,23 @@
251251
@ }
252252
@
253253
@ /* Run the editing command if in WYSIWYG mode */
254254
@ function formatDoc(sCmd, sValue) {
255255
@ if (isWysiwyg()){
256
- @ document.execCommand("styleWithCSS", false, false);
256
+ @ try {
257
+ @ // First, try the W3C draft standard way, which has
258
+ @ // been working on all non-IE browsers for a while.
259
+ @ // It is also supported by IE11 and higher.
260
+ @ document.execCommand("styleWithCSS", false, false);
261
+ @ } catch (e) {
262
+ @ try {
263
+ @ // For IE9 or IE10, this should work.
264
+ @ document.execCommand("useCSS", 0, true);
265
+ @ } catch (e) {
266
+ @ // Ok, that apparently did not work, do nothing.
267
+ @ }
268
+ @ }
257269
@ document.execCommand(sCmd, false, sValue);
258270
@ oDoc.focus();
259271
@ }
260272
@ }
261273
@
262274
--- src/wysiwyg.c
+++ src/wysiwyg.c
@@ -251,11 +251,23 @@
251 @ }
252 @
253 @ /* Run the editing command if in WYSIWYG mode */
254 @ function formatDoc(sCmd, sValue) {
255 @ if (isWysiwyg()){
256 @ document.execCommand("styleWithCSS", false, false);
 
 
 
 
 
 
 
 
 
 
 
 
257 @ document.execCommand(sCmd, false, sValue);
258 @ oDoc.focus();
259 @ }
260 @ }
261 @
262
--- src/wysiwyg.c
+++ src/wysiwyg.c
@@ -251,11 +251,23 @@
251 @ }
252 @
253 @ /* Run the editing command if in WYSIWYG mode */
254 @ function formatDoc(sCmd, sValue) {
255 @ if (isWysiwyg()){
256 @ try {
257 @ // First, try the W3C draft standard way, which has
258 @ // been working on all non-IE browsers for a while.
259 @ // It is also supported by IE11 and higher.
260 @ document.execCommand("styleWithCSS", false, false);
261 @ } catch (e) {
262 @ try {
263 @ // For IE9 or IE10, this should work.
264 @ document.execCommand("useCSS", 0, true);
265 @ } catch (e) {
266 @ // Ok, that apparently did not work, do nothing.
267 @ }
268 @ }
269 @ document.execCommand(sCmd, false, sValue);
270 @ oDoc.focus();
271 @ }
272 @ }
273 @
274
+21 -7
--- src/zip.c
+++ src/zip.c
@@ -393,10 +393,14 @@
393393
int rid;
394394
Blob zip;
395395
const char *zName;
396396
zName = find_option("name", 0, 1);
397397
db_find_and_open_repository(0, 0);
398
+
399
+ /* We should be done with options.. */
400
+ verify_all_options();
401
+
398402
if( g.argc!=4 ){
399403
usage("VERSION OUTPUTFILE");
400404
}
401405
rid = name_to_typed_rid(g.argv[2],"ci");
402406
if( zName==0 ){
@@ -421,15 +425,17 @@
421425
** Generate a ZIP archive for the baseline.
422426
** Return that ZIP archive as the HTTP reply content.
423427
**
424428
** Optional URL Parameters:
425429
**
426
-** - name=base name of the output file. Defaults to
427
-** something project/version-specific.
430
+** - name=NAME[.zip] is the name of the output file. Defaults to
431
+** something project/version-specific. The base part of the
432
+** name, up to the last dot, is used as the top-most directory
433
+** name in the output file.
428434
**
429435
** - uuid=the version to zip (may be a tag/branch name).
430
-** Defaults to trunk.
436
+** Defaults to "trunk".
431437
**
432438
*/
433439
void baseline_zip_page(void){
434440
int rid;
435441
char *zName, *zRid;
@@ -442,14 +448,22 @@
442448
load_control();
443449
zName = mprintf("%s", PD("name",""));
444450
nName = strlen(zName);
445451
zRid = mprintf("%s", PD("uuid","trunk"));
446452
nRid = strlen(zRid);
447
- for(nName=strlen(zName)-1; nName>5; nName--){
448
- if( zName[nName]=='.' ){
449
- zName[nName] = 0;
450
- break;
453
+ if( nName>4 && fossil_strcmp(&zName[nName-4], ".zip")==0 ){
454
+ /* Special case: Remove the ".zip" suffix. */
455
+ nName -= 4;
456
+ zName[nName] = 0;
457
+ }else{
458
+ /* If the file suffix is not ".zip" then just remove the
459
+ ** suffix up to and including the last "." */
460
+ for(nName=strlen(zName)-1; nName>5; nName--){
461
+ if( zName[nName]=='.' ){
462
+ zName[nName] = 0;
463
+ break;
464
+ }
451465
}
452466
}
453467
rid = name_to_typed_rid(nRid?zRid:zName,"ci");
454468
if( rid==0 ){
455469
@ Not found
456470
--- src/zip.c
+++ src/zip.c
@@ -393,10 +393,14 @@
393 int rid;
394 Blob zip;
395 const char *zName;
396 zName = find_option("name", 0, 1);
397 db_find_and_open_repository(0, 0);
 
 
 
 
398 if( g.argc!=4 ){
399 usage("VERSION OUTPUTFILE");
400 }
401 rid = name_to_typed_rid(g.argv[2],"ci");
402 if( zName==0 ){
@@ -421,15 +425,17 @@
421 ** Generate a ZIP archive for the baseline.
422 ** Return that ZIP archive as the HTTP reply content.
423 **
424 ** Optional URL Parameters:
425 **
426 ** - name=base name of the output file. Defaults to
427 ** something project/version-specific.
 
 
428 **
429 ** - uuid=the version to zip (may be a tag/branch name).
430 ** Defaults to trunk.
431 **
432 */
433 void baseline_zip_page(void){
434 int rid;
435 char *zName, *zRid;
@@ -442,14 +448,22 @@
442 load_control();
443 zName = mprintf("%s", PD("name",""));
444 nName = strlen(zName);
445 zRid = mprintf("%s", PD("uuid","trunk"));
446 nRid = strlen(zRid);
447 for(nName=strlen(zName)-1; nName>5; nName--){
448 if( zName[nName]=='.' ){
449 zName[nName] = 0;
450 break;
 
 
 
 
 
 
 
 
451 }
452 }
453 rid = name_to_typed_rid(nRid?zRid:zName,"ci");
454 if( rid==0 ){
455 @ Not found
456
--- src/zip.c
+++ src/zip.c
@@ -393,10 +393,14 @@
393 int rid;
394 Blob zip;
395 const char *zName;
396 zName = find_option("name", 0, 1);
397 db_find_and_open_repository(0, 0);
398
399 /* We should be done with options.. */
400 verify_all_options();
401
402 if( g.argc!=4 ){
403 usage("VERSION OUTPUTFILE");
404 }
405 rid = name_to_typed_rid(g.argv[2],"ci");
406 if( zName==0 ){
@@ -421,15 +425,17 @@
425 ** Generate a ZIP archive for the baseline.
426 ** Return that ZIP archive as the HTTP reply content.
427 **
428 ** Optional URL Parameters:
429 **
430 ** - name=NAME[.zip] is the name of the output file. Defaults to
431 ** something project/version-specific. The base part of the
432 ** name, up to the last dot, is used as the top-most directory
433 ** name in the output file.
434 **
435 ** - uuid=the version to zip (may be a tag/branch name).
436 ** Defaults to "trunk".
437 **
438 */
439 void baseline_zip_page(void){
440 int rid;
441 char *zName, *zRid;
@@ -442,14 +448,22 @@
448 load_control();
449 zName = mprintf("%s", PD("name",""));
450 nName = strlen(zName);
451 zRid = mprintf("%s", PD("uuid","trunk"));
452 nRid = strlen(zRid);
453 if( nName>4 && fossil_strcmp(&zName[nName-4], ".zip")==0 ){
454 /* Special case: Remove the ".zip" suffix. */
455 nName -= 4;
456 zName[nName] = 0;
457 }else{
458 /* If the file suffix is not ".zip" then just remove the
459 ** suffix up to and including the last "." */
460 for(nName=strlen(zName)-1; nName>5; nName--){
461 if( zName[nName]=='.' ){
462 zName[nName] = 0;
463 break;
464 }
465 }
466 }
467 rid = name_to_typed_rid(nRid?zRid:zName,"ci");
468 if( rid==0 ){
469 @ Not found
470
--- test/comment.test
+++ test/comment.test
@@ -227,12 +227,92 @@
227227
test comment-42 {$RESULT eq "*TEST* one two three four five six seven eight nine ten\n eleven twelve\n(2 lines output)"}
228228
229229
###############################################################################
230230
231231
set orig "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\\nxxxxxxx."
232
-fossil test-comment-format --width 73 --decode --origbreak "" $orig $orig
232
+fossil test-comment-format --width 73 --decode --origbreak "" $orig
233233
test comment-43 {$RESULT eq "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\nxxxxxxx.\n(5 lines output)"}
234234
235235
###############################################################################
236236
237
+fossil test-comment-format --width 73 --decode --origbreak "" $orig $orig
238
+test comment-44 {$RESULT eq "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\nxxxxxxx.\n(5 lines output)"}
239
+
240
+###############################################################################
241
+
237242
fossil test-comment-format --width 73 --decode --origbreak "" "00:00:00 \[0000000000\] *CURRENT* $orig" $orig
238
-test comment-44 {$RESULT eq "00:00:00 \[0000000000\] *CURRENT* \nxxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\nxxxxxxx.\n(6 lines output)"}
243
+test comment-45 {$RESULT eq "00:00:00 \[0000000000\] *CURRENT* \nxxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\nxxxxxxx.\n(6 lines output)"}
244
+
245
+###############################################################################
246
+
247
+fossil test-comment-format --width 82 --indent 9 --decode --origbreak " " $orig
248
+test comment-46 {$RESULT eq " xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n xxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\n xxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\n xxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\n xxxxxxx.\n(5 lines output)"}
249
+
250
+###############################################################################
251
+
252
+fossil test-comment-format --width 82 --indent 9 --decode --origbreak " " $orig $orig
253
+test comment-47 {$RESULT eq " xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n xxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\n xxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\n xxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\n xxxxxxx.\n(5 lines output)"}
254
+
255
+###############################################################################
256
+
257
+fossil test-comment-format --width 82 --indent 9 --decode --origbreak "00:00:00 " "\[0000000000\] *CURRENT* $orig" $orig
258
+test comment-48 {$RESULT eq "00:00:00 \[0000000000\] *CURRENT* \n xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n xxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\n xxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\n xxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\n xxxxxxx.\n(6 lines output)"}
259
+
260
+###############################################################################
261
+
262
+fossil test-comment-format --width 72 --decode --trimspace --origbreak "" $orig
263
+test comment-49 {$RESULT eq "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\nxxxxxxx.\n(5 lines output)"}
264
+
265
+###############################################################################
266
+
267
+fossil test-comment-format --width 72 --decode --trimspace --origbreak "" $orig $orig
268
+test comment-50 {$RESULT eq "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\nxxxxxxx.\n(5 lines output)"}
269
+
270
+###############################################################################
271
+
272
+fossil test-comment-format --width 72 --decode --trimspace --origbreak "" "00:00:00 \[0000000000\] *CURRENT* $orig" $orig
273
+test comment-51 {$RESULT eq "00:00:00 \[0000000000\] *CURRENT* \nxxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\nxxxxxxx.\n(6 lines output)"}
274
+
275
+###############################################################################
276
+
277
+fossil test-comment-format --width 81 --indent 9 --decode --trimspace --origbreak " " $orig
278
+test comment-52 {$RESULT eq " xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n xxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\n xxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\n xxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\n xxxxxxx.\n(5 lines output)"}
279
+
280
+###############################################################################
281
+
282
+fossil test-comment-format --width 81 --indent 9 --decode --trimspace --origbreak " " $orig $orig
283
+test comment-53 {$RESULT eq " xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n xxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\n xxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\n xxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\n xxxxxxx.\n(5 lines output)"}
284
+
285
+###############################################################################
286
+
287
+fossil test-comment-format --width 81 --indent 9 --decode --trimspace --origbreak "00:00:00 " "\[0000000000\] *CURRENT* $orig" $orig
288
+test comment-54 {$RESULT eq "00:00:00 \[0000000000\] *CURRENT* \n xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n xxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\n xxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\n xxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\n xxxxxxx.\n(6 lines output)"}
289
+
290
+###############################################################################
291
+
292
+fossil test-comment-format --width 72 --decode --trimcrlf --origbreak "" $orig
293
+test comment-55 {$RESULT eq "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\nxxxxxxx.\n(5 lines output)"}
294
+
295
+###############################################################################
296
+
297
+fossil test-comment-format --width 72 --decode --trimcrlf --origbreak "" $orig $orig
298
+test comment-56 {$RESULT eq "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\nxxxxxxx.\n(5 lines output)"}
299
+
300
+###############################################################################
301
+
302
+fossil test-comment-format --width 72 --decode --trimcrlf --origbreak "" "00:00:00 \[0000000000\] *CURRENT* $orig" $orig
303
+test comment-57 {$RESULT eq "00:00:00 \[0000000000\] *CURRENT* \nxxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\nxxxxxxx.\n(6 lines output)"}
304
+
305
+###############################################################################
306
+
307
+fossil test-comment-format --width 81 --indent 9 --decode --trimcrlf --origbreak " " $orig
308
+test comment-58 {$RESULT eq " xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n xxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\n xxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\n xxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\n xxxxxxx.\n(5 lines output)"}
309
+
310
+###############################################################################
311
+
312
+fossil test-comment-format --width 81 --indent 9 --decode --trimcrlf --origbreak " " $orig $orig
313
+test comment-59 {$RESULT eq " xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n xxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\n xxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\n xxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\n xxxxxxx.\n(5 lines output)"}
314
+
315
+###############################################################################
316
+
317
+fossil test-comment-format --width 81 --indent 9 --decode --trimcrlf --origbreak "00:00:00 " "\[0000000000\] *CURRENT* $orig" $orig
318
+test comment-60 {$RESULT eq "00:00:00 \[0000000000\] *CURRENT* \n xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n xxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\n xxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\n xxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\n xxxxxxx.\n(6 lines output)"}
239319
--- test/comment.test
+++ test/comment.test
@@ -227,12 +227,92 @@
227 test comment-42 {$RESULT eq "*TEST* one two three four five six seven eight nine ten\n eleven twelve\n(2 lines output)"}
228
229 ###############################################################################
230
231 set orig "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\\nxxxxxxx."
232 fossil test-comment-format --width 73 --decode --origbreak "" $orig $orig
233 test comment-43 {$RESULT eq "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\nxxxxxxx.\n(5 lines output)"}
234
235 ###############################################################################
236
 
 
 
 
 
237 fossil test-comment-format --width 73 --decode --origbreak "" "00:00:00 \[0000000000\] *CURRENT* $orig" $orig
238 test comment-44 {$RESULT eq "00:00:00 \[0000000000\] *CURRENT* \nxxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\nxxxxxxx.\n(6 lines output)"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
239
--- test/comment.test
+++ test/comment.test
@@ -227,12 +227,92 @@
227 test comment-42 {$RESULT eq "*TEST* one two three four five six seven eight nine ten\n eleven twelve\n(2 lines output)"}
228
229 ###############################################################################
230
231 set orig "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\\nxxxxxxx."
232 fossil test-comment-format --width 73 --decode --origbreak "" $orig
233 test comment-43 {$RESULT eq "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\nxxxxxxx.\n(5 lines output)"}
234
235 ###############################################################################
236
237 fossil test-comment-format --width 73 --decode --origbreak "" $orig $orig
238 test comment-44 {$RESULT eq "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\nxxxxxxx.\n(5 lines output)"}
239
240 ###############################################################################
241
242 fossil test-comment-format --width 73 --decode --origbreak "" "00:00:00 \[0000000000\] *CURRENT* $orig" $orig
243 test comment-45 {$RESULT eq "00:00:00 \[0000000000\] *CURRENT* \nxxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\nxxxxxxx.\n(6 lines output)"}
244
245 ###############################################################################
246
247 fossil test-comment-format --width 82 --indent 9 --decode --origbreak " " $orig
248 test comment-46 {$RESULT eq " xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n xxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\n xxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\n xxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\n xxxxxxx.\n(5 lines output)"}
249
250 ###############################################################################
251
252 fossil test-comment-format --width 82 --indent 9 --decode --origbreak " " $orig $orig
253 test comment-47 {$RESULT eq " xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n xxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\n xxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\n xxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\n xxxxxxx.\n(5 lines output)"}
254
255 ###############################################################################
256
257 fossil test-comment-format --width 82 --indent 9 --decode --origbreak "00:00:00 " "\[0000000000\] *CURRENT* $orig" $orig
258 test comment-48 {$RESULT eq "00:00:00 \[0000000000\] *CURRENT* \n xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n xxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\n xxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\n xxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\n xxxxxxx.\n(6 lines output)"}
259
260 ###############################################################################
261
262 fossil test-comment-format --width 72 --decode --trimspace --origbreak "" $orig
263 test comment-49 {$RESULT eq "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\nxxxxxxx.\n(5 lines output)"}
264
265 ###############################################################################
266
267 fossil test-comment-format --width 72 --decode --trimspace --origbreak "" $orig $orig
268 test comment-50 {$RESULT eq "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\nxxxxxxx.\n(5 lines output)"}
269
270 ###############################################################################
271
272 fossil test-comment-format --width 72 --decode --trimspace --origbreak "" "00:00:00 \[0000000000\] *CURRENT* $orig" $orig
273 test comment-51 {$RESULT eq "00:00:00 \[0000000000\] *CURRENT* \nxxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\nxxxxxxx.\n(6 lines output)"}
274
275 ###############################################################################
276
277 fossil test-comment-format --width 81 --indent 9 --decode --trimspace --origbreak " " $orig
278 test comment-52 {$RESULT eq " xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n xxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\n xxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\n xxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\n xxxxxxx.\n(5 lines output)"}
279
280 ###############################################################################
281
282 fossil test-comment-format --width 81 --indent 9 --decode --trimspace --origbreak " " $orig $orig
283 test comment-53 {$RESULT eq " xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n xxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\n xxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\n xxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\n xxxxxxx.\n(5 lines output)"}
284
285 ###############################################################################
286
287 fossil test-comment-format --width 81 --indent 9 --decode --trimspace --origbreak "00:00:00 " "\[0000000000\] *CURRENT* $orig" $orig
288 test comment-54 {$RESULT eq "00:00:00 \[0000000000\] *CURRENT* \n xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n xxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\n xxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\n xxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\n xxxxxxx.\n(6 lines output)"}
289
290 ###############################################################################
291
292 fossil test-comment-format --width 72 --decode --trimcrlf --origbreak "" $orig
293 test comment-55 {$RESULT eq "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\nxxxxxxx.\n(5 lines output)"}
294
295 ###############################################################################
296
297 fossil test-comment-format --width 72 --decode --trimcrlf --origbreak "" $orig $orig
298 test comment-56 {$RESULT eq "xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\nxxxxxxx.\n(5 lines output)"}
299
300 ###############################################################################
301
302 fossil test-comment-format --width 72 --decode --trimcrlf --origbreak "" "00:00:00 \[0000000000\] *CURRENT* $orig" $orig
303 test comment-57 {$RESULT eq "00:00:00 \[0000000000\] *CURRENT* \nxxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\nxxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\nxxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\nxxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\nxxxxxxx.\n(6 lines output)"}
304
305 ###############################################################################
306
307 fossil test-comment-format --width 81 --indent 9 --decode --trimcrlf --origbreak " " $orig
308 test comment-58 {$RESULT eq " xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n xxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\n xxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\n xxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\n xxxxxxx.\n(5 lines output)"}
309
310 ###############################################################################
311
312 fossil test-comment-format --width 81 --indent 9 --decode --trimcrlf --origbreak " " $orig $orig
313 test comment-59 {$RESULT eq " xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n xxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\n xxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\n xxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\n xxxxxxx.\n(5 lines output)"}
314
315 ###############################################################################
316
317 fossil test-comment-format --width 81 --indent 9 --decode --trimcrlf --origbreak "00:00:00 " "\[0000000000\] *CURRENT* $orig" $orig
318 test comment-60 {$RESULT eq "00:00:00 \[0000000000\] *CURRENT* \n xxxx xx xxxxxxx xxxx xxxxxx xxxxxxx, xxxxxxx, x xxxx xxxxxx xx xxxx xxxx\n xxxxxxx xxxxx xxxx xxxx xx xxxxxxx xxxxxxx (xxxxxx xxxxxxxxx x xxxxx).\n xxx'x xxx xxx xx xxxxx xxxx xxx xxx --xxxxxxxxxxx xxxxxx xx xx xxxx. x\n xxxxx x xxxxxx xxxx xxxx xxxx xxxx xxxx x xxxxx xx xxx x xxxxxxxx\n xxxxxxx.\n(6 lines output)"}
319
--- test/release-checklist.wiki
+++ test/release-checklist.wiki
@@ -17,13 +17,17 @@
1717
1818
<li><p>
1919
Click on each of the links in in the
2020
[./diff-test-1.wiki] document and verify that all diffs are
2121
rendered correctly.
22
-
2322
<li><p>
2423
Click on the following link to verify that it works: [./test-page%2b%2b.wiki | ./test-page++.wiki]
24
+(NB: Many web servers automatically block
25
+or rewrite URLs that contain "+" characters, even when those "+"
26
+characters are encoded as "%2B". On such web servers, the URL
27
+above will not work. This test is only guaranteed to work
28
+when running "fossil ui".)
2529
2630
<li><p>
2731
Verify correct name-change tracking behavior (no net changes) for:
2832
<blockquote><b>
2933
fossil test-name-changes --debug b120bc8b262ac 374920b20944b
3034
--- test/release-checklist.wiki
+++ test/release-checklist.wiki
@@ -17,13 +17,17 @@
17
18 <li><p>
19 Click on each of the links in in the
20 [./diff-test-1.wiki] document and verify that all diffs are
21 rendered correctly.
22
23 <li><p>
24 Click on the following link to verify that it works: [./test-page%2b%2b.wiki | ./test-page++.wiki]
 
 
 
 
 
25
26 <li><p>
27 Verify correct name-change tracking behavior (no net changes) for:
28 <blockquote><b>
29 fossil test-name-changes --debug b120bc8b262ac 374920b20944b
30
--- test/release-checklist.wiki
+++ test/release-checklist.wiki
@@ -17,13 +17,17 @@
17
18 <li><p>
19 Click on each of the links in in the
20 [./diff-test-1.wiki] document and verify that all diffs are
21 rendered correctly.
 
22 <li><p>
23 Click on the following link to verify that it works: [./test-page%2b%2b.wiki | ./test-page++.wiki]
24 (NB: Many web servers automatically block
25 or rewrite URLs that contain "+" characters, even when those "+"
26 characters are encoded as "%2B". On such web servers, the URL
27 above will not work. This test is only guaranteed to work
28 when running "fossil ui".)
29
30 <li><p>
31 Verify correct name-change tracking behavior (no net changes) for:
32 <blockquote><b>
33 fossil test-name-changes --debug b120bc8b262ac 374920b20944b
34
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -83,11 +83,11 @@
8383
8484
# define the sqlite files, which need special flags on compile
8585
SQLITESRC=sqlite3.c
8686
ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf))
8787
SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj))
88
-SQLITEDEFINES=-DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS
88
+SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_WIN32_NO_ANSI
8989
9090
# define the sqlite shell files, which need special flags on compile
9191
SQLITESHELLSRC=shell.c
9292
ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf))
9393
SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
9494
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -83,11 +83,11 @@
83
84 # define the sqlite files, which need special flags on compile
85 SQLITESRC=sqlite3.c
86 ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf))
87 SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj))
88 SQLITEDEFINES=-DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS
89
90 # define the sqlite shell files, which need special flags on compile
91 SQLITESHELLSRC=shell.c
92 ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf))
93 SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
94
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -83,11 +83,11 @@
83
84 # define the sqlite files, which need special flags on compile
85 SQLITESRC=sqlite3.c
86 ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf))
87 SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj))
88 SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_WIN32_NO_ANSI
89
90 # define the sqlite shell files, which need special flags on compile
91 SQLITESHELLSRC=shell.c
92 ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf))
93 SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
94
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -24,11 +24,11 @@
2424
CFLAGS = -o
2525
BCC = $(DMDIR)\bin\dmc $(CFLAGS)
2626
TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
2727
LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32
2828
29
-SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS
29
+SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS
3030
3131
SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
3232
3333
SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
3434
3535
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -24,11 +24,11 @@
24 CFLAGS = -o
25 BCC = $(DMDIR)\bin\dmc $(CFLAGS)
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_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS
30
31 SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
32
33 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
34
35
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -24,11 +24,11 @@
24 CFLAGS = -o
25 BCC = $(DMDIR)\bin\dmc $(CFLAGS)
26 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
27 LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32
28
29 SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS
30
31 SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
32
33 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
34
35
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -92,12 +92,12 @@
9292
#### The directories where the OpenSSL include and library files are located.
9393
# The recommended usage here is to use the Sysinternals junction tool
9494
# to create a hard link between an "openssl-1.x" sub-directory of the
9595
# Fossil source code directory and the target OpenSSL source directory.
9696
#
97
-OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1h/include
98
-OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1h
97
+OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1i/include
98
+OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1i
9999
100100
#### Either the directory where the Tcl library is installed or the Tcl
101101
# source code directory resides (depending on the value of the macro
102102
# FOSSIL_TCL_SOURCE). If this points to the Tcl install directory,
103103
# this directory must have "include" and "lib" sub-directories. If
@@ -1765,16 +1765,18 @@
17651765
$(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h
17661766
$(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
17671767
17681768
$(OBJDIR)/zip.h: $(OBJDIR)/headers
17691769
1770
-SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 \
1770
+SQLITE_OPTIONS = -DNDEBUG=1 \
1771
+ -DSQLITE_OMIT_LOAD_EXTENSION=1 \
17711772
-DSQLITE_ENABLE_LOCKING_STYLE=0 \
17721773
-DSQLITE_THREADSAFE=0 \
17731774
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
17741775
-DSQLITE_OMIT_DEPRECATED \
17751776
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
1777
+ -DSQLITE_WIN32_NO_ANSI \
17761778
-D_HAVE__MINGW_H \
17771779
-DSQLITE_USE_MALLOC_H \
17781780
-DSQLITE_USE_MSIZE
17791781
17801782
SHELL_OPTIONS = -Dmain=sqlite3_shell \
17811783
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -92,12 +92,12 @@
92 #### The directories where the OpenSSL include and library files are located.
93 # The recommended usage here is to use the Sysinternals junction tool
94 # to create a hard link between an "openssl-1.x" sub-directory of the
95 # Fossil source code directory and the target OpenSSL source directory.
96 #
97 OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1h/include
98 OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1h
99
100 #### Either the directory where the Tcl library is installed or the Tcl
101 # source code directory resides (depending on the value of the macro
102 # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory,
103 # this directory must have "include" and "lib" sub-directories. If
@@ -1765,16 +1765,18 @@
1765 $(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h
1766 $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
1767
1768 $(OBJDIR)/zip.h: $(OBJDIR)/headers
1769
1770 SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 \
 
1771 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
1772 -DSQLITE_THREADSAFE=0 \
1773 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
1774 -DSQLITE_OMIT_DEPRECATED \
1775 -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
 
1776 -D_HAVE__MINGW_H \
1777 -DSQLITE_USE_MALLOC_H \
1778 -DSQLITE_USE_MSIZE
1779
1780 SHELL_OPTIONS = -Dmain=sqlite3_shell \
1781
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -92,12 +92,12 @@
92 #### The directories where the OpenSSL include and library files are located.
93 # The recommended usage here is to use the Sysinternals junction tool
94 # to create a hard link between an "openssl-1.x" sub-directory of the
95 # Fossil source code directory and the target OpenSSL source directory.
96 #
97 OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1i/include
98 OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1i
99
100 #### Either the directory where the Tcl library is installed or the Tcl
101 # source code directory resides (depending on the value of the macro
102 # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory,
103 # this directory must have "include" and "lib" sub-directories. If
@@ -1765,16 +1765,18 @@
1765 $(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h
1766 $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
1767
1768 $(OBJDIR)/zip.h: $(OBJDIR)/headers
1769
1770 SQLITE_OPTIONS = -DNDEBUG=1 \
1771 -DSQLITE_OMIT_LOAD_EXTENSION=1 \
1772 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
1773 -DSQLITE_THREADSAFE=0 \
1774 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
1775 -DSQLITE_OMIT_DEPRECATED \
1776 -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
1777 -DSQLITE_WIN32_NO_ANSI \
1778 -D_HAVE__MINGW_H \
1779 -DSQLITE_USE_MALLOC_H \
1780 -DSQLITE_USE_MSIZE
1781
1782 SHELL_OPTIONS = -Dmain=sqlite3_shell \
1783
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -92,12 +92,12 @@
9292
#### The directories where the OpenSSL include and library files are located.
9393
# The recommended usage here is to use the Sysinternals junction tool
9494
# to create a hard link between an "openssl-1.x" sub-directory of the
9595
# Fossil source code directory and the target OpenSSL source directory.
9696
#
97
-OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1h/include
98
-OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1h
97
+OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1i/include
98
+OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1i
9999
100100
#### Either the directory where the Tcl library is installed or the Tcl
101101
# source code directory resides (depending on the value of the macro
102102
# FOSSIL_TCL_SOURCE). If this points to the Tcl install directory,
103103
# this directory must have "include" and "lib" sub-directories. If
@@ -1765,16 +1765,18 @@
17651765
$(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h
17661766
$(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
17671767
17681768
$(OBJDIR)/zip.h: $(OBJDIR)/headers
17691769
1770
-SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 \
1770
+SQLITE_OPTIONS = -DNDEBUG=1 \
1771
+ -DSQLITE_OMIT_LOAD_EXTENSION=1 \
17711772
-DSQLITE_ENABLE_LOCKING_STYLE=0 \
17721773
-DSQLITE_THREADSAFE=0 \
17731774
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
17741775
-DSQLITE_OMIT_DEPRECATED \
17751776
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
1777
+ -DSQLITE_WIN32_NO_ANSI \
17761778
-D_HAVE__MINGW_H \
17771779
-DSQLITE_USE_MALLOC_H \
17781780
-DSQLITE_USE_MSIZE
17791781
17801782
SHELL_OPTIONS = -Dmain=sqlite3_shell \
17811783
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -92,12 +92,12 @@
92 #### The directories where the OpenSSL include and library files are located.
93 # The recommended usage here is to use the Sysinternals junction tool
94 # to create a hard link between an "openssl-1.x" sub-directory of the
95 # Fossil source code directory and the target OpenSSL source directory.
96 #
97 OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1h/include
98 OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1h
99
100 #### Either the directory where the Tcl library is installed or the Tcl
101 # source code directory resides (depending on the value of the macro
102 # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory,
103 # this directory must have "include" and "lib" sub-directories. If
@@ -1765,16 +1765,18 @@
1765 $(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h
1766 $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
1767
1768 $(OBJDIR)/zip.h: $(OBJDIR)/headers
1769
1770 SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 \
 
1771 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
1772 -DSQLITE_THREADSAFE=0 \
1773 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
1774 -DSQLITE_OMIT_DEPRECATED \
1775 -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
 
1776 -D_HAVE__MINGW_H \
1777 -DSQLITE_USE_MALLOC_H \
1778 -DSQLITE_USE_MSIZE
1779
1780 SHELL_OPTIONS = -Dmain=sqlite3_shell \
1781
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -92,12 +92,12 @@
92 #### The directories where the OpenSSL include and library files are located.
93 # The recommended usage here is to use the Sysinternals junction tool
94 # to create a hard link between an "openssl-1.x" sub-directory of the
95 # Fossil source code directory and the target OpenSSL source directory.
96 #
97 OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1i/include
98 OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1i
99
100 #### Either the directory where the Tcl library is installed or the Tcl
101 # source code directory resides (depending on the value of the macro
102 # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory,
103 # this directory must have "include" and "lib" sub-directories. If
@@ -1765,16 +1765,18 @@
1765 $(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h
1766 $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
1767
1768 $(OBJDIR)/zip.h: $(OBJDIR)/headers
1769
1770 SQLITE_OPTIONS = -DNDEBUG=1 \
1771 -DSQLITE_OMIT_LOAD_EXTENSION=1 \
1772 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
1773 -DSQLITE_THREADSAFE=0 \
1774 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
1775 -DSQLITE_OMIT_DEPRECATED \
1776 -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
1777 -DSQLITE_WIN32_NO_ANSI \
1778 -D_HAVE__MINGW_H \
1779 -DSQLITE_USE_MALLOC_H \
1780 -DSQLITE_USE_MSIZE
1781
1782 SHELL_OPTIONS = -Dmain=sqlite3_shell \
1783
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -29,12 +29,12 @@
2929
3030
# Uncomment to enable Tcl support
3131
# FOSSIL_ENABLE_TCL = 1
3232
3333
!ifdef FOSSIL_ENABLE_SSL
34
-SSLINCDIR = $(B)\compat\openssl-1.0.1h\include
35
-SSLLIBDIR = $(B)\compat\openssl-1.0.1h\out32
34
+SSLINCDIR = $(B)\compat\openssl-1.0.1i\include
35
+SSLLIBDIR = $(B)\compat\openssl-1.0.1i\out32
3636
SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
3737
!endif
3838
3939
!ifdef FOSSIL_ENABLE_TCL
4040
TCLDIR = $(B)\compat\tcl-8.6
@@ -99,16 +99,18 @@
9999
RCC = $(RCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
100100
TCC = $(TCC) /DUSE_TCL_STUBS=1
101101
RCC = $(RCC) /DUSE_TCL_STUBS=1
102102
!endif
103103
104
-SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 \
104
+SQLITE_OPTIONS = /DNDEBUG=1 \
105
+ /DSQLITE_OMIT_LOAD_EXTENSION=1 \
105106
/DSQLITE_ENABLE_LOCKING_STYLE=0 \
106107
/DSQLITE_THREADSAFE=0 \
107108
/DSQLITE_DEFAULT_FILE_FORMAT=4 \
108109
/DSQLITE_OMIT_DEPRECATED \
109
- /DSQLITE_ENABLE_EXPLAIN_COMMENTS
110
+ /DSQLITE_ENABLE_EXPLAIN_COMMENTS \
111
+ /DSQLITE_WIN32_NO_ANSI
110112
111113
SHELL_OPTIONS = /Dmain=sqlite3_shell \
112114
/DSQLITE_OMIT_LOAD_EXTENSION=1 \
113115
/DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
114116
/DSQLITE_SHELL_DBNAME_PROC=fossil_open \
115117
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -29,12 +29,12 @@
29
30 # Uncomment to enable Tcl support
31 # FOSSIL_ENABLE_TCL = 1
32
33 !ifdef FOSSIL_ENABLE_SSL
34 SSLINCDIR = $(B)\compat\openssl-1.0.1h\include
35 SSLLIBDIR = $(B)\compat\openssl-1.0.1h\out32
36 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
37 !endif
38
39 !ifdef FOSSIL_ENABLE_TCL
40 TCLDIR = $(B)\compat\tcl-8.6
@@ -99,16 +99,18 @@
99 RCC = $(RCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
100 TCC = $(TCC) /DUSE_TCL_STUBS=1
101 RCC = $(RCC) /DUSE_TCL_STUBS=1
102 !endif
103
104 SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 \
 
105 /DSQLITE_ENABLE_LOCKING_STYLE=0 \
106 /DSQLITE_THREADSAFE=0 \
107 /DSQLITE_DEFAULT_FILE_FORMAT=4 \
108 /DSQLITE_OMIT_DEPRECATED \
109 /DSQLITE_ENABLE_EXPLAIN_COMMENTS
 
110
111 SHELL_OPTIONS = /Dmain=sqlite3_shell \
112 /DSQLITE_OMIT_LOAD_EXTENSION=1 \
113 /DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
114 /DSQLITE_SHELL_DBNAME_PROC=fossil_open \
115
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -29,12 +29,12 @@
29
30 # Uncomment to enable Tcl support
31 # FOSSIL_ENABLE_TCL = 1
32
33 !ifdef FOSSIL_ENABLE_SSL
34 SSLINCDIR = $(B)\compat\openssl-1.0.1i\include
35 SSLLIBDIR = $(B)\compat\openssl-1.0.1i\out32
36 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
37 !endif
38
39 !ifdef FOSSIL_ENABLE_TCL
40 TCLDIR = $(B)\compat\tcl-8.6
@@ -99,16 +99,18 @@
99 RCC = $(RCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
100 TCC = $(TCC) /DUSE_TCL_STUBS=1
101 RCC = $(RCC) /DUSE_TCL_STUBS=1
102 !endif
103
104 SQLITE_OPTIONS = /DNDEBUG=1 \
105 /DSQLITE_OMIT_LOAD_EXTENSION=1 \
106 /DSQLITE_ENABLE_LOCKING_STYLE=0 \
107 /DSQLITE_THREADSAFE=0 \
108 /DSQLITE_DEFAULT_FILE_FORMAT=4 \
109 /DSQLITE_OMIT_DEPRECATED \
110 /DSQLITE_ENABLE_EXPLAIN_COMMENTS \
111 /DSQLITE_WIN32_NO_ANSI
112
113 SHELL_OPTIONS = /Dmain=sqlite3_shell \
114 /DSQLITE_OMIT_LOAD_EXTENSION=1 \
115 /DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
116 /DSQLITE_SHELL_DBNAME_PROC=fossil_open \
117
--- win/include/dirent.h
+++ win/include/dirent.h
@@ -20,84 +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.
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
44
- * Defined FILE_ATTRIBUTE_DEVICE for MSVC 6.0.
45
- *
46
- * Version 1.10, Aug 11, 2010, Toni Ronkko
47
- * Added d_type and d_namlen fields to dirent structure. The former is
48
- * especially useful for determining whether directory entry represents a
49
- * file or a directory. For more information, see
50
- * http://www.delorie.com/gnu/docs/glibc/libc_270.html
51
- *
52
- * Improved conformance to the standards. For example, errno is now set
53
- * properly on failure and assert() is never used. Thanks to Peter Brockam
54
- * for suggestions.
55
- *
56
- * Fixed a bug in rewinddir(): when using relative directory names, change
57
- * of working directory no longer causes rewinddir() to fail.
58
- *
59
- * Version 1.9, Dec 15, 2009, John Cunningham
60
- * Added rewinddir member function
61
- *
62
- * Version 1.8, Jan 18, 2008, Toni Ronkko
63
- * Using FindFirstFileA and WIN32_FIND_DATAA to avoid converting string
64
- * between multi-byte and unicode representations. This makes the
65
- * code simpler and also allows the code to be compiled under MingW. Thanks
66
- * to Azriel Fasten for the suggestion.
67
- *
68
- * Mar 4, 2007, Toni Ronkko
69
- * Bug fix: due to the strncpy_s() function this file only compiled in
70
- * Visual Studio 2005. Using the new string functions only when the
71
- * compiler version allows.
72
- *
73
- * Nov 2, 2006, Toni Ronkko
74
- * Major update: removed support for Watcom C, MS-DOS and Turbo C to
75
- * simplify the file, updated the code to compile cleanly on Visual
76
- * Studio 2005 with both unicode and multi-byte character strings,
77
- * removed rewinddir() as it had a bug.
78
- *
79
- * Aug 20, 2006, Toni Ronkko
80
- * Removed all remarks about MSVC 1.0, which is antiqued now. Simplified
81
- * comments by removing SGML tags.
82
- *
83
- * May 14 2002, Toni Ronkko
84
- * Embedded the function definitions directly to the header so that no
85
- * source modules need to be included in the Visual Studio project. Removed
86
- * all the dependencies to other projects so that this header file can be
87
- * used independently.
88
- *
89
- * May 28 1998, Toni Ronkko
90
- * First version.
91
- *****************************************************************************/
25
+ * $Id: dirent.h,v 1.20 2014/03/19 17:52:23 tronkko Exp $
26
+ */
9227
#ifndef DIRENT_H
9328
#define DIRENT_H
9429
95
-#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && defined(_M_IX86)
30
+/*
31
+ * Define architecture flags so we don't need to include windows.h.
32
+ * Avoiding windows.h makes it simpler to use windows sockets in conjunction
33
+ * with dirent.h.
34
+ */
35
+#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86)
9636
# define _X86_
9737
#endif
98
-#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && defined(_M_AMD64)
38
+#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_AMD64)
9939
#define _AMD64_
10040
#endif
10141
10242
#include <stdio.h>
10343
#include <stdarg.h>
@@ -213,11 +153,11 @@
213153
214154
/* Return the exact length of d_namlen without zero terminator */
215155
#define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
216156
217157
/* Return number of bytes needed to store d_namlen */
218
-#define _D_ALLOC_NAMLEN(p) (PATH_MAX + 1)
158
+#define _D_ALLOC_NAMLEN(p) (PATH_MAX)
219159
220160
221161
#ifdef __cplusplus
222162
extern "C" {
223163
#endif
@@ -227,11 +167,11 @@
227167
struct _wdirent {
228168
long d_ino; /* Always zero */
229169
unsigned short d_reclen; /* Structure size */
230170
size_t d_namlen; /* Length of name without \0 */
231171
int d_type; /* File type */
232
- wchar_t d_name[PATH_MAX + 1]; /* File name */
172
+ wchar_t d_name[PATH_MAX]; /* File name */
233173
};
234174
typedef struct _wdirent _wdirent;
235175
236176
struct _WDIR {
237177
struct _wdirent ent; /* Current directory entry */
@@ -261,11 +201,11 @@
261201
struct dirent {
262202
long d_ino; /* Always zero */
263203
unsigned short d_reclen; /* Structure size */
264204
size_t d_namlen; /* Length of name without \0 */
265205
int d_type; /* File type */
266
- char d_name[PATH_MAX + 1]; /* File name */
206
+ char d_name[PATH_MAX]; /* File name */
267207
};
268208
typedef struct dirent dirent;
269209
270210
struct DIR {
271211
struct dirent ent;
@@ -423,11 +363,11 @@
423363
* Copy file name as wide-character string. If the file name is too
424364
* long to fit in to the destination buffer, then truncate file name
425365
* to PATH_MAX characters and zero-terminate the buffer.
426366
*/
427367
n = 0;
428
- while (n < PATH_MAX && datap->cFileName[n] != 0) {
368
+ while (n + 1 < PATH_MAX && datap->cFileName[n] != 0) {
429369
entp->d_name[n] = datap->cFileName[n];
430370
n++;
431371
}
432372
dirp->ent.d_name[n] = 0;
433373
@@ -592,16 +532,15 @@
592532
}
593533
594534
/* Allocate memory for DIR structure */
595535
dirp = (DIR*) malloc (sizeof (struct DIR));
596536
if (dirp) {
597
- wchar_t wname[PATH_MAX + 1];
537
+ wchar_t wname[PATH_MAX];
598538
size_t n;
599539
600540
/* Convert directory name to wide-character string */
601
- error = dirent_mbstowcs_s(
602
- &n, wname, PATH_MAX + 1, dirname, PATH_MAX);
541
+ error = dirent_mbstowcs_s (&n, wname, PATH_MAX, dirname, PATH_MAX);
603542
if (!error) {
604543
605544
/* Open directory stream using wide-character name */
606545
dirp->wdirp = _wopendir (wname);
607546
if (dirp->wdirp) {
@@ -662,11 +601,11 @@
662601
size_t n;
663602
int error;
664603
665604
/* Attempt to convert file name to multi-byte string */
666605
error = dirent_wcstombs_s(
667
- &n, dirp->ent.d_name, MAX_PATH + 1, datap->cFileName, MAX_PATH);
606
+ &n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX);
668607
669608
/*
670609
* If the file name cannot be represented by a multi-byte string,
671610
* then attempt to use old 8+3 file name. This allows traditional
672611
* Unix-code to access some file names despite of unicode
@@ -676,13 +615,12 @@
676615
* name unless the file system provides one. At least
677616
* VirtualBox shared folders fail to do this.
678617
*/
679618
if (error && datap->cAlternateFileName[0] != '\0') {
680619
error = dirent_wcstombs_s(
681
- &n, dirp->ent.d_name, MAX_PATH + 1, datap->cAlternateFileName,
682
- sizeof (datap->cAlternateFileName) /
683
- sizeof (datap->cAlternateFileName[0]));
620
+ &n, dirp->ent.d_name, PATH_MAX,
621
+ datap->cAlternateFileName, PATH_MAX);
684622
}
685623
686624
if (!error) {
687625
DWORD attr;
688626
@@ -787,16 +725,19 @@
787725
#else
788726
789727
/* Older Visual Studio or non-Microsoft compiler */
790728
size_t n;
791729
792
- /* Convert to wide-character string */
793
- n = mbstowcs (wcstr, mbstr, count);
794
- if (n < sizeInWords) {
730
+ /* Convert to wide-character string (or count characters) */
731
+ n = mbstowcs (wcstr, mbstr, sizeInWords);
732
+ if (!wcstr || n < count) {
795733
796734
/* Zero-terminate output buffer */
797
- if (wcstr) {
735
+ if (wcstr && sizeInWords) {
736
+ if (n >= sizeInWords) {
737
+ n = sizeInWords - 1;
738
+ }
798739
wcstr[n] = 0;
799740
}
800741
801742
/* Length of resuting multi-byte string WITH zero terminator */
802743
if (pReturnValue) {
@@ -821,11 +762,11 @@
821762
/* Convert wide-character string to multi-byte string */
822763
static int
823764
dirent_wcstombs_s(
824765
size_t *pReturnValue,
825766
char *mbstr,
826
- size_t sizeInBytes,
767
+ size_t sizeInBytes, /* max size of mbstr */
827768
const wchar_t *wcstr,
828769
size_t count)
829770
{
830771
int error;
831772
@@ -837,16 +778,19 @@
837778
#else
838779
839780
/* Older Visual Studio or non-Microsoft compiler */
840781
size_t n;
841782
842
- /* Convert to multi-byte string */
843
- n = wcstombs (mbstr, wcstr, count);
844
- if (n < sizeInBytes) {
783
+ /* Convert to multi-byte string (or count the number of bytes needed) */
784
+ n = wcstombs (mbstr, wcstr, sizeInBytes);
785
+ if (!mbstr || n < count) {
845786
846787
/* Zero-terminate output buffer */
847
- if (mbstr) {
788
+ if (mbstr && sizeInBytes) {
789
+ if (n >= sizeInBytes) {
790
+ n = sizeInBytes - 1;
791
+ }
848792
mbstr[n] = '\0';
849793
}
850794
851795
/* Lenght of resulting multi-bytes string WITH zero-terminator */
852796
if (pReturnValue) {
@@ -871,11 +815,11 @@
871815
/* Set errno variable */
872816
static void
873817
dirent_set_errno(
874818
int error)
875819
{
876
-#if defined(_MSC_VER) && _MSC_VER >= 1400
820
+#if defined(_MSC_VER) && _MSC_VER >= 1400
877821
878822
/* Microsoft Visual Studio 2005 and later */
879823
_set_errno (error);
880824
881825
#else
882826
--- win/include/dirent.h
+++ win/include/dirent.h
@@ -20,84 +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
44 * Defined FILE_ATTRIBUTE_DEVICE for MSVC 6.0.
45 *
46 * Version 1.10, Aug 11, 2010, Toni Ronkko
47 * Added d_type and d_namlen fields to dirent structure. The former is
48 * especially useful for determining whether directory entry represents a
49 * file or a directory. For more information, see
50 * http://www.delorie.com/gnu/docs/glibc/libc_270.html
51 *
52 * Improved conformance to the standards. For example, errno is now set
53 * properly on failure and assert() is never used. Thanks to Peter Brockam
54 * for suggestions.
55 *
56 * Fixed a bug in rewinddir(): when using relative directory names, change
57 * of working directory no longer causes rewinddir() to fail.
58 *
59 * Version 1.9, Dec 15, 2009, John Cunningham
60 * Added rewinddir member function
61 *
62 * Version 1.8, Jan 18, 2008, Toni Ronkko
63 * Using FindFirstFileA and WIN32_FIND_DATAA to avoid converting string
64 * between multi-byte and unicode representations. This makes the
65 * code simpler and also allows the code to be compiled under MingW. Thanks
66 * to Azriel Fasten for the suggestion.
67 *
68 * Mar 4, 2007, Toni Ronkko
69 * Bug fix: due to the strncpy_s() function this file only compiled in
70 * Visual Studio 2005. Using the new string functions only when the
71 * compiler version allows.
72 *
73 * Nov 2, 2006, Toni Ronkko
74 * Major update: removed support for Watcom C, MS-DOS and Turbo C to
75 * simplify the file, updated the code to compile cleanly on Visual
76 * Studio 2005 with both unicode and multi-byte character strings,
77 * removed rewinddir() as it had a bug.
78 *
79 * Aug 20, 2006, Toni Ronkko
80 * Removed all remarks about MSVC 1.0, which is antiqued now. Simplified
81 * comments by removing SGML tags.
82 *
83 * May 14 2002, Toni Ronkko
84 * Embedded the function definitions directly to the header so that no
85 * source modules need to be included in the Visual Studio project. Removed
86 * all the dependencies to other projects so that this header file can be
87 * used independently.
88 *
89 * May 28 1998, Toni Ronkko
90 * First version.
91 *****************************************************************************/
92 #ifndef DIRENT_H
93 #define DIRENT_H
94
95 #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && defined(_M_IX86)
 
 
 
 
 
96 # define _X86_
97 #endif
98 #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && defined(_M_AMD64)
99 #define _AMD64_
100 #endif
101
102 #include <stdio.h>
103 #include <stdarg.h>
@@ -213,11 +153,11 @@
213
214 /* Return the exact length of d_namlen without zero terminator */
215 #define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
216
217 /* Return number of bytes needed to store d_namlen */
218 #define _D_ALLOC_NAMLEN(p) (PATH_MAX + 1)
219
220
221 #ifdef __cplusplus
222 extern "C" {
223 #endif
@@ -227,11 +167,11 @@
227 struct _wdirent {
228 long d_ino; /* Always zero */
229 unsigned short d_reclen; /* Structure size */
230 size_t d_namlen; /* Length of name without \0 */
231 int d_type; /* File type */
232 wchar_t d_name[PATH_MAX + 1]; /* File name */
233 };
234 typedef struct _wdirent _wdirent;
235
236 struct _WDIR {
237 struct _wdirent ent; /* Current directory entry */
@@ -261,11 +201,11 @@
261 struct dirent {
262 long d_ino; /* Always zero */
263 unsigned short d_reclen; /* Structure size */
264 size_t d_namlen; /* Length of name without \0 */
265 int d_type; /* File type */
266 char d_name[PATH_MAX + 1]; /* File name */
267 };
268 typedef struct dirent dirent;
269
270 struct DIR {
271 struct dirent ent;
@@ -423,11 +363,11 @@
423 * Copy file name as wide-character string. If the file name is too
424 * long to fit in to the destination buffer, then truncate file name
425 * to PATH_MAX characters and zero-terminate the buffer.
426 */
427 n = 0;
428 while (n < PATH_MAX && datap->cFileName[n] != 0) {
429 entp->d_name[n] = datap->cFileName[n];
430 n++;
431 }
432 dirp->ent.d_name[n] = 0;
433
@@ -592,16 +532,15 @@
592 }
593
594 /* Allocate memory for DIR structure */
595 dirp = (DIR*) malloc (sizeof (struct DIR));
596 if (dirp) {
597 wchar_t wname[PATH_MAX + 1];
598 size_t n;
599
600 /* Convert directory name to wide-character string */
601 error = dirent_mbstowcs_s(
602 &n, wname, PATH_MAX + 1, dirname, PATH_MAX);
603 if (!error) {
604
605 /* Open directory stream using wide-character name */
606 dirp->wdirp = _wopendir (wname);
607 if (dirp->wdirp) {
@@ -662,11 +601,11 @@
662 size_t n;
663 int error;
664
665 /* Attempt to convert file name to multi-byte string */
666 error = dirent_wcstombs_s(
667 &n, dirp->ent.d_name, MAX_PATH + 1, datap->cFileName, MAX_PATH);
668
669 /*
670 * If the file name cannot be represented by a multi-byte string,
671 * then attempt to use old 8+3 file name. This allows traditional
672 * Unix-code to access some file names despite of unicode
@@ -676,13 +615,12 @@
676 * name unless the file system provides one. At least
677 * VirtualBox shared folders fail to do this.
678 */
679 if (error && datap->cAlternateFileName[0] != '\0') {
680 error = dirent_wcstombs_s(
681 &n, dirp->ent.d_name, MAX_PATH + 1, datap->cAlternateFileName,
682 sizeof (datap->cAlternateFileName) /
683 sizeof (datap->cAlternateFileName[0]));
684 }
685
686 if (!error) {
687 DWORD attr;
688
@@ -787,16 +725,19 @@
787 #else
788
789 /* Older Visual Studio or non-Microsoft compiler */
790 size_t n;
791
792 /* Convert to wide-character string */
793 n = mbstowcs (wcstr, mbstr, count);
794 if (n < sizeInWords) {
795
796 /* Zero-terminate output buffer */
797 if (wcstr) {
 
 
 
798 wcstr[n] = 0;
799 }
800
801 /* Length of resuting multi-byte string WITH zero terminator */
802 if (pReturnValue) {
@@ -821,11 +762,11 @@
821 /* Convert wide-character string to multi-byte string */
822 static int
823 dirent_wcstombs_s(
824 size_t *pReturnValue,
825 char *mbstr,
826 size_t sizeInBytes,
827 const wchar_t *wcstr,
828 size_t count)
829 {
830 int error;
831
@@ -837,16 +778,19 @@
837 #else
838
839 /* Older Visual Studio or non-Microsoft compiler */
840 size_t n;
841
842 /* Convert to multi-byte string */
843 n = wcstombs (mbstr, wcstr, count);
844 if (n < sizeInBytes) {
845
846 /* Zero-terminate output buffer */
847 if (mbstr) {
 
 
 
848 mbstr[n] = '\0';
849 }
850
851 /* Lenght of resulting multi-bytes string WITH zero-terminator */
852 if (pReturnValue) {
@@ -871,11 +815,11 @@
871 /* Set errno variable */
872 static void
873 dirent_set_errno(
874 int error)
875 {
876 #if defined(_MSC_VER) && _MSC_VER >= 1400
877
878 /* Microsoft Visual Studio 2005 and later */
879 _set_errno (error);
880
881 #else
882
--- win/include/dirent.h
+++ win/include/dirent.h
@@ -20,84 +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 * $Id: dirent.h,v 1.20 2014/03/19 17:52:23 tronkko Exp $
26 */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27 #ifndef DIRENT_H
28 #define DIRENT_H
29
30 /*
31 * Define architecture flags so we don't need to include windows.h.
32 * Avoiding windows.h makes it simpler to use windows sockets in conjunction
33 * with dirent.h.
34 */
35 #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86)
36 # define _X86_
37 #endif
38 #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_AMD64)
39 #define _AMD64_
40 #endif
41
42 #include <stdio.h>
43 #include <stdarg.h>
@@ -213,11 +153,11 @@
153
154 /* Return the exact length of d_namlen without zero terminator */
155 #define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
156
157 /* Return number of bytes needed to store d_namlen */
158 #define _D_ALLOC_NAMLEN(p) (PATH_MAX)
159
160
161 #ifdef __cplusplus
162 extern "C" {
163 #endif
@@ -227,11 +167,11 @@
167 struct _wdirent {
168 long d_ino; /* Always zero */
169 unsigned short d_reclen; /* Structure size */
170 size_t d_namlen; /* Length of name without \0 */
171 int d_type; /* File type */
172 wchar_t d_name[PATH_MAX]; /* File name */
173 };
174 typedef struct _wdirent _wdirent;
175
176 struct _WDIR {
177 struct _wdirent ent; /* Current directory entry */
@@ -261,11 +201,11 @@
201 struct dirent {
202 long d_ino; /* Always zero */
203 unsigned short d_reclen; /* Structure size */
204 size_t d_namlen; /* Length of name without \0 */
205 int d_type; /* File type */
206 char d_name[PATH_MAX]; /* File name */
207 };
208 typedef struct dirent dirent;
209
210 struct DIR {
211 struct dirent ent;
@@ -423,11 +363,11 @@
363 * Copy file name as wide-character string. If the file name is too
364 * long to fit in to the destination buffer, then truncate file name
365 * to PATH_MAX characters and zero-terminate the buffer.
366 */
367 n = 0;
368 while (n + 1 < PATH_MAX && datap->cFileName[n] != 0) {
369 entp->d_name[n] = datap->cFileName[n];
370 n++;
371 }
372 dirp->ent.d_name[n] = 0;
373
@@ -592,16 +532,15 @@
532 }
533
534 /* Allocate memory for DIR structure */
535 dirp = (DIR*) malloc (sizeof (struct DIR));
536 if (dirp) {
537 wchar_t wname[PATH_MAX];
538 size_t n;
539
540 /* Convert directory name to wide-character string */
541 error = dirent_mbstowcs_s (&n, wname, PATH_MAX, dirname, PATH_MAX);
 
542 if (!error) {
543
544 /* Open directory stream using wide-character name */
545 dirp->wdirp = _wopendir (wname);
546 if (dirp->wdirp) {
@@ -662,11 +601,11 @@
601 size_t n;
602 int error;
603
604 /* Attempt to convert file name to multi-byte string */
605 error = dirent_wcstombs_s(
606 &n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX);
607
608 /*
609 * If the file name cannot be represented by a multi-byte string,
610 * then attempt to use old 8+3 file name. This allows traditional
611 * Unix-code to access some file names despite of unicode
@@ -676,13 +615,12 @@
615 * name unless the file system provides one. At least
616 * VirtualBox shared folders fail to do this.
617 */
618 if (error && datap->cAlternateFileName[0] != '\0') {
619 error = dirent_wcstombs_s(
620 &n, dirp->ent.d_name, PATH_MAX,
621 datap->cAlternateFileName, PATH_MAX);
 
622 }
623
624 if (!error) {
625 DWORD attr;
626
@@ -787,16 +725,19 @@
725 #else
726
727 /* Older Visual Studio or non-Microsoft compiler */
728 size_t n;
729
730 /* Convert to wide-character string (or count characters) */
731 n = mbstowcs (wcstr, mbstr, sizeInWords);
732 if (!wcstr || n < count) {
733
734 /* Zero-terminate output buffer */
735 if (wcstr && sizeInWords) {
736 if (n >= sizeInWords) {
737 n = sizeInWords - 1;
738 }
739 wcstr[n] = 0;
740 }
741
742 /* Length of resuting multi-byte string WITH zero terminator */
743 if (pReturnValue) {
@@ -821,11 +762,11 @@
762 /* Convert wide-character string to multi-byte string */
763 static int
764 dirent_wcstombs_s(
765 size_t *pReturnValue,
766 char *mbstr,
767 size_t sizeInBytes, /* max size of mbstr */
768 const wchar_t *wcstr,
769 size_t count)
770 {
771 int error;
772
@@ -837,16 +778,19 @@
778 #else
779
780 /* Older Visual Studio or non-Microsoft compiler */
781 size_t n;
782
783 /* Convert to multi-byte string (or count the number of bytes needed) */
784 n = wcstombs (mbstr, wcstr, sizeInBytes);
785 if (!mbstr || n < count) {
786
787 /* Zero-terminate output buffer */
788 if (mbstr && sizeInBytes) {
789 if (n >= sizeInBytes) {
790 n = sizeInBytes - 1;
791 }
792 mbstr[n] = '\0';
793 }
794
795 /* Lenght of resulting multi-bytes string WITH zero-terminator */
796 if (pReturnValue) {
@@ -871,11 +815,11 @@
815 /* Set errno variable */
816 static void
817 dirent_set_errno(
818 int error)
819 {
820 #if defined(_MSC_VER) && _MSC_VER >= 1400
821
822 /* Microsoft Visual Studio 2005 and later */
823 _set_errno (error);
824
825 #else
826
+11 -1
--- www/quotes.wiki
+++ www/quotes.wiki
@@ -70,10 +70,20 @@
7070
get a bug-tracking system to work with mercurial.
7171
7272
<blockquote>
7373
<i>rawjeev at [http://stackoverflow.com/questions/156322/what-do-people-think-of-the-fossil-dvcs]</i>
7474
</blockquote>
75
+
76
+<li>Fossil is the best thing to happen
77
+to my development workflow this year, as I am pretty sure that using
78
+Git has resulted in the premature death of too many of my brain cells.
79
+I'm glad to be able to replace Git in every place that I possibly can
80
+with Fossil.
81
+
82
+<blockquote>
83
+<i>Joe Prostko at [http://www.mail-archive.com/[email protected]/msg16716.html]
84
+</blockquote>
7585
7686
<li>Fossil is awesome!!! I have never seen an app like that before,
7787
such simplicity and flexibility!!!
7888
7989
<blockquote>
@@ -85,11 +95,11 @@
8595
8696
8797
<h2>On Git Versus Fossil</h2>
8898
8999
<ol>
90
-<li value=9>
100
+<li value=10>
91101
Just want to say thanks for fossil making my life easier....
92102
Also <nowiki>[for]</nowiki> not having a misanthropic command line interface.
93103
94104
<blockquote>
95105
<i>Joshua Paine at [http://www.mail-archive.com/[email protected]/msg02736.html]</i>
96106
--- www/quotes.wiki
+++ www/quotes.wiki
@@ -70,10 +70,20 @@
70 get a bug-tracking system to work with mercurial.
71
72 <blockquote>
73 <i>rawjeev at [http://stackoverflow.com/questions/156322/what-do-people-think-of-the-fossil-dvcs]</i>
74 </blockquote>
 
 
 
 
 
 
 
 
 
 
75
76 <li>Fossil is awesome!!! I have never seen an app like that before,
77 such simplicity and flexibility!!!
78
79 <blockquote>
@@ -85,11 +95,11 @@
85
86
87 <h2>On Git Versus Fossil</h2>
88
89 <ol>
90 <li value=9>
91 Just want to say thanks for fossil making my life easier....
92 Also <nowiki>[for]</nowiki> not having a misanthropic command line interface.
93
94 <blockquote>
95 <i>Joshua Paine at [http://www.mail-archive.com/[email protected]/msg02736.html]</i>
96
--- www/quotes.wiki
+++ www/quotes.wiki
@@ -70,10 +70,20 @@
70 get a bug-tracking system to work with mercurial.
71
72 <blockquote>
73 <i>rawjeev at [http://stackoverflow.com/questions/156322/what-do-people-think-of-the-fossil-dvcs]</i>
74 </blockquote>
75
76 <li>Fossil is the best thing to happen
77 to my development workflow this year, as I am pretty sure that using
78 Git has resulted in the premature death of too many of my brain cells.
79 I'm glad to be able to replace Git in every place that I possibly can
80 with Fossil.
81
82 <blockquote>
83 <i>Joe Prostko at [http://www.mail-archive.com/[email protected]/msg16716.html]
84 </blockquote>
85
86 <li>Fossil is awesome!!! I have never seen an app like that before,
87 such simplicity and flexibility!!!
88
89 <blockquote>
@@ -85,11 +95,11 @@
95
96
97 <h2>On Git Versus Fossil</h2>
98
99 <ol>
100 <li value=10>
101 Just want to say thanks for fossil making my life easier....
102 Also <nowiki>[for]</nowiki> not having a misanthropic command line interface.
103
104 <blockquote>
105 <i>Joshua Paine at [http://www.mail-archive.com/[email protected]/msg02736.html]</i>
106
+55 -9
--- www/sync.wiki
+++ www/sync.wiki
@@ -159,15 +159,21 @@
159159
160160
<p>Privileges are cumulative. There can be multiple successful
161161
login cards. The session privileges are the bit-wise OR of the
162162
privileges of each individual login.</p>
163163
164
-<h3>3.3 File Cards</h3>
164
+<h3>3.3 File and Compressed File Cards</h3>
165165
166
-<p>Artifacts are transferred using "file" cards. (The name "file"
167
-card comes from the fact that most artifacts correspond to files.)
168
-File cards come in two different formats depending
166
+<p>Artifacts are transferred using either "file" cards, or "cfile" cards.
167
+(The name "file" card comes from the fact that most artifacts correspond to
168
+files, and "cfile" is just a compressed file.)
169
+</p>
170
+
171
+<h4>3.3.1 File Cards</h4>
172
+
173
+<p>For sync protocols, artifacts are transferred using "file"
174
+cards. File cards come in two different formats depending
169175
on whether the artifact is sent directly or as a delta from some
170176
other artifact.</p>
171177
172178
<blockquote>
173179
<b>file</b> <i>artifact-id size</i> <b>\n</b> <i>content</i><br>
@@ -176,11 +182,11 @@
176182
177183
<p>File cards are different from all other cards in that they
178184
followed by in-line "payload" data. The content of the artifact
179185
or the artifact delta consists of the first <i>size</i> bytes of the
180186
x-fossil content that immediately follow the newline that
181
-terminates the file card. No other cards have this characteristic.
187
+terminates the file card. Only file and cfile cards have this characteristic.
182188
</p>
183189
184190
<p>The first argument of a file card is the ID of the artifact that
185191
is being transferred. The artifact ID is the lower-case hexadecimal
186192
representation of the SHA1 hash of the artifact.
@@ -194,10 +200,43 @@
194200
<p>File cards are sent in both directions: client to server and
195201
server to client. A delta might be sent before the source of
196202
the delta, so both client and server should remember deltas
197203
and be able to apply them when their source arrives.</p>
198204
205
+<h4>3.3.2 Compressed File Cards</h4>
206
+
207
+<p>A client that sends a clone protocol version "3" or greater will
208
+receive artifacts as "cfile" cards while cloning. This card was
209
+introduced to improve the speed of the transfer of content by sending the
210
+compressed artifact directly from the server database to the client.</p>
211
+
212
+<p>Compressed File cards are similar to File cards, sharing the same
213
+in-line "payload" data characteristics and also the same treatment of
214
+direct content or delta content. It comes in two different formats
215
+depending on whether the artifact is sent directly or as a delta from
216
+some other artifact.</p>
217
+
218
+<blockquote>
219
+<b>cfile</b> <i>artifact-id usize csize</i> <b>\n</b> <i>content</i><br>
220
+<b>cfile</b> <i>artifact-id delta-artifact-id usize csize</i> <b>\n</b> <i>content</i><br>
221
+</blockquote>
222
+
223
+<p>The first argument of the cfile card is the ID of the artifact that
224
+is being transferred. The artifact ID is the lower-case hexadecimal
225
+representation of the SHA1 hash of the artifact. The second argument of
226
+the cfile card is the original size in bytes of the artifact. The last
227
+argument of the cfile card is the number of compressed bytes of payload
228
+that immediately follow the cfile card. If the cfile card has only
229
+three arguments, that means the payload is the complete content of the
230
+artifact. If the cfile card has four arguments, then the payload is a
231
+delta and the second argument is the ID of another artifact that is the
232
+source of the delta and the third argument is the original size of the
233
+delta artifact.</p>
234
+
235
+<p>Unlike file cards, cfile cards are only sent in one direction during a
236
+clone from server to client for clone protocol version "3" or greater.</p>
237
+
199238
<h3>3.4 Push and Pull Cards</h3>
200239
201240
<p>Among the first cards in a client-to-server message are
202241
the push and pull cards. The push card tells the server that
203242
the client is pushing content. The pull card tells the server
@@ -232,15 +271,22 @@
232271
<blockquote>
233272
<b>clone</b><br>
234273
<b>clone</b> <i>protocol-version sequence-number</i>
235274
</blockquote>
236275
237
-<h4>3.5.1 Protocol 2</h4>
276
+<h4>3.5.1 Protocol 3</h4>
238277
239278
<p>The latest clients send a two-argument clone message with a
240
-protocol version of "2". (Future versions of Fossil might use larger
241
-protocol version numbers.) The sequence-number sent is the number
279
+protocol version of "3". (Future versions of Fossil might use larger
280
+protocol version numbers.) Version "3" of the protocol enhanced version
281
+"2" by introducing the "cfile" card which is intended to speed up clone
282
+operations. Instead of sending "file" cards, the server will send "cfile"
283
+cards</p>
284
+
285
+<h4>3.5.2 Protocol 2</h4>
286
+
287
+<p>The sequence-number sent is the number
242288
of artifacts received so far. For the first clone message, the
243289
sequence number is 0. The server will respond by sending file
244290
cards for some number of artifacts up to the maximum message size.
245291
246292
<p>The server will also send a single "clone_seqno" card to the client
@@ -256,11 +302,11 @@
256302
257303
<p>In response to an initial clone message, the server also sends the client
258304
a push message so that the client can discover the projectcode for
259305
this project.</p>
260306
261
-<h4>3.5.2 Legacy Protocol</h4>
307
+<h4>3.5.3 Legacy Protocol</h4>
262308
263309
<p>Older clients send a clone card with no argument. The server responds
264310
to a blank clone card by sending an "igot" card for every artifact in the
265311
repository. The client will then issue "gimme" cards to pull down all the
266312
content it needs.
267313
--- www/sync.wiki
+++ www/sync.wiki
@@ -159,15 +159,21 @@
159
160 <p>Privileges are cumulative. There can be multiple successful
161 login cards. The session privileges are the bit-wise OR of the
162 privileges of each individual login.</p>
163
164 <h3>3.3 File Cards</h3>
165
166 <p>Artifacts are transferred using "file" cards. (The name "file"
167 card comes from the fact that most artifacts correspond to files.)
168 File cards come in two different formats depending
 
 
 
 
 
 
169 on whether the artifact is sent directly or as a delta from some
170 other artifact.</p>
171
172 <blockquote>
173 <b>file</b> <i>artifact-id size</i> <b>\n</b> <i>content</i><br>
@@ -176,11 +182,11 @@
176
177 <p>File cards are different from all other cards in that they
178 followed by in-line "payload" data. The content of the artifact
179 or the artifact delta consists of the first <i>size</i> bytes of the
180 x-fossil content that immediately follow the newline that
181 terminates the file card. No other cards have this characteristic.
182 </p>
183
184 <p>The first argument of a file card is the ID of the artifact that
185 is being transferred. The artifact ID is the lower-case hexadecimal
186 representation of the SHA1 hash of the artifact.
@@ -194,10 +200,43 @@
194 <p>File cards are sent in both directions: client to server and
195 server to client. A delta might be sent before the source of
196 the delta, so both client and server should remember deltas
197 and be able to apply them when their source arrives.</p>
198
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199 <h3>3.4 Push and Pull Cards</h3>
200
201 <p>Among the first cards in a client-to-server message are
202 the push and pull cards. The push card tells the server that
203 the client is pushing content. The pull card tells the server
@@ -232,15 +271,22 @@
232 <blockquote>
233 <b>clone</b><br>
234 <b>clone</b> <i>protocol-version sequence-number</i>
235 </blockquote>
236
237 <h4>3.5.1 Protocol 2</h4>
238
239 <p>The latest clients send a two-argument clone message with a
240 protocol version of "2". (Future versions of Fossil might use larger
241 protocol version numbers.) The sequence-number sent is the number
 
 
 
 
 
 
 
242 of artifacts received so far. For the first clone message, the
243 sequence number is 0. The server will respond by sending file
244 cards for some number of artifacts up to the maximum message size.
245
246 <p>The server will also send a single "clone_seqno" card to the client
@@ -256,11 +302,11 @@
256
257 <p>In response to an initial clone message, the server also sends the client
258 a push message so that the client can discover the projectcode for
259 this project.</p>
260
261 <h4>3.5.2 Legacy Protocol</h4>
262
263 <p>Older clients send a clone card with no argument. The server responds
264 to a blank clone card by sending an "igot" card for every artifact in the
265 repository. The client will then issue "gimme" cards to pull down all the
266 content it needs.
267
--- www/sync.wiki
+++ www/sync.wiki
@@ -159,15 +159,21 @@
159
160 <p>Privileges are cumulative. There can be multiple successful
161 login cards. The session privileges are the bit-wise OR of the
162 privileges of each individual login.</p>
163
164 <h3>3.3 File and Compressed File Cards</h3>
165
166 <p>Artifacts are transferred using either "file" cards, or "cfile" cards.
167 (The name "file" card comes from the fact that most artifacts correspond to
168 files, and "cfile" is just a compressed file.)
169 </p>
170
171 <h4>3.3.1 File Cards</h4>
172
173 <p>For sync protocols, artifacts are transferred using "file"
174 cards. File cards come in two different formats depending
175 on whether the artifact is sent directly or as a delta from some
176 other artifact.</p>
177
178 <blockquote>
179 <b>file</b> <i>artifact-id size</i> <b>\n</b> <i>content</i><br>
@@ -176,11 +182,11 @@
182
183 <p>File cards are different from all other cards in that they
184 followed by in-line "payload" data. The content of the artifact
185 or the artifact delta consists of the first <i>size</i> bytes of the
186 x-fossil content that immediately follow the newline that
187 terminates the file card. Only file and cfile cards have this characteristic.
188 </p>
189
190 <p>The first argument of a file card is the ID of the artifact that
191 is being transferred. The artifact ID is the lower-case hexadecimal
192 representation of the SHA1 hash of the artifact.
@@ -194,10 +200,43 @@
200 <p>File cards are sent in both directions: client to server and
201 server to client. A delta might be sent before the source of
202 the delta, so both client and server should remember deltas
203 and be able to apply them when their source arrives.</p>
204
205 <h4>3.3.2 Compressed File Cards</h4>
206
207 <p>A client that sends a clone protocol version "3" or greater will
208 receive artifacts as "cfile" cards while cloning. This card was
209 introduced to improve the speed of the transfer of content by sending the
210 compressed artifact directly from the server database to the client.</p>
211
212 <p>Compressed File cards are similar to File cards, sharing the same
213 in-line "payload" data characteristics and also the same treatment of
214 direct content or delta content. It comes in two different formats
215 depending on whether the artifact is sent directly or as a delta from
216 some other artifact.</p>
217
218 <blockquote>
219 <b>cfile</b> <i>artifact-id usize csize</i> <b>\n</b> <i>content</i><br>
220 <b>cfile</b> <i>artifact-id delta-artifact-id usize csize</i> <b>\n</b> <i>content</i><br>
221 </blockquote>
222
223 <p>The first argument of the cfile card is the ID of the artifact that
224 is being transferred. The artifact ID is the lower-case hexadecimal
225 representation of the SHA1 hash of the artifact. The second argument of
226 the cfile card is the original size in bytes of the artifact. The last
227 argument of the cfile card is the number of compressed bytes of payload
228 that immediately follow the cfile card. If the cfile card has only
229 three arguments, that means the payload is the complete content of the
230 artifact. If the cfile card has four arguments, then the payload is a
231 delta and the second argument is the ID of another artifact that is the
232 source of the delta and the third argument is the original size of the
233 delta artifact.</p>
234
235 <p>Unlike file cards, cfile cards are only sent in one direction during a
236 clone from server to client for clone protocol version "3" or greater.</p>
237
238 <h3>3.4 Push and Pull Cards</h3>
239
240 <p>Among the first cards in a client-to-server message are
241 the push and pull cards. The push card tells the server that
242 the client is pushing content. The pull card tells the server
@@ -232,15 +271,22 @@
271 <blockquote>
272 <b>clone</b><br>
273 <b>clone</b> <i>protocol-version sequence-number</i>
274 </blockquote>
275
276 <h4>3.5.1 Protocol 3</h4>
277
278 <p>The latest clients send a two-argument clone message with a
279 protocol version of "3". (Future versions of Fossil might use larger
280 protocol version numbers.) Version "3" of the protocol enhanced version
281 "2" by introducing the "cfile" card which is intended to speed up clone
282 operations. Instead of sending "file" cards, the server will send "cfile"
283 cards</p>
284
285 <h4>3.5.2 Protocol 2</h4>
286
287 <p>The sequence-number sent is the number
288 of artifacts received so far. For the first clone message, the
289 sequence number is 0. The server will respond by sending file
290 cards for some number of artifacts up to the maximum message size.
291
292 <p>The server will also send a single "clone_seqno" card to the client
@@ -256,11 +302,11 @@
302
303 <p>In response to an initial clone message, the server also sends the client
304 a push message so that the client can discover the projectcode for
305 this project.</p>
306
307 <h4>3.5.3 Legacy Protocol</h4>
308
309 <p>Older clients send a clone card with no argument. The server responds
310 to a blank clone card by sending an "igot" card for every artifact in the
311 repository. The client will then issue "gimme" cards to pull down all the
312 content it needs.
313

Keyboard Shortcuts

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