Fossil SCM

Merge updates from trunk.

mistachkin 2015-04-05 20:02 UTC mvAndRmFiles merge
Commit 55f7ec6c5d0e338937b14b5b2bb0fb43bdeb9c8a
--- skins/blitz/css.txt
+++ skins/blitz/css.txt
@@ -1054,26 +1054,48 @@
10541054
* Displays chronologically-ordered check-ins with a branch graph.
10551055
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
10561056
tr.timelineCurrent {
10571057
border-left: 2px solid orange;
10581058
background-color: #ffc;
1059
+ border-bottom: 1px solid #ddd;
1060
+ border-right: 1px solid #ddd;
10591061
}
10601062
10611063
tr.timelineSelected {
10621064
border-left: 2px solid orange;
10631065
background-color: #ffffe8;
1066
+ border-bottom: 1px solid #ddd;
1067
+ border-right: 1px solid #ddd;
10641068
}
10651069
10661070
tr.timelineCurrent td.timelineTableCell {
10671071
}
10681072
10691073
tr.timelineSpacer {
10701074
}
1075
+
1076
+tr.timelineBottom td {
1077
+ border-bottom: 0;
1078
+}
10711079
10721080
div.timelineDate {
1073
- font-weight: bold;
1074
- white-space: nowrap;
1081
+ font-weight: bold;
1082
+ white-space: nowrap;
1083
+}
1084
+
1085
+td.timelineTime {
1086
+ vertical-align: top;
1087
+ text-align: right;
1088
+ white-space: nowrap;
1089
+ border-bottom: 0;
1090
+}
1091
+
1092
+td.timelineGraph {
1093
+ width: 20px;
1094
+ text-align: left;
1095
+ vertical-align: top;
1096
+ border-bottom: 0;
10751097
}
10761098
10771099
a.timelineHistLink {
10781100
text-transform: lowercase;
10791101
}
10801102
--- skins/blitz/css.txt
+++ skins/blitz/css.txt
@@ -1054,26 +1054,48 @@
1054 * Displays chronologically-ordered check-ins with a branch graph.
1055 ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
1056 tr.timelineCurrent {
1057 border-left: 2px solid orange;
1058 background-color: #ffc;
 
 
1059 }
1060
1061 tr.timelineSelected {
1062 border-left: 2px solid orange;
1063 background-color: #ffffe8;
 
 
1064 }
1065
1066 tr.timelineCurrent td.timelineTableCell {
1067 }
1068
1069 tr.timelineSpacer {
1070 }
 
 
 
 
1071
1072 div.timelineDate {
1073 font-weight: bold;
1074 white-space: nowrap;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1075 }
1076
1077 a.timelineHistLink {
1078 text-transform: lowercase;
1079 }
1080
--- skins/blitz/css.txt
+++ skins/blitz/css.txt
@@ -1054,26 +1054,48 @@
1054 * Displays chronologically-ordered check-ins with a branch graph.
1055 ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
1056 tr.timelineCurrent {
1057 border-left: 2px solid orange;
1058 background-color: #ffc;
1059 border-bottom: 1px solid #ddd;
1060 border-right: 1px solid #ddd;
1061 }
1062
1063 tr.timelineSelected {
1064 border-left: 2px solid orange;
1065 background-color: #ffffe8;
1066 border-bottom: 1px solid #ddd;
1067 border-right: 1px solid #ddd;
1068 }
1069
1070 tr.timelineCurrent td.timelineTableCell {
1071 }
1072
1073 tr.timelineSpacer {
1074 }
1075
1076 tr.timelineBottom td {
1077 border-bottom: 0;
1078 }
1079
1080 div.timelineDate {
1081 font-weight: bold;
1082 white-space: nowrap;
1083 }
1084
1085 td.timelineTime {
1086 vertical-align: top;
1087 text-align: right;
1088 white-space: nowrap;
1089 border-bottom: 0;
1090 }
1091
1092 td.timelineGraph {
1093 width: 20px;
1094 text-align: left;
1095 vertical-align: top;
1096 border-bottom: 0;
1097 }
1098
1099 a.timelineHistLink {
1100 text-transform: lowercase;
1101 }
1102
--- skins/blitz_no_logo/css.txt
+++ skins/blitz_no_logo/css.txt
@@ -1054,26 +1054,48 @@
10541054
* Displays chronologically-ordered check-ins with a branch graph.
10551055
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
10561056
tr.timelineCurrent {
10571057
border-left: 2px solid orange;
10581058
background-color: #ffc;
1059
+ border-bottom: 1px solid #ddd;
1060
+ border-right: 1px solid #ddd;
10591061
}
10601062
10611063
tr.timelineSelected {
10621064
border-left: 2px solid orange;
10631065
background-color: #ffffe8;
1066
+ border-bottom: 1px solid #ddd;
1067
+ border-right: 1px solid #ddd;
10641068
}
10651069
10661070
tr.timelineCurrent td.timelineTableCell {
10671071
}
10681072
10691073
tr.timelineSpacer {
10701074
}
1075
+
1076
+tr.timelineBottom td {
1077
+ border-bottom: 0;
1078
+}
10711079
10721080
div.timelineDate {
1073
- font-weight: bold;
1074
- white-space: nowrap;
1081
+ font-weight: bold;
1082
+ white-space: nowrap;
1083
+}
1084
+
1085
+td.timelineTime {
1086
+ vertical-align: top;
1087
+ text-align: right;
1088
+ white-space: nowrap;
1089
+ border-bottom: 0;
1090
+}
1091
+
1092
+td.timelineGraph {
1093
+ width: 20px;
1094
+ text-align: left;
1095
+ vertical-align: top;
1096
+ border-bottom: 0;
10751097
}
10761098
10771099
a.timelineHistLink {
10781100
text-transform: lowercase;
10791101
}
10801102
--- skins/blitz_no_logo/css.txt
+++ skins/blitz_no_logo/css.txt
@@ -1054,26 +1054,48 @@
1054 * Displays chronologically-ordered check-ins with a branch graph.
1055 ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
1056 tr.timelineCurrent {
1057 border-left: 2px solid orange;
1058 background-color: #ffc;
 
 
1059 }
1060
1061 tr.timelineSelected {
1062 border-left: 2px solid orange;
1063 background-color: #ffffe8;
 
 
1064 }
1065
1066 tr.timelineCurrent td.timelineTableCell {
1067 }
1068
1069 tr.timelineSpacer {
1070 }
 
 
 
 
1071
1072 div.timelineDate {
1073 font-weight: bold;
1074 white-space: nowrap;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1075 }
1076
1077 a.timelineHistLink {
1078 text-transform: lowercase;
1079 }
1080
--- skins/blitz_no_logo/css.txt
+++ skins/blitz_no_logo/css.txt
@@ -1054,26 +1054,48 @@
1054 * Displays chronologically-ordered check-ins with a branch graph.
1055 ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
1056 tr.timelineCurrent {
1057 border-left: 2px solid orange;
1058 background-color: #ffc;
1059 border-bottom: 1px solid #ddd;
1060 border-right: 1px solid #ddd;
1061 }
1062
1063 tr.timelineSelected {
1064 border-left: 2px solid orange;
1065 background-color: #ffffe8;
1066 border-bottom: 1px solid #ddd;
1067 border-right: 1px solid #ddd;
1068 }
1069
1070 tr.timelineCurrent td.timelineTableCell {
1071 }
1072
1073 tr.timelineSpacer {
1074 }
1075
1076 tr.timelineBottom td {
1077 border-bottom: 0;
1078 }
1079
1080 div.timelineDate {
1081 font-weight: bold;
1082 white-space: nowrap;
1083 }
1084
1085 td.timelineTime {
1086 vertical-align: top;
1087 text-align: right;
1088 white-space: nowrap;
1089 border-bottom: 0;
1090 }
1091
1092 td.timelineGraph {
1093 width: 20px;
1094 text-align: left;
1095 vertical-align: top;
1096 border-bottom: 0;
1097 }
1098
1099 a.timelineHistLink {
1100 text-transform: lowercase;
1101 }
1102
+63 -52
--- src/allrepo.c
+++ src/allrepo.c
@@ -87,63 +87,65 @@
8787
** On Win32 systems, the file is named "_fossil" and is located in
8888
** %LOCALAPPDATA%, %APPDATA% or %HOMEPATH%.
8989
**
9090
** Available operations are:
9191
**
92
-** changes Shows all local checkouts that have uncommitted changes.
93
-** This operation has no additional options.
94
-**
95
-** clean Delete all "extra" files in all local checkouts. Extreme
96
-** caution should be exercised with this command because its
97
-** effects cannot be undone. Use of the --dry-run option to
98
-** carefully review the local checkouts to be operated upon
99
-** and the --whatif option to carefully review the files to
100
-** be deleted beforehand is highly recommended. The command
101
-** line options supported by the clean command itself, if any
102
-** are present, are passed along verbatim.
103
-**
104
-** dbstat Run the "dbstat" command on all repositories.
105
-**
106
-** extras Shows "extra" files from all local checkouts. The command
107
-** line options supported by the extra command itself, if any
108
-** are present, are passed along verbatim.
109
-**
110
-** info Run the "info" command on all repositories.
111
-**
112
-** pull Run a "pull" operation on all repositories. Only the
113
-** --verbose option is supported.
114
-**
115
-** push Run a "push" on all repositories. Only the --verbose
116
-** option is supported.
117
-**
118
-** rebuild Rebuild on all repositories. The command line options
119
-** supported by the rebuild command itself, if any are
120
-** present, are passed along verbatim. The --force and
121
-** --randomize options are not supported.
122
-**
123
-** sync Run a "sync" on all repositories. Only the --verbose
124
-** option is supported.
125
-**
126
-** setting Run the "setting", "set", or "unset" commands on all
127
-** set repositories. These command are particularly useful in
128
-** unset conjunction with the "max-loadavg" setting which cannot
129
-** otherwise be set globally.
92
+** changes Shows all local checkouts that have uncommitted changes.
93
+** This operation has no additional options.
94
+**
95
+** clean Delete all "extra" files in all local checkouts. Extreme
96
+** caution should be exercised with this command because its
97
+** effects cannot be undone. Use of the --dry-run option to
98
+** carefully review the local checkouts to be operated upon
99
+** and the --whatif option to carefully review the files to
100
+** be deleted beforehand is highly recommended. The command
101
+** line options supported by the clean command itself, if any
102
+** are present, are passed along verbatim.
103
+**
104
+** dbstat Run the "dbstat" command on all repositories.
105
+**
106
+** extras Shows "extra" files from all local checkouts. The command
107
+** line options supported by the extra command itself, if any
108
+** are present, are passed along verbatim.
109
+**
110
+** fts-config Run the "fts-config" command on all repositories.
111
+**
112
+** info Run the "info" command on all repositories.
113
+**
114
+** pull Run a "pull" operation on all repositories. Only the
115
+** --verbose option is supported.
116
+**
117
+** push Run a "push" on all repositories. Only the --verbose
118
+** option is supported.
119
+**
120
+** rebuild Rebuild on all repositories. The command line options
121
+** supported by the rebuild command itself, if any are
122
+** present, are passed along verbatim. The --force and
123
+** --randomize options are not supported.
124
+**
125
+** sync Run a "sync" on all repositories. Only the --verbose
126
+** option is supported.
127
+**
128
+** setting Run the "setting", "set", or "unset" commands on all
129
+** set repositories. These command are particularly useful in
130
+** unset conjunction with the "max-loadavg" setting which cannot
131
+** otherwise be set globally.
130132
**
131133
** In addition, the following maintenance operations are supported:
132134
**
133
-** add Add all the repositories named to the set of repositories
134
-** tracked by Fossil. Normally Fossil is able to keep up with
135
-** this list by itself, but sometime it can benefit from this
136
-** hint if you rename repositories.
137
-**
138
-** ignore Arguments are repositories that should be ignored by
139
-** subsequent clean, extras, list, pull, push, rebuild, and
140
-** sync operations. The -c|--ckout option causes the listed
141
-** local checkouts to be ignored instead.
142
-**
143
-** list | ls Display the location of all repositories. The -c|--ckout
144
-** option causes all local checkouts to be listed instead.
135
+** add Add all the repositories named to the set of repositories
136
+** tracked by Fossil. Normally Fossil is able to keep up with
137
+** this list by itself, but sometime it can benefit from this
138
+** hint if you rename repositories.
139
+**
140
+** ignore Arguments are repositories that should be ignored by
141
+** subsequent clean, extras, list, pull, push, rebuild, and
142
+** sync operations. The -c|--ckout option causes the listed
143
+** local checkouts to be ignored instead.
144
+**
145
+** list | ls Display the location of all repositories. The -c|--ckout
146
+** option causes all local checkouts to be listed instead.
145147
**
146148
** Repositories are automatically added to the set of known repositories
147149
** when one of the following commands are run against the repository:
148150
** clone, info, pull, push, or sync. Even previously ignored repositories
149151
** are added back to the list of repositories by these commands.
@@ -174,11 +176,11 @@
174176
if( !dryRunFlag ){
175177
dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
176178
}
177179
178180
if( g.argc<3 ){
179
- usage("changes|clean|extras|ignore|list|ls|pull|push|rebuild|sync");
181
+ usage("SUBCOMMAND ...");
180182
}
181183
n = strlen(g.argv[2]);
182184
db_open_config(1);
183185
blob_zero(&extra);
184186
zCmd = g.argv[2];
@@ -284,10 +286,13 @@
284286
}else{
285287
db_multi_exec("%s", blob_sql_text(&sql));
286288
}
287289
}
288290
db_end_transaction(0);
291
+ blob_reset(&sql);
292
+ blob_reset(&fn);
293
+ blob_reset(&extra);
289294
return;
290295
}else if( strncmp(zCmd, "add", n)==0 ){
291296
int j;
292297
Blob fn = BLOB_INITIALIZER;
293298
Blob sql = BLOB_INITIALIZER;
@@ -313,18 +318,22 @@
313318
}else{
314319
db_multi_exec("%s", blob_sql_text(&sql));
315320
}
316321
}
317322
db_end_transaction(0);
323
+ blob_reset(&sql);
324
+ blob_reset(&fn);
325
+ blob_reset(&extra);
318326
return;
319327
}else if( strncmp(zCmd, "info", n)==0 ){
320328
zCmd = "info";
321329
showLabel = 1;
322330
quiet = 1;
323331
}else{
324332
fossil_fatal("\"all\" subcommand should be one of: "
325
- "changes clean extras ignore list ls push pull rebuild sync");
333
+ "add changes clean dbstat extras fts-config ignore "
334
+ "info list ls pull push rebuild setting sync unset");
326335
}
327336
verify_all_options();
328337
zFossil = quoteFilename(g.nameOfExe);
329338
db_multi_exec("CREATE TEMP TABLE repolist(name,tag);");
330339
if( useCheckouts ){
@@ -382,10 +391,12 @@
382391
if( stopOnError && rc ){
383392
break;
384393
}
385394
}
386395
db_finalize(&q);
396
+
397
+ blob_reset(&extra);
387398
388399
/* If any repositories whose names appear in the ~/.fossil file could not
389400
** be found, remove those names from the ~/.fossil file.
390401
*/
391402
if( nToDel>0 ){
392403
--- src/allrepo.c
+++ src/allrepo.c
@@ -87,63 +87,65 @@
87 ** On Win32 systems, the file is named "_fossil" and is located in
88 ** %LOCALAPPDATA%, %APPDATA% or %HOMEPATH%.
89 **
90 ** Available operations are:
91 **
92 ** changes Shows all local checkouts that have uncommitted changes.
93 ** This operation has no additional options.
94 **
95 ** clean Delete all "extra" files in all local checkouts. Extreme
96 ** caution should be exercised with this command because its
97 ** effects cannot be undone. Use of the --dry-run option to
98 ** carefully review the local checkouts to be operated upon
99 ** and the --whatif option to carefully review the files to
100 ** be deleted beforehand is highly recommended. The command
101 ** line options supported by the clean command itself, if any
102 ** are present, are passed along verbatim.
103 **
104 ** dbstat Run the "dbstat" command on all repositories.
105 **
106 ** extras Shows "extra" files from all local checkouts. The command
107 ** line options supported by the extra command itself, if any
108 ** are present, are passed along verbatim.
109 **
110 ** info Run the "info" command on all repositories.
111 **
112 ** pull Run a "pull" operation on all repositories. Only the
113 ** --verbose option is supported.
114 **
115 ** push Run a "push" on all repositories. Only the --verbose
116 ** option is supported.
117 **
118 ** rebuild Rebuild on all repositories. The command line options
119 ** supported by the rebuild command itself, if any are
120 ** present, are passed along verbatim. The --force and
121 ** --randomize options are not supported.
122 **
123 ** sync Run a "sync" on all repositories. Only the --verbose
124 ** option is supported.
125 **
126 ** setting Run the "setting", "set", or "unset" commands on all
127 ** set repositories. These command are particularly useful in
128 ** unset conjunction with the "max-loadavg" setting which cannot
129 ** otherwise be set globally.
 
 
130 **
131 ** In addition, the following maintenance operations are supported:
132 **
133 ** add Add all the repositories named to the set of repositories
134 ** tracked by Fossil. Normally Fossil is able to keep up with
135 ** this list by itself, but sometime it can benefit from this
136 ** hint if you rename repositories.
137 **
138 ** ignore Arguments are repositories that should be ignored by
139 ** subsequent clean, extras, list, pull, push, rebuild, and
140 ** sync operations. The -c|--ckout option causes the listed
141 ** local checkouts to be ignored instead.
142 **
143 ** list | ls Display the location of all repositories. The -c|--ckout
144 ** option causes all local checkouts to be listed instead.
145 **
146 ** Repositories are automatically added to the set of known repositories
147 ** when one of the following commands are run against the repository:
148 ** clone, info, pull, push, or sync. Even previously ignored repositories
149 ** are added back to the list of repositories by these commands.
@@ -174,11 +176,11 @@
174 if( !dryRunFlag ){
175 dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
176 }
177
178 if( g.argc<3 ){
179 usage("changes|clean|extras|ignore|list|ls|pull|push|rebuild|sync");
180 }
181 n = strlen(g.argv[2]);
182 db_open_config(1);
183 blob_zero(&extra);
184 zCmd = g.argv[2];
@@ -284,10 +286,13 @@
284 }else{
285 db_multi_exec("%s", blob_sql_text(&sql));
286 }
287 }
288 db_end_transaction(0);
 
 
 
289 return;
290 }else if( strncmp(zCmd, "add", n)==0 ){
291 int j;
292 Blob fn = BLOB_INITIALIZER;
293 Blob sql = BLOB_INITIALIZER;
@@ -313,18 +318,22 @@
313 }else{
314 db_multi_exec("%s", blob_sql_text(&sql));
315 }
316 }
317 db_end_transaction(0);
 
 
 
318 return;
319 }else if( strncmp(zCmd, "info", n)==0 ){
320 zCmd = "info";
321 showLabel = 1;
322 quiet = 1;
323 }else{
324 fossil_fatal("\"all\" subcommand should be one of: "
325 "changes clean extras ignore list ls push pull rebuild sync");
 
326 }
327 verify_all_options();
328 zFossil = quoteFilename(g.nameOfExe);
329 db_multi_exec("CREATE TEMP TABLE repolist(name,tag);");
330 if( useCheckouts ){
@@ -382,10 +391,12 @@
382 if( stopOnError && rc ){
383 break;
384 }
385 }
386 db_finalize(&q);
 
 
387
388 /* If any repositories whose names appear in the ~/.fossil file could not
389 ** be found, remove those names from the ~/.fossil file.
390 */
391 if( nToDel>0 ){
392
--- src/allrepo.c
+++ src/allrepo.c
@@ -87,63 +87,65 @@
87 ** On Win32 systems, the file is named "_fossil" and is located in
88 ** %LOCALAPPDATA%, %APPDATA% or %HOMEPATH%.
89 **
90 ** Available operations are:
91 **
92 ** changes Shows all local checkouts that have uncommitted changes.
93 ** This operation has no additional options.
94 **
95 ** clean Delete all "extra" files in all local checkouts. Extreme
96 ** caution should be exercised with this command because its
97 ** effects cannot be undone. Use of the --dry-run option to
98 ** carefully review the local checkouts to be operated upon
99 ** and the --whatif option to carefully review the files to
100 ** be deleted beforehand is highly recommended. The command
101 ** line options supported by the clean command itself, if any
102 ** are present, are passed along verbatim.
103 **
104 ** dbstat Run the "dbstat" command on all repositories.
105 **
106 ** extras Shows "extra" files from all local checkouts. The command
107 ** line options supported by the extra command itself, if any
108 ** are present, are passed along verbatim.
109 **
110 ** fts-config Run the "fts-config" command on all repositories.
111 **
112 ** info Run the "info" command on all repositories.
113 **
114 ** pull Run a "pull" operation on all repositories. Only the
115 ** --verbose option is supported.
116 **
117 ** push Run a "push" on all repositories. Only the --verbose
118 ** option is supported.
119 **
120 ** rebuild Rebuild on all repositories. The command line options
121 ** supported by the rebuild command itself, if any are
122 ** present, are passed along verbatim. The --force and
123 ** --randomize options are not supported.
124 **
125 ** sync Run a "sync" on all repositories. Only the --verbose
126 ** option is supported.
127 **
128 ** setting Run the "setting", "set", or "unset" commands on all
129 ** set repositories. These command are particularly useful in
130 ** unset conjunction with the "max-loadavg" setting which cannot
131 ** otherwise be set globally.
132 **
133 ** In addition, the following maintenance operations are supported:
134 **
135 ** add Add all the repositories named to the set of repositories
136 ** tracked by Fossil. Normally Fossil is able to keep up with
137 ** this list by itself, but sometime it can benefit from this
138 ** hint if you rename repositories.
139 **
140 ** ignore Arguments are repositories that should be ignored by
141 ** subsequent clean, extras, list, pull, push, rebuild, and
142 ** sync operations. The -c|--ckout option causes the listed
143 ** local checkouts to be ignored instead.
144 **
145 ** list | ls Display the location of all repositories. The -c|--ckout
146 ** option causes all local checkouts to be listed instead.
147 **
148 ** Repositories are automatically added to the set of known repositories
149 ** when one of the following commands are run against the repository:
150 ** clone, info, pull, push, or sync. Even previously ignored repositories
151 ** are added back to the list of repositories by these commands.
@@ -174,11 +176,11 @@
176 if( !dryRunFlag ){
177 dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
178 }
179
180 if( g.argc<3 ){
181 usage("SUBCOMMAND ...");
182 }
183 n = strlen(g.argv[2]);
184 db_open_config(1);
185 blob_zero(&extra);
186 zCmd = g.argv[2];
@@ -284,10 +286,13 @@
286 }else{
287 db_multi_exec("%s", blob_sql_text(&sql));
288 }
289 }
290 db_end_transaction(0);
291 blob_reset(&sql);
292 blob_reset(&fn);
293 blob_reset(&extra);
294 return;
295 }else if( strncmp(zCmd, "add", n)==0 ){
296 int j;
297 Blob fn = BLOB_INITIALIZER;
298 Blob sql = BLOB_INITIALIZER;
@@ -313,18 +318,22 @@
318 }else{
319 db_multi_exec("%s", blob_sql_text(&sql));
320 }
321 }
322 db_end_transaction(0);
323 blob_reset(&sql);
324 blob_reset(&fn);
325 blob_reset(&extra);
326 return;
327 }else if( strncmp(zCmd, "info", n)==0 ){
328 zCmd = "info";
329 showLabel = 1;
330 quiet = 1;
331 }else{
332 fossil_fatal("\"all\" subcommand should be one of: "
333 "add changes clean dbstat extras fts-config ignore "
334 "info list ls pull push rebuild setting sync unset");
335 }
336 verify_all_options();
337 zFossil = quoteFilename(g.nameOfExe);
338 db_multi_exec("CREATE TEMP TABLE repolist(name,tag);");
339 if( useCheckouts ){
@@ -382,10 +391,12 @@
391 if( stopOnError && rc ){
392 break;
393 }
394 }
395 db_finalize(&q);
396
397 blob_reset(&extra);
398
399 /* If any repositories whose names appear in the ~/.fossil file could not
400 ** be found, remove those names from the ~/.fossil file.
401 */
402 if( nToDel>0 ){
403
+52 -14
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -317,11 +317,11 @@
317317
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
318318
** [sqlite_version()] and [sqlite_source_id()].
319319
*/
320320
#define SQLITE_VERSION "3.8.9"
321321
#define SQLITE_VERSION_NUMBER 3008009
322
-#define SQLITE_SOURCE_ID "2015-03-30 23:43:56 395bb3e677a6551b06ba96fc58c393132b93d1e8"
322
+#define SQLITE_SOURCE_ID "2015-04-03 20:33:33 4ae9a3acc4eeeb7998769eb856c97c2233476f72"
323323
324324
/*
325325
** CAPI3REF: Run-Time Library Version Numbers
326326
** KEYWORDS: sqlite3_version, sqlite3_sourceid
327327
**
@@ -29147,11 +29147,11 @@
2914729147
*/
2914829148
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
2914929149
unixFile *pFile = (unixFile*)id;
2915029150
switch( op ){
2915129151
case SQLITE_FCNTL_WAL_BLOCK: {
29152
- pFile->ctrlFlags |= UNIXFILE_BLOCK;
29152
+ /* pFile->ctrlFlags |= UNIXFILE_BLOCK; // Deferred feature */
2915329153
return SQLITE_OK;
2915429154
}
2915529155
case SQLITE_FCNTL_LOCKSTATE: {
2915629156
*(int*)pArg = pFile->eFileLock;
2915729157
return SQLITE_OK;
@@ -33323,12 +33323,14 @@
3332333323
3332433324
WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
3332533325
#endif /* SQLITE_OS_WINRT */
3332633326
3332733327
/*
33328
-** This file mapping API is common to both Win32 and WinRT.
33328
+** These file mapping APIs are common to both Win32 and WinRT.
3332933329
*/
33330
+
33331
+WINBASEAPI BOOL WINAPI FlushViewOfFile(LPCVOID, SIZE_T);
3333033332
WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
3333133333
#endif /* SQLITE_WIN32_FILEMAPPING_API */
3333233334
3333333335
/*
3333433336
** Some Microsoft compilers lack this definition.
@@ -34209,10 +34211,19 @@
3420934211
#endif
3421034212
3421134213
#define osUuidCreateSequential \
3421234214
((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent)
3421334215
34216
+#if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0
34217
+ { "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 },
34218
+#else
34219
+ { "FlushViewOfFile", (SYSCALL)0, 0 },
34220
+#endif
34221
+
34222
+#define osFlushViewOfFile \
34223
+ ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent)
34224
+
3421434225
}; /* End of the overrideable system calls */
3421534226
3421634227
/*
3421734228
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
3421834229
** "win32" VFSes. Return SQLITE_OK opon successfully updating the
@@ -35094,11 +35105,11 @@
3509435105
/*
3509535106
** Log a I/O error retry episode.
3509635107
*/
3509735108
static void winLogIoerr(int nRetry, int lineno){
3509835109
if( nRetry ){
35099
- sqlite3_log(SQLITE_IOERR,
35110
+ sqlite3_log(SQLITE_NOTICE,
3510035111
"delayed %dms for lock/sharing conflict at line %d",
3510135112
winIoerrRetryDelay*nRetry*(nRetry+1)/2, lineno
3510235113
);
3510335114
}
3510435115
}
@@ -35914,10 +35925,26 @@
3591435925
#ifdef SQLITE_NO_SYNC
3591535926
OSTRACE(("SYNC-NOP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
3591635927
osGetCurrentProcessId(), pFile, pFile->h));
3591735928
return SQLITE_OK;
3591835929
#else
35930
+#if SQLITE_MAX_MMAP_SIZE>0
35931
+ if( pFile->pMapRegion ){
35932
+ if( osFlushViewOfFile(pFile->pMapRegion, 0) ){
35933
+ OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, "
35934
+ "rc=SQLITE_OK\n", osGetCurrentProcessId(),
35935
+ pFile, pFile->pMapRegion));
35936
+ }else{
35937
+ pFile->lastErrno = osGetLastError();
35938
+ OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, "
35939
+ "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(),
35940
+ pFile, pFile->pMapRegion));
35941
+ return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
35942
+ "winSync1", pFile->zPath);
35943
+ }
35944
+ }
35945
+#endif
3591935946
rc = osFlushFileBuffers(pFile->h);
3592035947
SimulateIOError( rc=FALSE );
3592135948
if( rc ){
3592235949
OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
3592335950
osGetCurrentProcessId(), pFile, pFile->h));
@@ -35925,11 +35952,11 @@
3592535952
}else{
3592635953
pFile->lastErrno = osGetLastError();
3592735954
OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_FSYNC\n",
3592835955
osGetCurrentProcessId(), pFile, pFile->h));
3592935956
return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno,
35930
- "winSync", pFile->zPath);
35957
+ "winSync2", pFile->zPath);
3593135958
}
3593235959
#endif
3593335960
}
3593435961
3593535962
/*
@@ -38699,11 +38726,11 @@
3869938726
};
3870038727
#endif
3870138728
3870238729
/* Double-check that the aSyscall[] array has been constructed
3870338730
** correctly. See ticket [bb3a86e890c8e96ab] */
38704
- assert( ArraySize(aSyscall)==79 );
38731
+ assert( ArraySize(aSyscall)==80 );
3870538732
3870638733
/* get memory map allocation granularity */
3870738734
memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
3870838735
#if SQLITE_OS_WINRT
3870938736
osGetNativeSystemInfo(&winSysInfo);
@@ -52246,10 +52273,11 @@
5224652273
u8 noPayload; /* True if internal intKey page (thus w/o data) */
5224752274
u8 leaf; /* True if a leaf page */
5224852275
u8 hdrOffset; /* 100 for page 1. 0 otherwise */
5224952276
u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
5225052277
u8 max1bytePayload; /* min(maxLocal,127) */
52278
+ u8 bBusy; /* Prevent endless loops on corrupt database files */
5225152279
u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
5225252280
u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */
5225352281
u16 cellOffset; /* Index in aData of first cell pointer */
5225452282
u16 nFree; /* Number of free bytes on the page */
5225552283
u16 nCell; /* Number of cells on this page, local and ovfl */
@@ -54894,20 +54922,22 @@
5489454922
** If this Btree is a candidate for shared cache, try to find an
5489554923
** existing BtShared object that we can share with
5489654924
*/
5489754925
if( isTempDb==0 && (isMemdb==0 || (vfsFlags&SQLITE_OPEN_URI)!=0) ){
5489854926
if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){
54927
+ int nFilename = sqlite3Strlen30(zFilename)+1;
5489954928
int nFullPathname = pVfs->mxPathname+1;
54900
- char *zFullPathname = sqlite3Malloc(nFullPathname);
54929
+ char *zFullPathname = sqlite3Malloc(MAX(nFullPathname,nFilename));
5490154930
MUTEX_LOGIC( sqlite3_mutex *mutexShared; )
54931
+
5490254932
p->sharable = 1;
5490354933
if( !zFullPathname ){
5490454934
sqlite3_free(p);
5490554935
return SQLITE_NOMEM;
5490654936
}
5490754937
if( isMemdb ){
54908
- memcpy(zFullPathname, zFilename, sqlite3Strlen30(zFilename)+1);
54938
+ memcpy(zFullPathname, zFilename, nFilename);
5490954939
}else{
5491054940
rc = sqlite3OsFullPathname(pVfs, zFilename,
5491154941
nFullPathname, zFullPathname);
5491254942
if( rc ){
5491354943
sqlite3_free(zFullPathname);
@@ -60913,32 +60943,33 @@
6091360943
int rc;
6091460944
unsigned char *pCell;
6091560945
int i;
6091660946
int hdr;
6091760947
u16 szCell;
60918
- u8 hasChildren;
6091960948
6092060949
assert( sqlite3_mutex_held(pBt->mutex) );
6092160950
if( pgno>btreePagecount(pBt) ){
6092260951
return SQLITE_CORRUPT_BKPT;
6092360952
}
60924
-
6092560953
rc = getAndInitPage(pBt, pgno, &pPage, 0);
6092660954
if( rc ) return rc;
60927
- hasChildren = !pPage->leaf;
60928
- pPage->leaf = 1; /* Block looping if the database is corrupt */
60955
+ if( pPage->bBusy ){
60956
+ rc = SQLITE_CORRUPT_BKPT;
60957
+ goto cleardatabasepage_out;
60958
+ }
60959
+ pPage->bBusy = 1;
6092960960
hdr = pPage->hdrOffset;
6093060961
for(i=0; i<pPage->nCell; i++){
6093160962
pCell = findCell(pPage, i);
60932
- if( hasChildren ){
60963
+ if( !pPage->leaf ){
6093360964
rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
6093460965
if( rc ) goto cleardatabasepage_out;
6093560966
}
6093660967
rc = clearCell(pPage, pCell, &szCell);
6093760968
if( rc ) goto cleardatabasepage_out;
6093860969
}
60939
- if( hasChildren ){
60970
+ if( !pPage->leaf ){
6094060971
rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
6094160972
if( rc ) goto cleardatabasepage_out;
6094260973
}else if( pnChange ){
6094360974
assert( pPage->intKey );
6094460975
*pnChange += pPage->nCell;
@@ -60948,10 +60979,11 @@
6094860979
}else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){
6094960980
zeroPage(pPage, pPage->aData[hdr] | PTF_LEAF);
6095060981
}
6095160982
6095260983
cleardatabasepage_out:
60984
+ pPage->bBusy = 0;
6095360985
releasePage(pPage);
6095460986
return rc;
6095560987
}
6095660988
6095760989
/*
@@ -72561,15 +72593,19 @@
7256172593
}else if( affinity==SQLITE_AFF_TEXT ){
7256272594
if( (pIn1->flags & MEM_Str)==0 && (pIn1->flags & (MEM_Int|MEM_Real))!=0 ){
7256372595
testcase( pIn1->flags & MEM_Int );
7256472596
testcase( pIn1->flags & MEM_Real );
7256572597
sqlite3VdbeMemStringify(pIn1, encoding, 1);
72598
+ testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) );
72599
+ flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
7256672600
}
7256772601
if( (pIn3->flags & MEM_Str)==0 && (pIn3->flags & (MEM_Int|MEM_Real))!=0 ){
7256872602
testcase( pIn3->flags & MEM_Int );
7256972603
testcase( pIn3->flags & MEM_Real );
7257072604
sqlite3VdbeMemStringify(pIn3, encoding, 1);
72605
+ testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) );
72606
+ flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask);
7257172607
}
7257272608
}
7257372609
assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
7257472610
if( pIn1->flags & MEM_Zero ){
7257572611
sqlite3VdbeMemExpandBlob(pIn1);
@@ -72602,11 +72638,13 @@
7260272638
if( res ){
7260372639
pc = pOp->p2-1;
7260472640
}
7260572641
}
7260672642
/* Undo any changes made by applyAffinity() to the input registers. */
72643
+ assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
7260772644
pIn1->flags = flags1;
72645
+ assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) );
7260872646
pIn3->flags = flags3;
7260972647
break;
7261072648
}
7261172649
7261272650
/* Opcode: Permutation * * * P4 *
7261372651
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -317,11 +317,11 @@
317 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
318 ** [sqlite_version()] and [sqlite_source_id()].
319 */
320 #define SQLITE_VERSION "3.8.9"
321 #define SQLITE_VERSION_NUMBER 3008009
322 #define SQLITE_SOURCE_ID "2015-03-30 23:43:56 395bb3e677a6551b06ba96fc58c393132b93d1e8"
323
324 /*
325 ** CAPI3REF: Run-Time Library Version Numbers
326 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
327 **
@@ -29147,11 +29147,11 @@
29147 */
29148 static int unixFileControl(sqlite3_file *id, int op, void *pArg){
29149 unixFile *pFile = (unixFile*)id;
29150 switch( op ){
29151 case SQLITE_FCNTL_WAL_BLOCK: {
29152 pFile->ctrlFlags |= UNIXFILE_BLOCK;
29153 return SQLITE_OK;
29154 }
29155 case SQLITE_FCNTL_LOCKSTATE: {
29156 *(int*)pArg = pFile->eFileLock;
29157 return SQLITE_OK;
@@ -33323,12 +33323,14 @@
33323
33324 WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
33325 #endif /* SQLITE_OS_WINRT */
33326
33327 /*
33328 ** This file mapping API is common to both Win32 and WinRT.
33329 */
 
 
33330 WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
33331 #endif /* SQLITE_WIN32_FILEMAPPING_API */
33332
33333 /*
33334 ** Some Microsoft compilers lack this definition.
@@ -34209,10 +34211,19 @@
34209 #endif
34210
34211 #define osUuidCreateSequential \
34212 ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent)
34213
 
 
 
 
 
 
 
 
 
34214 }; /* End of the overrideable system calls */
34215
34216 /*
34217 ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
34218 ** "win32" VFSes. Return SQLITE_OK opon successfully updating the
@@ -35094,11 +35105,11 @@
35094 /*
35095 ** Log a I/O error retry episode.
35096 */
35097 static void winLogIoerr(int nRetry, int lineno){
35098 if( nRetry ){
35099 sqlite3_log(SQLITE_IOERR,
35100 "delayed %dms for lock/sharing conflict at line %d",
35101 winIoerrRetryDelay*nRetry*(nRetry+1)/2, lineno
35102 );
35103 }
35104 }
@@ -35914,10 +35925,26 @@
35914 #ifdef SQLITE_NO_SYNC
35915 OSTRACE(("SYNC-NOP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
35916 osGetCurrentProcessId(), pFile, pFile->h));
35917 return SQLITE_OK;
35918 #else
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35919 rc = osFlushFileBuffers(pFile->h);
35920 SimulateIOError( rc=FALSE );
35921 if( rc ){
35922 OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
35923 osGetCurrentProcessId(), pFile, pFile->h));
@@ -35925,11 +35952,11 @@
35925 }else{
35926 pFile->lastErrno = osGetLastError();
35927 OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_FSYNC\n",
35928 osGetCurrentProcessId(), pFile, pFile->h));
35929 return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno,
35930 "winSync", pFile->zPath);
35931 }
35932 #endif
35933 }
35934
35935 /*
@@ -38699,11 +38726,11 @@
38699 };
38700 #endif
38701
38702 /* Double-check that the aSyscall[] array has been constructed
38703 ** correctly. See ticket [bb3a86e890c8e96ab] */
38704 assert( ArraySize(aSyscall)==79 );
38705
38706 /* get memory map allocation granularity */
38707 memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
38708 #if SQLITE_OS_WINRT
38709 osGetNativeSystemInfo(&winSysInfo);
@@ -52246,10 +52273,11 @@
52246 u8 noPayload; /* True if internal intKey page (thus w/o data) */
52247 u8 leaf; /* True if a leaf page */
52248 u8 hdrOffset; /* 100 for page 1. 0 otherwise */
52249 u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
52250 u8 max1bytePayload; /* min(maxLocal,127) */
 
52251 u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
52252 u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */
52253 u16 cellOffset; /* Index in aData of first cell pointer */
52254 u16 nFree; /* Number of free bytes on the page */
52255 u16 nCell; /* Number of cells on this page, local and ovfl */
@@ -54894,20 +54922,22 @@
54894 ** If this Btree is a candidate for shared cache, try to find an
54895 ** existing BtShared object that we can share with
54896 */
54897 if( isTempDb==0 && (isMemdb==0 || (vfsFlags&SQLITE_OPEN_URI)!=0) ){
54898 if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){
 
54899 int nFullPathname = pVfs->mxPathname+1;
54900 char *zFullPathname = sqlite3Malloc(nFullPathname);
54901 MUTEX_LOGIC( sqlite3_mutex *mutexShared; )
 
54902 p->sharable = 1;
54903 if( !zFullPathname ){
54904 sqlite3_free(p);
54905 return SQLITE_NOMEM;
54906 }
54907 if( isMemdb ){
54908 memcpy(zFullPathname, zFilename, sqlite3Strlen30(zFilename)+1);
54909 }else{
54910 rc = sqlite3OsFullPathname(pVfs, zFilename,
54911 nFullPathname, zFullPathname);
54912 if( rc ){
54913 sqlite3_free(zFullPathname);
@@ -60913,32 +60943,33 @@
60913 int rc;
60914 unsigned char *pCell;
60915 int i;
60916 int hdr;
60917 u16 szCell;
60918 u8 hasChildren;
60919
60920 assert( sqlite3_mutex_held(pBt->mutex) );
60921 if( pgno>btreePagecount(pBt) ){
60922 return SQLITE_CORRUPT_BKPT;
60923 }
60924
60925 rc = getAndInitPage(pBt, pgno, &pPage, 0);
60926 if( rc ) return rc;
60927 hasChildren = !pPage->leaf;
60928 pPage->leaf = 1; /* Block looping if the database is corrupt */
 
 
 
60929 hdr = pPage->hdrOffset;
60930 for(i=0; i<pPage->nCell; i++){
60931 pCell = findCell(pPage, i);
60932 if( hasChildren ){
60933 rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
60934 if( rc ) goto cleardatabasepage_out;
60935 }
60936 rc = clearCell(pPage, pCell, &szCell);
60937 if( rc ) goto cleardatabasepage_out;
60938 }
60939 if( hasChildren ){
60940 rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
60941 if( rc ) goto cleardatabasepage_out;
60942 }else if( pnChange ){
60943 assert( pPage->intKey );
60944 *pnChange += pPage->nCell;
@@ -60948,10 +60979,11 @@
60948 }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){
60949 zeroPage(pPage, pPage->aData[hdr] | PTF_LEAF);
60950 }
60951
60952 cleardatabasepage_out:
 
60953 releasePage(pPage);
60954 return rc;
60955 }
60956
60957 /*
@@ -72561,15 +72593,19 @@
72561 }else if( affinity==SQLITE_AFF_TEXT ){
72562 if( (pIn1->flags & MEM_Str)==0 && (pIn1->flags & (MEM_Int|MEM_Real))!=0 ){
72563 testcase( pIn1->flags & MEM_Int );
72564 testcase( pIn1->flags & MEM_Real );
72565 sqlite3VdbeMemStringify(pIn1, encoding, 1);
 
 
72566 }
72567 if( (pIn3->flags & MEM_Str)==0 && (pIn3->flags & (MEM_Int|MEM_Real))!=0 ){
72568 testcase( pIn3->flags & MEM_Int );
72569 testcase( pIn3->flags & MEM_Real );
72570 sqlite3VdbeMemStringify(pIn3, encoding, 1);
 
 
72571 }
72572 }
72573 assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
72574 if( pIn1->flags & MEM_Zero ){
72575 sqlite3VdbeMemExpandBlob(pIn1);
@@ -72602,11 +72638,13 @@
72602 if( res ){
72603 pc = pOp->p2-1;
72604 }
72605 }
72606 /* Undo any changes made by applyAffinity() to the input registers. */
 
72607 pIn1->flags = flags1;
 
72608 pIn3->flags = flags3;
72609 break;
72610 }
72611
72612 /* Opcode: Permutation * * * P4 *
72613
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -317,11 +317,11 @@
317 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
318 ** [sqlite_version()] and [sqlite_source_id()].
319 */
320 #define SQLITE_VERSION "3.8.9"
321 #define SQLITE_VERSION_NUMBER 3008009
322 #define SQLITE_SOURCE_ID "2015-04-03 20:33:33 4ae9a3acc4eeeb7998769eb856c97c2233476f72"
323
324 /*
325 ** CAPI3REF: Run-Time Library Version Numbers
326 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
327 **
@@ -29147,11 +29147,11 @@
29147 */
29148 static int unixFileControl(sqlite3_file *id, int op, void *pArg){
29149 unixFile *pFile = (unixFile*)id;
29150 switch( op ){
29151 case SQLITE_FCNTL_WAL_BLOCK: {
29152 /* pFile->ctrlFlags |= UNIXFILE_BLOCK; // Deferred feature */
29153 return SQLITE_OK;
29154 }
29155 case SQLITE_FCNTL_LOCKSTATE: {
29156 *(int*)pArg = pFile->eFileLock;
29157 return SQLITE_OK;
@@ -33323,12 +33323,14 @@
33323
33324 WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
33325 #endif /* SQLITE_OS_WINRT */
33326
33327 /*
33328 ** These file mapping APIs are common to both Win32 and WinRT.
33329 */
33330
33331 WINBASEAPI BOOL WINAPI FlushViewOfFile(LPCVOID, SIZE_T);
33332 WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
33333 #endif /* SQLITE_WIN32_FILEMAPPING_API */
33334
33335 /*
33336 ** Some Microsoft compilers lack this definition.
@@ -34209,10 +34211,19 @@
34211 #endif
34212
34213 #define osUuidCreateSequential \
34214 ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent)
34215
34216 #if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0
34217 { "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 },
34218 #else
34219 { "FlushViewOfFile", (SYSCALL)0, 0 },
34220 #endif
34221
34222 #define osFlushViewOfFile \
34223 ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent)
34224
34225 }; /* End of the overrideable system calls */
34226
34227 /*
34228 ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
34229 ** "win32" VFSes. Return SQLITE_OK opon successfully updating the
@@ -35094,11 +35105,11 @@
35105 /*
35106 ** Log a I/O error retry episode.
35107 */
35108 static void winLogIoerr(int nRetry, int lineno){
35109 if( nRetry ){
35110 sqlite3_log(SQLITE_NOTICE,
35111 "delayed %dms for lock/sharing conflict at line %d",
35112 winIoerrRetryDelay*nRetry*(nRetry+1)/2, lineno
35113 );
35114 }
35115 }
@@ -35914,10 +35925,26 @@
35925 #ifdef SQLITE_NO_SYNC
35926 OSTRACE(("SYNC-NOP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
35927 osGetCurrentProcessId(), pFile, pFile->h));
35928 return SQLITE_OK;
35929 #else
35930 #if SQLITE_MAX_MMAP_SIZE>0
35931 if( pFile->pMapRegion ){
35932 if( osFlushViewOfFile(pFile->pMapRegion, 0) ){
35933 OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, "
35934 "rc=SQLITE_OK\n", osGetCurrentProcessId(),
35935 pFile, pFile->pMapRegion));
35936 }else{
35937 pFile->lastErrno = osGetLastError();
35938 OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, "
35939 "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(),
35940 pFile, pFile->pMapRegion));
35941 return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
35942 "winSync1", pFile->zPath);
35943 }
35944 }
35945 #endif
35946 rc = osFlushFileBuffers(pFile->h);
35947 SimulateIOError( rc=FALSE );
35948 if( rc ){
35949 OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
35950 osGetCurrentProcessId(), pFile, pFile->h));
@@ -35925,11 +35952,11 @@
35952 }else{
35953 pFile->lastErrno = osGetLastError();
35954 OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_FSYNC\n",
35955 osGetCurrentProcessId(), pFile, pFile->h));
35956 return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno,
35957 "winSync2", pFile->zPath);
35958 }
35959 #endif
35960 }
35961
35962 /*
@@ -38699,11 +38726,11 @@
38726 };
38727 #endif
38728
38729 /* Double-check that the aSyscall[] array has been constructed
38730 ** correctly. See ticket [bb3a86e890c8e96ab] */
38731 assert( ArraySize(aSyscall)==80 );
38732
38733 /* get memory map allocation granularity */
38734 memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
38735 #if SQLITE_OS_WINRT
38736 osGetNativeSystemInfo(&winSysInfo);
@@ -52246,10 +52273,11 @@
52273 u8 noPayload; /* True if internal intKey page (thus w/o data) */
52274 u8 leaf; /* True if a leaf page */
52275 u8 hdrOffset; /* 100 for page 1. 0 otherwise */
52276 u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
52277 u8 max1bytePayload; /* min(maxLocal,127) */
52278 u8 bBusy; /* Prevent endless loops on corrupt database files */
52279 u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
52280 u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */
52281 u16 cellOffset; /* Index in aData of first cell pointer */
52282 u16 nFree; /* Number of free bytes on the page */
52283 u16 nCell; /* Number of cells on this page, local and ovfl */
@@ -54894,20 +54922,22 @@
54922 ** If this Btree is a candidate for shared cache, try to find an
54923 ** existing BtShared object that we can share with
54924 */
54925 if( isTempDb==0 && (isMemdb==0 || (vfsFlags&SQLITE_OPEN_URI)!=0) ){
54926 if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){
54927 int nFilename = sqlite3Strlen30(zFilename)+1;
54928 int nFullPathname = pVfs->mxPathname+1;
54929 char *zFullPathname = sqlite3Malloc(MAX(nFullPathname,nFilename));
54930 MUTEX_LOGIC( sqlite3_mutex *mutexShared; )
54931
54932 p->sharable = 1;
54933 if( !zFullPathname ){
54934 sqlite3_free(p);
54935 return SQLITE_NOMEM;
54936 }
54937 if( isMemdb ){
54938 memcpy(zFullPathname, zFilename, nFilename);
54939 }else{
54940 rc = sqlite3OsFullPathname(pVfs, zFilename,
54941 nFullPathname, zFullPathname);
54942 if( rc ){
54943 sqlite3_free(zFullPathname);
@@ -60913,32 +60943,33 @@
60943 int rc;
60944 unsigned char *pCell;
60945 int i;
60946 int hdr;
60947 u16 szCell;
 
60948
60949 assert( sqlite3_mutex_held(pBt->mutex) );
60950 if( pgno>btreePagecount(pBt) ){
60951 return SQLITE_CORRUPT_BKPT;
60952 }
 
60953 rc = getAndInitPage(pBt, pgno, &pPage, 0);
60954 if( rc ) return rc;
60955 if( pPage->bBusy ){
60956 rc = SQLITE_CORRUPT_BKPT;
60957 goto cleardatabasepage_out;
60958 }
60959 pPage->bBusy = 1;
60960 hdr = pPage->hdrOffset;
60961 for(i=0; i<pPage->nCell; i++){
60962 pCell = findCell(pPage, i);
60963 if( !pPage->leaf ){
60964 rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
60965 if( rc ) goto cleardatabasepage_out;
60966 }
60967 rc = clearCell(pPage, pCell, &szCell);
60968 if( rc ) goto cleardatabasepage_out;
60969 }
60970 if( !pPage->leaf ){
60971 rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
60972 if( rc ) goto cleardatabasepage_out;
60973 }else if( pnChange ){
60974 assert( pPage->intKey );
60975 *pnChange += pPage->nCell;
@@ -60948,10 +60979,11 @@
60979 }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){
60980 zeroPage(pPage, pPage->aData[hdr] | PTF_LEAF);
60981 }
60982
60983 cleardatabasepage_out:
60984 pPage->bBusy = 0;
60985 releasePage(pPage);
60986 return rc;
60987 }
60988
60989 /*
@@ -72561,15 +72593,19 @@
72593 }else if( affinity==SQLITE_AFF_TEXT ){
72594 if( (pIn1->flags & MEM_Str)==0 && (pIn1->flags & (MEM_Int|MEM_Real))!=0 ){
72595 testcase( pIn1->flags & MEM_Int );
72596 testcase( pIn1->flags & MEM_Real );
72597 sqlite3VdbeMemStringify(pIn1, encoding, 1);
72598 testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) );
72599 flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
72600 }
72601 if( (pIn3->flags & MEM_Str)==0 && (pIn3->flags & (MEM_Int|MEM_Real))!=0 ){
72602 testcase( pIn3->flags & MEM_Int );
72603 testcase( pIn3->flags & MEM_Real );
72604 sqlite3VdbeMemStringify(pIn3, encoding, 1);
72605 testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) );
72606 flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask);
72607 }
72608 }
72609 assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
72610 if( pIn1->flags & MEM_Zero ){
72611 sqlite3VdbeMemExpandBlob(pIn1);
@@ -72602,11 +72638,13 @@
72638 if( res ){
72639 pc = pOp->p2-1;
72640 }
72641 }
72642 /* Undo any changes made by applyAffinity() to the input registers. */
72643 assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
72644 pIn1->flags = flags1;
72645 assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) );
72646 pIn3->flags = flags3;
72647 break;
72648 }
72649
72650 /* Opcode: Permutation * * * P4 *
72651
+1 -1
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -111,11 +111,11 @@
111111
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
112112
** [sqlite_version()] and [sqlite_source_id()].
113113
*/
114114
#define SQLITE_VERSION "3.8.9"
115115
#define SQLITE_VERSION_NUMBER 3008009
116
-#define SQLITE_SOURCE_ID "2015-03-30 23:43:56 395bb3e677a6551b06ba96fc58c393132b93d1e8"
116
+#define SQLITE_SOURCE_ID "2015-04-03 20:33:33 4ae9a3acc4eeeb7998769eb856c97c2233476f72"
117117
118118
/*
119119
** CAPI3REF: Run-Time Library Version Numbers
120120
** KEYWORDS: sqlite3_version, sqlite3_sourceid
121121
**
122122
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -111,11 +111,11 @@
111 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
112 ** [sqlite_version()] and [sqlite_source_id()].
113 */
114 #define SQLITE_VERSION "3.8.9"
115 #define SQLITE_VERSION_NUMBER 3008009
116 #define SQLITE_SOURCE_ID "2015-03-30 23:43:56 395bb3e677a6551b06ba96fc58c393132b93d1e8"
117
118 /*
119 ** CAPI3REF: Run-Time Library Version Numbers
120 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
121 **
122
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -111,11 +111,11 @@
111 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
112 ** [sqlite_version()] and [sqlite_source_id()].
113 */
114 #define SQLITE_VERSION "3.8.9"
115 #define SQLITE_VERSION_NUMBER 3008009
116 #define SQLITE_SOURCE_ID "2015-04-03 20:33:33 4ae9a3acc4eeeb7998769eb856c97c2233476f72"
117
118 /*
119 ** CAPI3REF: Run-Time Library Version Numbers
120 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
121 **
122
+69 -3
--- src/th.c
+++ src/th.c
@@ -7,13 +7,14 @@
77
#include "config.h"
88
#include "th.h"
99
#include <string.h>
1010
#include <assert.h>
1111
12
-typedef struct Th_Command Th_Command;
13
-typedef struct Th_Frame Th_Frame;
14
-typedef struct Th_Variable Th_Variable;
12
+typedef struct Th_Command Th_Command;
13
+typedef struct Th_Frame Th_Frame;
14
+typedef struct Th_Variable Th_Variable;
15
+typedef struct Th_InterpAndList Th_InterpAndList;
1516
1617
/*
1718
** Interpreter structure.
1819
*/
1920
struct Th_Interp {
@@ -87,10 +88,21 @@
8788
int nRef; /* Number of references to this structure */
8889
int nData; /* Number of bytes at Th_Variable.zData */
8990
char *zData; /* Data for scalar variables */
9091
Th_Hash *pHash; /* Data for array variables */
9192
};
93
+
94
+/*
95
+** This structure is used to pass complete context information to the
96
+** hash iteration callback functions that need a Th_Interp and a list
97
+** to operate on, e.g. thListAppendHashKey().
98
+*/
99
+struct Th_InterpAndList {
100
+ Th_Interp *interp; /* Associated interpreter context */
101
+ char **pzList; /* IN/OUT: Ptr to ptr to list */
102
+ int *pnList; /* IN/OUT: Current length of *pzList */
103
+};
92104
93105
/*
94106
** Hash table API:
95107
*/
96108
#define TH_HASHSIZE 257
@@ -298,10 +310,25 @@
298310
}
299311
Th_Free((Th_Interp *)pContext, pEntry->pData);
300312
pEntry->pData = 0;
301313
return 1;
302314
}
315
+
316
+/*
317
+** Argument pEntry points to an entry in a hash table. The key is
318
+** the list element to be added.
319
+**
320
+** Argument pContext is a pointer to the Th_InterpAndList structure.
321
+**
322
+** Always returns non-zero.
323
+*/
324
+static int thListAppendHashKey(Th_HashEntry *pEntry, void *pContext){
325
+ Th_InterpAndList *pInterpAndList = (Th_InterpAndList *)pContext;
326
+ Th_ListAppend(pInterpAndList->interp, pInterpAndList->pzList,
327
+ pInterpAndList->pnList, pEntry->zKey, pEntry->nKey);
328
+ return 1;
329
+}
303330
304331
/*
305332
** Push a new frame onto the stack.
306333
*/
307334
static int thPushFrame(Th_Interp *interp, Th_Frame *pFrame){
@@ -2832,5 +2859,44 @@
28322859
}
28332860
28342861
*z = '\0';
28352862
return Th_SetResult(interp, zBuf, -1);
28362863
}
2864
+
2865
+/*
2866
+** Appends all currently registered command names to the specified list
2867
+** and returns TH_OK upon success. Any other return value indicates an
2868
+** error.
2869
+*/
2870
+int Th_ListAppendCommands(Th_Interp *interp, char **pzList, int *pnList){
2871
+ Th_InterpAndList *p = (Th_InterpAndList *)Th_Malloc(
2872
+ interp, sizeof(Th_InterpAndList)
2873
+ );
2874
+ p->interp = interp;
2875
+ p->pzList = pzList;
2876
+ p->pnList = pnList;
2877
+ Th_HashIterate(interp, interp->paCmd, thListAppendHashKey, p);
2878
+ Th_Free(interp, p);
2879
+ return TH_OK;
2880
+}
2881
+
2882
+/*
2883
+** Appends all variable names for the current frame to the specified list
2884
+** and returns TH_OK upon success. Any other return value indicates an
2885
+** error. If the current frame cannot be obtained, TH_ERROR is returned.
2886
+*/
2887
+int Th_ListAppendVariables(Th_Interp *interp, char **pzList, int *pnList){
2888
+ Th_Frame *pFrame = getFrame(interp, 0);
2889
+ if( pFrame ){
2890
+ Th_InterpAndList *p = (Th_InterpAndList *)Th_Malloc(
2891
+ interp, sizeof(Th_InterpAndList)
2892
+ );
2893
+ p->interp = interp;
2894
+ p->pzList = pzList;
2895
+ p->pnList = pnList;
2896
+ Th_HashIterate(interp, pFrame->paVar, thListAppendHashKey, p);
2897
+ Th_Free(interp, p);
2898
+ return TH_OK;
2899
+ }else{
2900
+ return TH_ERROR;
2901
+ }
2902
+}
28372903
--- src/th.c
+++ src/th.c
@@ -7,13 +7,14 @@
7 #include "config.h"
8 #include "th.h"
9 #include <string.h>
10 #include <assert.h>
11
12 typedef struct Th_Command Th_Command;
13 typedef struct Th_Frame Th_Frame;
14 typedef struct Th_Variable Th_Variable;
 
15
16 /*
17 ** Interpreter structure.
18 */
19 struct Th_Interp {
@@ -87,10 +88,21 @@
87 int nRef; /* Number of references to this structure */
88 int nData; /* Number of bytes at Th_Variable.zData */
89 char *zData; /* Data for scalar variables */
90 Th_Hash *pHash; /* Data for array variables */
91 };
 
 
 
 
 
 
 
 
 
 
 
92
93 /*
94 ** Hash table API:
95 */
96 #define TH_HASHSIZE 257
@@ -298,10 +310,25 @@
298 }
299 Th_Free((Th_Interp *)pContext, pEntry->pData);
300 pEntry->pData = 0;
301 return 1;
302 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
303
304 /*
305 ** Push a new frame onto the stack.
306 */
307 static int thPushFrame(Th_Interp *interp, Th_Frame *pFrame){
@@ -2832,5 +2859,44 @@
2832 }
2833
2834 *z = '\0';
2835 return Th_SetResult(interp, zBuf, -1);
2836 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2837
--- src/th.c
+++ src/th.c
@@ -7,13 +7,14 @@
7 #include "config.h"
8 #include "th.h"
9 #include <string.h>
10 #include <assert.h>
11
12 typedef struct Th_Command Th_Command;
13 typedef struct Th_Frame Th_Frame;
14 typedef struct Th_Variable Th_Variable;
15 typedef struct Th_InterpAndList Th_InterpAndList;
16
17 /*
18 ** Interpreter structure.
19 */
20 struct Th_Interp {
@@ -87,10 +88,21 @@
88 int nRef; /* Number of references to this structure */
89 int nData; /* Number of bytes at Th_Variable.zData */
90 char *zData; /* Data for scalar variables */
91 Th_Hash *pHash; /* Data for array variables */
92 };
93
94 /*
95 ** This structure is used to pass complete context information to the
96 ** hash iteration callback functions that need a Th_Interp and a list
97 ** to operate on, e.g. thListAppendHashKey().
98 */
99 struct Th_InterpAndList {
100 Th_Interp *interp; /* Associated interpreter context */
101 char **pzList; /* IN/OUT: Ptr to ptr to list */
102 int *pnList; /* IN/OUT: Current length of *pzList */
103 };
104
105 /*
106 ** Hash table API:
107 */
108 #define TH_HASHSIZE 257
@@ -298,10 +310,25 @@
310 }
311 Th_Free((Th_Interp *)pContext, pEntry->pData);
312 pEntry->pData = 0;
313 return 1;
314 }
315
316 /*
317 ** Argument pEntry points to an entry in a hash table. The key is
318 ** the list element to be added.
319 **
320 ** Argument pContext is a pointer to the Th_InterpAndList structure.
321 **
322 ** Always returns non-zero.
323 */
324 static int thListAppendHashKey(Th_HashEntry *pEntry, void *pContext){
325 Th_InterpAndList *pInterpAndList = (Th_InterpAndList *)pContext;
326 Th_ListAppend(pInterpAndList->interp, pInterpAndList->pzList,
327 pInterpAndList->pnList, pEntry->zKey, pEntry->nKey);
328 return 1;
329 }
330
331 /*
332 ** Push a new frame onto the stack.
333 */
334 static int thPushFrame(Th_Interp *interp, Th_Frame *pFrame){
@@ -2832,5 +2859,44 @@
2859 }
2860
2861 *z = '\0';
2862 return Th_SetResult(interp, zBuf, -1);
2863 }
2864
2865 /*
2866 ** Appends all currently registered command names to the specified list
2867 ** and returns TH_OK upon success. Any other return value indicates an
2868 ** error.
2869 */
2870 int Th_ListAppendCommands(Th_Interp *interp, char **pzList, int *pnList){
2871 Th_InterpAndList *p = (Th_InterpAndList *)Th_Malloc(
2872 interp, sizeof(Th_InterpAndList)
2873 );
2874 p->interp = interp;
2875 p->pzList = pzList;
2876 p->pnList = pnList;
2877 Th_HashIterate(interp, interp->paCmd, thListAppendHashKey, p);
2878 Th_Free(interp, p);
2879 return TH_OK;
2880 }
2881
2882 /*
2883 ** Appends all variable names for the current frame to the specified list
2884 ** and returns TH_OK upon success. Any other return value indicates an
2885 ** error. If the current frame cannot be obtained, TH_ERROR is returned.
2886 */
2887 int Th_ListAppendVariables(Th_Interp *interp, char **pzList, int *pnList){
2888 Th_Frame *pFrame = getFrame(interp, 0);
2889 if( pFrame ){
2890 Th_InterpAndList *p = (Th_InterpAndList *)Th_Malloc(
2891 interp, sizeof(Th_InterpAndList)
2892 );
2893 p->interp = interp;
2894 p->pzList = pzList;
2895 p->pnList = pnList;
2896 Th_HashIterate(interp, pFrame->paVar, thListAppendHashKey, p);
2897 Th_Free(interp, p);
2898 return TH_OK;
2899 }else{
2900 return TH_ERROR;
2901 }
2902 }
2903
+6
--- src/th.h
+++ src/th.h
@@ -138,10 +138,16 @@
138138
int Th_ToInt(Th_Interp *, const char *, int, int *);
139139
int Th_ToDouble(Th_Interp *, const char *, int, double *);
140140
int Th_SetResultInt(Th_Interp *, int);
141141
int Th_SetResultDouble(Th_Interp *, double);
142142
143
+/*
144
+** Functions for handling command and variable introspection.
145
+*/
146
+int Th_ListAppendCommands(Th_Interp *, char **, int *);
147
+int Th_ListAppendVariables(Th_Interp *, char **, int *);
148
+
143149
/*
144150
** Drop in replacements for the corresponding standard library functions.
145151
*/
146152
int th_strlen(const char *);
147153
int th_isdigit(char);
148154
--- src/th.h
+++ src/th.h
@@ -138,10 +138,16 @@
138 int Th_ToInt(Th_Interp *, const char *, int, int *);
139 int Th_ToDouble(Th_Interp *, const char *, int, double *);
140 int Th_SetResultInt(Th_Interp *, int);
141 int Th_SetResultDouble(Th_Interp *, double);
142
 
 
 
 
 
 
143 /*
144 ** Drop in replacements for the corresponding standard library functions.
145 */
146 int th_strlen(const char *);
147 int th_isdigit(char);
148
--- src/th.h
+++ src/th.h
@@ -138,10 +138,16 @@
138 int Th_ToInt(Th_Interp *, const char *, int, int *);
139 int Th_ToDouble(Th_Interp *, const char *, int, double *);
140 int Th_SetResultInt(Th_Interp *, int);
141 int Th_SetResultDouble(Th_Interp *, double);
142
143 /*
144 ** Functions for handling command and variable introspection.
145 */
146 int Th_ListAppendCommands(Th_Interp *, char **, int *);
147 int Th_ListAppendVariables(Th_Interp *, char **, int *);
148
149 /*
150 ** Drop in replacements for the corresponding standard library functions.
151 */
152 int th_strlen(const char *);
153 int th_isdigit(char);
154
+52 -2
--- src/th_lang.c
+++ src/th_lang.c
@@ -848,11 +848,11 @@
848848
}
849849
850850
/*
851851
** TH Syntax:
852852
**
853
-** info exists VAR
853
+** info exists VARNAME
854854
*/
855855
static int info_exists_command(
856856
Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl
857857
){
858858
int rc;
@@ -862,10 +862,56 @@
862862
}
863863
rc = Th_ExistsVar(interp, argv[2], argl[2]);
864864
Th_SetResultInt(interp, rc);
865865
return TH_OK;
866866
}
867
+
868
+/*
869
+** TH Syntax:
870
+**
871
+** info commands
872
+*/
873
+static int info_commands_command(
874
+ Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl
875
+){
876
+ int rc;
877
+ char *zElem = 0;
878
+ int nElem = 0;
879
+
880
+ if( argc!=2 ){
881
+ return Th_WrongNumArgs(interp, "info commands");
882
+ }
883
+ rc = Th_ListAppendCommands(interp, &zElem, &nElem);
884
+ if( rc!=TH_OK ){
885
+ return rc;
886
+ }
887
+ Th_SetResult(interp, zElem, nElem);
888
+ return TH_OK;
889
+}
890
+
891
+/*
892
+** TH Syntax:
893
+**
894
+** info vars
895
+*/
896
+static int info_vars_command(
897
+ Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl
898
+){
899
+ int rc;
900
+ char *zElem = 0;
901
+ int nElem = 0;
902
+
903
+ if( argc!=2 ){
904
+ return Th_WrongNumArgs(interp, "info vars");
905
+ }
906
+ rc = Th_ListAppendVariables(interp, &zElem, &nElem);
907
+ if( rc!=TH_OK ){
908
+ return rc;
909
+ }
910
+ Th_SetResult(interp, zElem, nElem);
911
+ return TH_OK;
912
+}
867913
868914
/*
869915
** TH Syntax:
870916
**
871917
** unset VAR
@@ -943,21 +989,25 @@
943989
}
944990
945991
/*
946992
** TH Syntax:
947993
**
994
+** info commands
948995
** info exists VARNAME
996
+** info vars
949997
*/
950998
static int info_command(
951999
Th_Interp *interp,
9521000
void *ctx,
9531001
int argc,
9541002
const char **argv,
9551003
int *argl
9561004
){
9571005
static const Th_SubCommand aSub[] = {
958
- { "exists", info_exists_command },
1006
+ { "commands", info_commands_command },
1007
+ { "exists", info_exists_command },
1008
+ { "vars", info_vars_command },
9591009
{ 0, 0 }
9601010
};
9611011
return Th_CallSubCommand(interp, ctx, argc, argv, argl, aSub);
9621012
}
9631013
9641014
--- src/th_lang.c
+++ src/th_lang.c
@@ -848,11 +848,11 @@
848 }
849
850 /*
851 ** TH Syntax:
852 **
853 ** info exists VAR
854 */
855 static int info_exists_command(
856 Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl
857 ){
858 int rc;
@@ -862,10 +862,56 @@
862 }
863 rc = Th_ExistsVar(interp, argv[2], argl[2]);
864 Th_SetResultInt(interp, rc);
865 return TH_OK;
866 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
867
868 /*
869 ** TH Syntax:
870 **
871 ** unset VAR
@@ -943,21 +989,25 @@
943 }
944
945 /*
946 ** TH Syntax:
947 **
 
948 ** info exists VARNAME
 
949 */
950 static int info_command(
951 Th_Interp *interp,
952 void *ctx,
953 int argc,
954 const char **argv,
955 int *argl
956 ){
957 static const Th_SubCommand aSub[] = {
958 { "exists", info_exists_command },
 
 
959 { 0, 0 }
960 };
961 return Th_CallSubCommand(interp, ctx, argc, argv, argl, aSub);
962 }
963
964
--- src/th_lang.c
+++ src/th_lang.c
@@ -848,11 +848,11 @@
848 }
849
850 /*
851 ** TH Syntax:
852 **
853 ** info exists VARNAME
854 */
855 static int info_exists_command(
856 Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl
857 ){
858 int rc;
@@ -862,10 +862,56 @@
862 }
863 rc = Th_ExistsVar(interp, argv[2], argl[2]);
864 Th_SetResultInt(interp, rc);
865 return TH_OK;
866 }
867
868 /*
869 ** TH Syntax:
870 **
871 ** info commands
872 */
873 static int info_commands_command(
874 Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl
875 ){
876 int rc;
877 char *zElem = 0;
878 int nElem = 0;
879
880 if( argc!=2 ){
881 return Th_WrongNumArgs(interp, "info commands");
882 }
883 rc = Th_ListAppendCommands(interp, &zElem, &nElem);
884 if( rc!=TH_OK ){
885 return rc;
886 }
887 Th_SetResult(interp, zElem, nElem);
888 return TH_OK;
889 }
890
891 /*
892 ** TH Syntax:
893 **
894 ** info vars
895 */
896 static int info_vars_command(
897 Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl
898 ){
899 int rc;
900 char *zElem = 0;
901 int nElem = 0;
902
903 if( argc!=2 ){
904 return Th_WrongNumArgs(interp, "info vars");
905 }
906 rc = Th_ListAppendVariables(interp, &zElem, &nElem);
907 if( rc!=TH_OK ){
908 return rc;
909 }
910 Th_SetResult(interp, zElem, nElem);
911 return TH_OK;
912 }
913
914 /*
915 ** TH Syntax:
916 **
917 ** unset VAR
@@ -943,21 +989,25 @@
989 }
990
991 /*
992 ** TH Syntax:
993 **
994 ** info commands
995 ** info exists VARNAME
996 ** info vars
997 */
998 static int info_command(
999 Th_Interp *interp,
1000 void *ctx,
1001 int argc,
1002 const char **argv,
1003 int *argl
1004 ){
1005 static const Th_SubCommand aSub[] = {
1006 { "commands", info_commands_command },
1007 { "exists", info_exists_command },
1008 { "vars", info_vars_command },
1009 { 0, 0 }
1010 };
1011 return Th_CallSubCommand(interp, ctx, argc, argv, argl, aSub);
1012 }
1013
1014
+4 -2
--- src/th_main.c
+++ src/th_main.c
@@ -174,11 +174,11 @@
174174
static int enableOutput = 1;
175175
176176
/*
177177
** TH1 command: enable_output BOOLEAN
178178
**
179
-** Enable or disable the puts and hputs commands.
179
+** Enable or disable the puts and wiki commands.
180180
*/
181181
static int enableOutputCmd(
182182
Th_Interp *interp,
183183
void *p,
184184
int argc,
@@ -339,13 +339,15 @@
339339
sendText((char*)argv[1], argl[1], *(unsigned int*)pConvert);
340340
return TH_OK;
341341
}
342342
343343
/*
344
+** TH1 command: decorate STRING
344345
** TH1 command: wiki STRING
345346
**
346
-** Render the input string as wiki.
347
+** Render the input string as wiki. For the decorate command, only links
348
+** are handled.
347349
*/
348350
static int wikiCmd(
349351
Th_Interp *interp,
350352
void *p,
351353
int argc,
352354
--- src/th_main.c
+++ src/th_main.c
@@ -174,11 +174,11 @@
174 static int enableOutput = 1;
175
176 /*
177 ** TH1 command: enable_output BOOLEAN
178 **
179 ** Enable or disable the puts and hputs commands.
180 */
181 static int enableOutputCmd(
182 Th_Interp *interp,
183 void *p,
184 int argc,
@@ -339,13 +339,15 @@
339 sendText((char*)argv[1], argl[1], *(unsigned int*)pConvert);
340 return TH_OK;
341 }
342
343 /*
 
344 ** TH1 command: wiki STRING
345 **
346 ** Render the input string as wiki.
 
347 */
348 static int wikiCmd(
349 Th_Interp *interp,
350 void *p,
351 int argc,
352
--- src/th_main.c
+++ src/th_main.c
@@ -174,11 +174,11 @@
174 static int enableOutput = 1;
175
176 /*
177 ** TH1 command: enable_output BOOLEAN
178 **
179 ** Enable or disable the puts and wiki commands.
180 */
181 static int enableOutputCmd(
182 Th_Interp *interp,
183 void *p,
184 int argc,
@@ -339,13 +339,15 @@
339 sendText((char*)argv[1], argl[1], *(unsigned int*)pConvert);
340 return TH_OK;
341 }
342
343 /*
344 ** TH1 command: decorate STRING
345 ** TH1 command: wiki STRING
346 **
347 ** Render the input string as wiki. For the decorate command, only links
348 ** are handled.
349 */
350 static int wikiCmd(
351 Th_Interp *interp,
352 void *p,
353 int argc,
354
+4 -2
--- src/th_main.c
+++ src/th_main.c
@@ -174,11 +174,11 @@
174174
static int enableOutput = 1;
175175
176176
/*
177177
** TH1 command: enable_output BOOLEAN
178178
**
179
-** Enable or disable the puts and hputs commands.
179
+** Enable or disable the puts and wiki commands.
180180
*/
181181
static int enableOutputCmd(
182182
Th_Interp *interp,
183183
void *p,
184184
int argc,
@@ -339,13 +339,15 @@
339339
sendText((char*)argv[1], argl[1], *(unsigned int*)pConvert);
340340
return TH_OK;
341341
}
342342
343343
/*
344
+** TH1 command: decorate STRING
344345
** TH1 command: wiki STRING
345346
**
346
-** Render the input string as wiki.
347
+** Render the input string as wiki. For the decorate command, only links
348
+** are handled.
347349
*/
348350
static int wikiCmd(
349351
Th_Interp *interp,
350352
void *p,
351353
int argc,
352354
--- src/th_main.c
+++ src/th_main.c
@@ -174,11 +174,11 @@
174 static int enableOutput = 1;
175
176 /*
177 ** TH1 command: enable_output BOOLEAN
178 **
179 ** Enable or disable the puts and hputs commands.
180 */
181 static int enableOutputCmd(
182 Th_Interp *interp,
183 void *p,
184 int argc,
@@ -339,13 +339,15 @@
339 sendText((char*)argv[1], argl[1], *(unsigned int*)pConvert);
340 return TH_OK;
341 }
342
343 /*
 
344 ** TH1 command: wiki STRING
345 **
346 ** Render the input string as wiki.
 
347 */
348 static int wikiCmd(
349 Th_Interp *interp,
350 void *p,
351 int argc,
352
--- src/th_main.c
+++ src/th_main.c
@@ -174,11 +174,11 @@
174 static int enableOutput = 1;
175
176 /*
177 ** TH1 command: enable_output BOOLEAN
178 **
179 ** Enable or disable the puts and wiki commands.
180 */
181 static int enableOutputCmd(
182 Th_Interp *interp,
183 void *p,
184 int argc,
@@ -339,13 +339,15 @@
339 sendText((char*)argv[1], argl[1], *(unsigned int*)pConvert);
340 return TH_OK;
341 }
342
343 /*
344 ** TH1 command: decorate STRING
345 ** TH1 command: wiki STRING
346 **
347 ** Render the input string as wiki. For the decorate command, only links
348 ** are handled.
349 */
350 static int wikiCmd(
351 Th_Interp *interp,
352 void *p,
353 int argc,
354
+61 -16
--- src/th_tcl.c
+++ src/th_tcl.c
@@ -250,10 +250,44 @@
250250
** interpreter. Stores the created Tcl interpreter in the Tcl context supplied
251251
** by the caller. This must be declared here because quite a few functions in
252252
** this file need to use it before it can be defined.
253253
*/
254254
static int createTclInterp(Th_Interp *interp, void *pContext);
255
+
256
+/*
257
+** Returns the TH1 return code corresponding to the specified Tcl
258
+** return code.
259
+*/
260
+static int getTh1ReturnCode(
261
+ int rc /* The Tcl return code value to convert. */
262
+){
263
+ switch( rc ){
264
+ case /*0*/ TCL_OK: return /*0*/ TH_OK;
265
+ case /*1*/ TCL_ERROR: return /*1*/ TH_ERROR;
266
+ case /*2*/ TCL_RETURN: return /*3*/ TH_RETURN;
267
+ case /*3*/ TCL_BREAK: return /*2*/ TH_BREAK;
268
+ case /*4*/ TCL_CONTINUE: return /*4*/ TH_CONTINUE;
269
+ default /*?*/: return /*?*/ rc;
270
+ }
271
+}
272
+
273
+/*
274
+** Returns the Tcl return code corresponding to the specified TH1
275
+** return code.
276
+*/
277
+static int getTclReturnCode(
278
+ int rc /* The TH1 return code value to convert. */
279
+){
280
+ switch( rc ){
281
+ case /*0*/ TH_OK: return /*0*/ TCL_OK;
282
+ case /*1*/ TH_ERROR: return /*1*/ TCL_ERROR;
283
+ case /*2*/ TH_BREAK: return /*3*/ TCL_BREAK;
284
+ case /*3*/ TH_RETURN: return /*2*/ TCL_RETURN;
285
+ case /*4*/ TH_CONTINUE: return /*4*/ TCL_CONTINUE;
286
+ default /*?*/: return /*?*/ rc;
287
+ }
288
+}
255289
256290
/*
257291
** Returns a name for a Tcl return code.
258292
*/
259293
static const char *getTclReturnCodeName(
@@ -263,12 +297,12 @@
263297
static char zRc[32];
264298
265299
switch( rc ){
266300
case TCL_OK: return nullIfOk ? 0 : "TCL_OK";
267301
case TCL_ERROR: return "TCL_ERROR";
268
- case TCL_BREAK: return "TCL_BREAK";
269302
case TCL_RETURN: return "TCL_RETURN";
303
+ case TCL_BREAK: return "TCL_BREAK";
270304
case TCL_CONTINUE: return "TCL_CONTINUE";
271305
default: {
272306
sqlite3_snprintf(sizeof(zRc), zRc, "Tcl return code %d", rc);
273307
}
274308
}
@@ -350,13 +384,15 @@
350384
}
351385
return rc;
352386
}
353387
354388
/*
355
-** Syntax:
389
+** TH1 command: tclEval arg ?arg ...?
356390
**
357
-** tclEval arg ?arg ...?
391
+** Evaluates the Tcl script and returns its result verbatim. If a Tcl script
392
+** error is generated, it will be transformed into a TH1 script error. A Tcl
393
+** interpreter will be created automatically if it has not been already.
358394
*/
359395
static int tclEval_command(
360396
Th_Interp *interp,
361397
void *ctx,
362398
int argc,
@@ -400,18 +436,21 @@
400436
FREE_ARGV_TO_OBJV();
401437
}
402438
zResult = getTclResult(tclInterp, &nResult);
403439
Th_SetResult(interp, zResult, nResult);
404440
Tcl_Release((ClientData)tclInterp);
405
- rc = notifyPreOrPostEval(1, interp, ctx, argc, argv, argl, rc);
441
+ rc = notifyPreOrPostEval(1, interp, ctx, argc, argv, argl,
442
+ getTh1ReturnCode(rc));
406443
return rc;
407444
}
408445
409446
/*
410
-** Syntax:
447
+** TH1 command: tclExpr arg ?arg ...?
411448
**
412
-** tclExpr arg ?arg ...?
449
+** Evaluates the Tcl expression and returns its result verbatim. If a Tcl
450
+** script error is generated, it will be transformed into a TH1 script error.
451
+** A Tcl interpreter will be created automatically if it has not been already.
413452
*/
414453
static int tclExpr_command(
415454
Th_Interp *interp,
416455
void *ctx,
417456
int argc,
@@ -461,18 +500,21 @@
461500
zResult = getTclResult(tclInterp, &nResult);
462501
}
463502
Th_SetResult(interp, zResult, nResult);
464503
if( rc==TCL_OK ) Tcl_DecrRefCount(resultObjPtr);
465504
Tcl_Release((ClientData)tclInterp);
466
- rc = notifyPreOrPostEval(1, interp, ctx, argc, argv, argl, rc);
505
+ rc = notifyPreOrPostEval(1, interp, ctx, argc, argv, argl,
506
+ getTh1ReturnCode(rc));
467507
return rc;
468508
}
469509
470510
/*
471
-** Syntax:
511
+** TH1 command: tclInvoke command ?arg ...?
472512
**
473
-** tclInvoke command ?arg ...?
513
+** Invokes the Tcl command using the supplied arguments. No additional
514
+** substitutions are performed on the arguments. A Tcl interpreter will
515
+** be created automatically if it has not been already.
474516
*/
475517
static int tclInvoke_command(
476518
Th_Interp *interp,
477519
void *ctx,
478520
int argc,
@@ -533,18 +575,20 @@
533575
FREE_ARGV_TO_OBJV();
534576
}
535577
zResult = getTclResult(tclInterp, &nResult);
536578
Th_SetResult(interp, zResult, nResult);
537579
Tcl_Release((ClientData)tclInterp);
538
- rc = notifyPreOrPostEval(1, interp, ctx, argc, argv, argl, rc);
580
+ rc = notifyPreOrPostEval(1, interp, ctx, argc, argv, argl,
581
+ getTh1ReturnCode(rc));
539582
return rc;
540583
}
541584
542585
/*
543
-** Syntax:
586
+** Tcl command: th1Eval arg
544587
**
545
-** th1Eval arg
588
+** Evaluates the TH1 script and returns its result verbatim. If a TH1 script
589
+** error is generated, it will be transformed into a Tcl script error.
546590
*/
547591
static int Th1EvalObjCmd(
548592
ClientData clientData,
549593
Tcl_Interp *interp,
550594
int objc,
@@ -566,17 +610,18 @@
566610
}
567611
arg = Tcl_GetStringFromObj(objv[1], &nArg);
568612
rc = Th_Eval(th1Interp, 0, arg, nArg);
569613
arg = Th_GetResult(th1Interp, &nArg);
570614
Tcl_SetObjResult(interp, Tcl_NewStringObj(arg, nArg));
571
- return rc;
615
+ return getTclReturnCode(rc);
572616
}
573617
574618
/*
575
-** Syntax:
619
+** Tcl command: th1Expr arg
576620
**
577
-** th1Expr arg
621
+** Evaluates the TH1 expression and returns its result verbatim. If a TH1
622
+** script error is generated, it will be transformed into a Tcl script error.
578623
*/
579624
static int Th1ExprObjCmd(
580625
ClientData clientData,
581626
Tcl_Interp *interp,
582627
int objc,
@@ -598,11 +643,11 @@
598643
}
599644
arg = Tcl_GetStringFromObj(objv[1], &nArg);
600645
rc = Th_Expr(th1Interp, arg, nArg);
601646
arg = Th_GetResult(th1Interp, &nArg);
602647
Tcl_SetObjResult(interp, Tcl_NewStringObj(arg, nArg));
603
- return rc;
648
+ return getTclReturnCode(rc);
604649
}
605650
606651
/*
607652
** Array of Tcl integration commands. Used when adding or removing the Tcl
608653
** integration commands from TH1.
609654
--- src/th_tcl.c
+++ src/th_tcl.c
@@ -250,10 +250,44 @@
250 ** interpreter. Stores the created Tcl interpreter in the Tcl context supplied
251 ** by the caller. This must be declared here because quite a few functions in
252 ** this file need to use it before it can be defined.
253 */
254 static int createTclInterp(Th_Interp *interp, void *pContext);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
256 /*
257 ** Returns a name for a Tcl return code.
258 */
259 static const char *getTclReturnCodeName(
@@ -263,12 +297,12 @@
263 static char zRc[32];
264
265 switch( rc ){
266 case TCL_OK: return nullIfOk ? 0 : "TCL_OK";
267 case TCL_ERROR: return "TCL_ERROR";
268 case TCL_BREAK: return "TCL_BREAK";
269 case TCL_RETURN: return "TCL_RETURN";
 
270 case TCL_CONTINUE: return "TCL_CONTINUE";
271 default: {
272 sqlite3_snprintf(sizeof(zRc), zRc, "Tcl return code %d", rc);
273 }
274 }
@@ -350,13 +384,15 @@
350 }
351 return rc;
352 }
353
354 /*
355 ** Syntax:
356 **
357 ** tclEval arg ?arg ...?
 
 
358 */
359 static int tclEval_command(
360 Th_Interp *interp,
361 void *ctx,
362 int argc,
@@ -400,18 +436,21 @@
400 FREE_ARGV_TO_OBJV();
401 }
402 zResult = getTclResult(tclInterp, &nResult);
403 Th_SetResult(interp, zResult, nResult);
404 Tcl_Release((ClientData)tclInterp);
405 rc = notifyPreOrPostEval(1, interp, ctx, argc, argv, argl, rc);
 
406 return rc;
407 }
408
409 /*
410 ** Syntax:
411 **
412 ** tclExpr arg ?arg ...?
 
 
413 */
414 static int tclExpr_command(
415 Th_Interp *interp,
416 void *ctx,
417 int argc,
@@ -461,18 +500,21 @@
461 zResult = getTclResult(tclInterp, &nResult);
462 }
463 Th_SetResult(interp, zResult, nResult);
464 if( rc==TCL_OK ) Tcl_DecrRefCount(resultObjPtr);
465 Tcl_Release((ClientData)tclInterp);
466 rc = notifyPreOrPostEval(1, interp, ctx, argc, argv, argl, rc);
 
467 return rc;
468 }
469
470 /*
471 ** Syntax:
472 **
473 ** tclInvoke command ?arg ...?
 
 
474 */
475 static int tclInvoke_command(
476 Th_Interp *interp,
477 void *ctx,
478 int argc,
@@ -533,18 +575,20 @@
533 FREE_ARGV_TO_OBJV();
534 }
535 zResult = getTclResult(tclInterp, &nResult);
536 Th_SetResult(interp, zResult, nResult);
537 Tcl_Release((ClientData)tclInterp);
538 rc = notifyPreOrPostEval(1, interp, ctx, argc, argv, argl, rc);
 
539 return rc;
540 }
541
542 /*
543 ** Syntax:
544 **
545 ** th1Eval arg
 
546 */
547 static int Th1EvalObjCmd(
548 ClientData clientData,
549 Tcl_Interp *interp,
550 int objc,
@@ -566,17 +610,18 @@
566 }
567 arg = Tcl_GetStringFromObj(objv[1], &nArg);
568 rc = Th_Eval(th1Interp, 0, arg, nArg);
569 arg = Th_GetResult(th1Interp, &nArg);
570 Tcl_SetObjResult(interp, Tcl_NewStringObj(arg, nArg));
571 return rc;
572 }
573
574 /*
575 ** Syntax:
576 **
577 ** th1Expr arg
 
578 */
579 static int Th1ExprObjCmd(
580 ClientData clientData,
581 Tcl_Interp *interp,
582 int objc,
@@ -598,11 +643,11 @@
598 }
599 arg = Tcl_GetStringFromObj(objv[1], &nArg);
600 rc = Th_Expr(th1Interp, arg, nArg);
601 arg = Th_GetResult(th1Interp, &nArg);
602 Tcl_SetObjResult(interp, Tcl_NewStringObj(arg, nArg));
603 return rc;
604 }
605
606 /*
607 ** Array of Tcl integration commands. Used when adding or removing the Tcl
608 ** integration commands from TH1.
609
--- src/th_tcl.c
+++ src/th_tcl.c
@@ -250,10 +250,44 @@
250 ** interpreter. Stores the created Tcl interpreter in the Tcl context supplied
251 ** by the caller. This must be declared here because quite a few functions in
252 ** this file need to use it before it can be defined.
253 */
254 static int createTclInterp(Th_Interp *interp, void *pContext);
255
256 /*
257 ** Returns the TH1 return code corresponding to the specified Tcl
258 ** return code.
259 */
260 static int getTh1ReturnCode(
261 int rc /* The Tcl return code value to convert. */
262 ){
263 switch( rc ){
264 case /*0*/ TCL_OK: return /*0*/ TH_OK;
265 case /*1*/ TCL_ERROR: return /*1*/ TH_ERROR;
266 case /*2*/ TCL_RETURN: return /*3*/ TH_RETURN;
267 case /*3*/ TCL_BREAK: return /*2*/ TH_BREAK;
268 case /*4*/ TCL_CONTINUE: return /*4*/ TH_CONTINUE;
269 default /*?*/: return /*?*/ rc;
270 }
271 }
272
273 /*
274 ** Returns the Tcl return code corresponding to the specified TH1
275 ** return code.
276 */
277 static int getTclReturnCode(
278 int rc /* The TH1 return code value to convert. */
279 ){
280 switch( rc ){
281 case /*0*/ TH_OK: return /*0*/ TCL_OK;
282 case /*1*/ TH_ERROR: return /*1*/ TCL_ERROR;
283 case /*2*/ TH_BREAK: return /*3*/ TCL_BREAK;
284 case /*3*/ TH_RETURN: return /*2*/ TCL_RETURN;
285 case /*4*/ TH_CONTINUE: return /*4*/ TCL_CONTINUE;
286 default /*?*/: return /*?*/ rc;
287 }
288 }
289
290 /*
291 ** Returns a name for a Tcl return code.
292 */
293 static const char *getTclReturnCodeName(
@@ -263,12 +297,12 @@
297 static char zRc[32];
298
299 switch( rc ){
300 case TCL_OK: return nullIfOk ? 0 : "TCL_OK";
301 case TCL_ERROR: return "TCL_ERROR";
 
302 case TCL_RETURN: return "TCL_RETURN";
303 case TCL_BREAK: return "TCL_BREAK";
304 case TCL_CONTINUE: return "TCL_CONTINUE";
305 default: {
306 sqlite3_snprintf(sizeof(zRc), zRc, "Tcl return code %d", rc);
307 }
308 }
@@ -350,13 +384,15 @@
384 }
385 return rc;
386 }
387
388 /*
389 ** TH1 command: tclEval arg ?arg ...?
390 **
391 ** Evaluates the Tcl script and returns its result verbatim. If a Tcl script
392 ** error is generated, it will be transformed into a TH1 script error. A Tcl
393 ** interpreter will be created automatically if it has not been already.
394 */
395 static int tclEval_command(
396 Th_Interp *interp,
397 void *ctx,
398 int argc,
@@ -400,18 +436,21 @@
436 FREE_ARGV_TO_OBJV();
437 }
438 zResult = getTclResult(tclInterp, &nResult);
439 Th_SetResult(interp, zResult, nResult);
440 Tcl_Release((ClientData)tclInterp);
441 rc = notifyPreOrPostEval(1, interp, ctx, argc, argv, argl,
442 getTh1ReturnCode(rc));
443 return rc;
444 }
445
446 /*
447 ** TH1 command: tclExpr arg ?arg ...?
448 **
449 ** Evaluates the Tcl expression and returns its result verbatim. If a Tcl
450 ** script error is generated, it will be transformed into a TH1 script error.
451 ** A Tcl interpreter will be created automatically if it has not been already.
452 */
453 static int tclExpr_command(
454 Th_Interp *interp,
455 void *ctx,
456 int argc,
@@ -461,18 +500,21 @@
500 zResult = getTclResult(tclInterp, &nResult);
501 }
502 Th_SetResult(interp, zResult, nResult);
503 if( rc==TCL_OK ) Tcl_DecrRefCount(resultObjPtr);
504 Tcl_Release((ClientData)tclInterp);
505 rc = notifyPreOrPostEval(1, interp, ctx, argc, argv, argl,
506 getTh1ReturnCode(rc));
507 return rc;
508 }
509
510 /*
511 ** TH1 command: tclInvoke command ?arg ...?
512 **
513 ** Invokes the Tcl command using the supplied arguments. No additional
514 ** substitutions are performed on the arguments. A Tcl interpreter will
515 ** be created automatically if it has not been already.
516 */
517 static int tclInvoke_command(
518 Th_Interp *interp,
519 void *ctx,
520 int argc,
@@ -533,18 +575,20 @@
575 FREE_ARGV_TO_OBJV();
576 }
577 zResult = getTclResult(tclInterp, &nResult);
578 Th_SetResult(interp, zResult, nResult);
579 Tcl_Release((ClientData)tclInterp);
580 rc = notifyPreOrPostEval(1, interp, ctx, argc, argv, argl,
581 getTh1ReturnCode(rc));
582 return rc;
583 }
584
585 /*
586 ** Tcl command: th1Eval arg
587 **
588 ** Evaluates the TH1 script and returns its result verbatim. If a TH1 script
589 ** error is generated, it will be transformed into a Tcl script error.
590 */
591 static int Th1EvalObjCmd(
592 ClientData clientData,
593 Tcl_Interp *interp,
594 int objc,
@@ -566,17 +610,18 @@
610 }
611 arg = Tcl_GetStringFromObj(objv[1], &nArg);
612 rc = Th_Eval(th1Interp, 0, arg, nArg);
613 arg = Th_GetResult(th1Interp, &nArg);
614 Tcl_SetObjResult(interp, Tcl_NewStringObj(arg, nArg));
615 return getTclReturnCode(rc);
616 }
617
618 /*
619 ** Tcl command: th1Expr arg
620 **
621 ** Evaluates the TH1 expression and returns its result verbatim. If a TH1
622 ** script error is generated, it will be transformed into a Tcl script error.
623 */
624 static int Th1ExprObjCmd(
625 ClientData clientData,
626 Tcl_Interp *interp,
627 int objc,
@@ -598,11 +643,11 @@
643 }
644 arg = Tcl_GetStringFromObj(objv[1], &nArg);
645 rc = Th_Expr(th1Interp, arg, nArg);
646 arg = Th_GetResult(th1Interp, &nArg);
647 Tcl_SetObjResult(interp, Tcl_NewStringObj(arg, nArg));
648 return getTclReturnCode(rc);
649 }
650
651 /*
652 ** Array of Tcl integration commands. Used when adding or removing the Tcl
653 ** integration commands from TH1.
654
+1 -1
--- src/timeline.c
+++ src/timeline.c
@@ -587,11 +587,11 @@
587587
int w;
588588
/* style is not moved to css, because this is
589589
** a technical div for the timeline graph
590590
*/
591591
w = pGraph->mxRail*pGraph->iRailPitch + 28;
592
- @ <tr><td></td><td>
592
+ @ <tr class="timelineBottom"><td></td><td>
593593
@ <div id="grbtm" style="width:%d(w)px;"></div>
594594
@ </td><td></td></tr>
595595
}
596596
}
597597
@ </table>
598598
--- src/timeline.c
+++ src/timeline.c
@@ -587,11 +587,11 @@
587 int w;
588 /* style is not moved to css, because this is
589 ** a technical div for the timeline graph
590 */
591 w = pGraph->mxRail*pGraph->iRailPitch + 28;
592 @ <tr><td></td><td>
593 @ <div id="grbtm" style="width:%d(w)px;"></div>
594 @ </td><td></td></tr>
595 }
596 }
597 @ </table>
598
--- src/timeline.c
+++ src/timeline.c
@@ -587,11 +587,11 @@
587 int w;
588 /* style is not moved to css, because this is
589 ** a technical div for the timeline graph
590 */
591 w = pGraph->mxRail*pGraph->iRailPitch + 28;
592 @ <tr class="timelineBottom"><td></td><td>
593 @ <div id="grbtm" style="width:%d(w)px;"></div>
594 @ </td><td></td></tr>
595 }
596 }
597 @ </table>
598
--- test/th1.test
+++ test/th1.test
@@ -848,5 +848,45 @@
848848
849849
###############################################################################
850850
851851
fossil test-th-eval "reinitialize 1; globalState configuration"
852852
test th1-reinitialize-2 {$RESULT ne ""}
853
+
854
+###############################################################################
855
+
856
+#
857
+# NOTE: This test may fail if the command names do not always come
858
+# out in a deterministic order from TH1.
859
+#
860
+fossil test-th-eval "info commands"
861
+test th1-info-commands-1 {$RESULT eq {linecount htmlize date stime\
862
+enable_output uplevel http expr utime styleFooter catch if tclReady\
863
+searchable reinitialize combobox lindex query html anoncap randhex\
864
+llength for set break regexp styleHeader puts return checkout decorate\
865
+artifact trace wiki proc hascap globalState continue getParameter\
866
+hasfeature setting breakpoint upvar render repository string unset\
867
+setParameter list error info rename anycap httpize}}
868
+
869
+###############################################################################
870
+
871
+fossil test-th-eval "info vars"
872
+test th1-info-vars-1 {$RESULT eq ""}
873
+
874
+###############################################################################
875
+
876
+fossil test-th-eval "set x 1; info vars"
877
+test th1-info-vars-2 {$RESULT eq "x"}
878
+
879
+###############################################################################
880
+
881
+fossil test-th-eval "set x 1; unset x; info vars"
882
+test th1-info-vars-3 {$RESULT eq ""}
883
+
884
+###############################################################################
885
+
886
+fossil test-th-eval "proc foo {} {set x 1; info vars}; foo"
887
+test th1-info-vars-4 {$RESULT eq "x"}
888
+
889
+###############################################################################
890
+
891
+fossil test-th-eval "set y 1; proc foo {} {set x 1; uplevel 1 {info vars}}; foo"
892
+test th1-info-vars-5 {$RESULT eq "y"}
853893
--- test/th1.test
+++ test/th1.test
@@ -848,5 +848,45 @@
848
849 ###############################################################################
850
851 fossil test-th-eval "reinitialize 1; globalState configuration"
852 test th1-reinitialize-2 {$RESULT ne ""}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
853
--- test/th1.test
+++ test/th1.test
@@ -848,5 +848,45 @@
848
849 ###############################################################################
850
851 fossil test-th-eval "reinitialize 1; globalState configuration"
852 test th1-reinitialize-2 {$RESULT ne ""}
853
854 ###############################################################################
855
856 #
857 # NOTE: This test may fail if the command names do not always come
858 # out in a deterministic order from TH1.
859 #
860 fossil test-th-eval "info commands"
861 test th1-info-commands-1 {$RESULT eq {linecount htmlize date stime\
862 enable_output uplevel http expr utime styleFooter catch if tclReady\
863 searchable reinitialize combobox lindex query html anoncap randhex\
864 llength for set break regexp styleHeader puts return checkout decorate\
865 artifact trace wiki proc hascap globalState continue getParameter\
866 hasfeature setting breakpoint upvar render repository string unset\
867 setParameter list error info rename anycap httpize}}
868
869 ###############################################################################
870
871 fossil test-th-eval "info vars"
872 test th1-info-vars-1 {$RESULT eq ""}
873
874 ###############################################################################
875
876 fossil test-th-eval "set x 1; info vars"
877 test th1-info-vars-2 {$RESULT eq "x"}
878
879 ###############################################################################
880
881 fossil test-th-eval "set x 1; unset x; info vars"
882 test th1-info-vars-3 {$RESULT eq ""}
883
884 ###############################################################################
885
886 fossil test-th-eval "proc foo {} {set x 1; info vars}; foo"
887 test th1-info-vars-4 {$RESULT eq "x"}
888
889 ###############################################################################
890
891 fossil test-th-eval "set y 1; proc foo {} {set x 1; uplevel 1 {info vars}}; foo"
892 test th1-info-vars-5 {$RESULT eq "y"}
893
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,10 +1,18 @@
11
<title>Change Log</title>
22
33
<h2>Changes for Version 1.33 (not released yet)</h2>
44
* Add [/help?cmd=import|fossil import --svn], for importing a subversion
55
repository into fossil which was exported using "svnadmin dump".
6
+ * Added <nowiki>[info commands] and [info vars]</nowiki> commands to TH1.
7
+ These commands perform the same function as their Tcl counterparts,
8
+ except they do not accept a pattern argument.
9
+ * Fix some obscure issues with TH1 expression processing.
10
+ * Fix titles in search results for documents that are not wiki, markdown,
11
+ or HTML.
12
+ * Formally translate TH1 to Tcl return codes and vice-versa, where
13
+ necessary, in the Tcl integration subsystem.
614
715
<h2>Changes for Version 1.32 (2015-03-14)</h2>
816
* When creating a new repository using [/help?cmd=init|fossil init], ensure
917
that the new repository is fully compatible with historical versions of
1018
Fossil by having a valid manifest as RID 1.
1119
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,10 +1,18 @@
1 <title>Change Log</title>
2
3 <h2>Changes for Version 1.33 (not released yet)</h2>
4 * Add [/help?cmd=import|fossil import --svn], for importing a subversion
5 repository into fossil which was exported using "svnadmin dump".
 
 
 
 
 
 
 
 
6
7 <h2>Changes for Version 1.32 (2015-03-14)</h2>
8 * When creating a new repository using [/help?cmd=init|fossil init], ensure
9 that the new repository is fully compatible with historical versions of
10 Fossil by having a valid manifest as RID 1.
11
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,10 +1,18 @@
1 <title>Change Log</title>
2
3 <h2>Changes for Version 1.33 (not released yet)</h2>
4 * Add [/help?cmd=import|fossil import --svn], for importing a subversion
5 repository into fossil which was exported using "svnadmin dump".
6 * Added <nowiki>[info commands] and [info vars]</nowiki> commands to TH1.
7 These commands perform the same function as their Tcl counterparts,
8 except they do not accept a pattern argument.
9 * Fix some obscure issues with TH1 expression processing.
10 * Fix titles in search results for documents that are not wiki, markdown,
11 or HTML.
12 * Formally translate TH1 to Tcl return codes and vice-versa, where
13 necessary, in the Tcl integration subsystem.
14
15 <h2>Changes for Version 1.32 (2015-03-14)</h2>
16 * When creating a new repository using [/help?cmd=init|fossil init], ensure
17 that the new repository is fully compatible with historical versions of
18 Fossil by having a valid manifest as RID 1.
19
+413 -11
--- www/th1.md
+++ www/th1.md
@@ -5,22 +5,22 @@
55
content in Fossil.
66
77
Origins
88
-------
99
10
-TH1 began as a minimalist re-implementation of the TCL scripting language.
10
+TH1 began as a minimalist re-implementation of the Tcl scripting language.
1111
There was a need to test the SQLite library on Symbian phones, but at that
1212
time all of the test cases for SQLite were written in Tcl and Tcl could not
1313
be easily compiled on the SymbianOS. So TH1 was developed as a cut-down
14
-version of TCL that would facilitate running the SQLite test scripts on
14
+version of Tcl that would facilitate running the SQLite test scripts on
1515
SymbianOS.
1616
1717
The testing of SQLite on SymbianOS was eventually accomplished by other
18
-means. But Fossil was first being designed at about the same time.
19
-Early prototypes of Fossil were written in pure TCL. But as the development
20
-shifted toward the use of C-code, the need arose to have a TCL-like
21
-scripting language to help with code generation. TH1 was small and
18
+means. But Fossil was first being designed at about the same time.
19
+Early prototypes of Fossil were written in pure Tcl. But as the development
20
+shifted toward the use of C-code, the need arose to have a Tcl-like
21
+scripting language to help with code generation. TH1 was small and
2222
light-weight and used minimal resources and seemed ideally suited for the
2323
task.
2424
2525
The name "TH1" stands "Test Harness 1", since that was its original purpose.
2626
@@ -78,11 +78,11 @@
7878
just a single command.
7979
8080
Summary of Core TH1 Commands
8181
----------------------------
8282
83
-The original TCL language after when TH1 is modeled has a very rich
83
+The original Tcl language after when TH1 is modeled has a very rich
8484
repertoire of commands. TH1, as it is designed to be minimalist and
8585
embedded has a greatly reduced command set. The following bullets
8686
summarize the commands available in TH1:
8787
8888
* break
@@ -90,11 +90,13 @@
9090
* continue
9191
* error ?STRING?
9292
* expr EXPR
9393
* for INIT-SCRIPT TEST-EXPR NEXT-SCRIPT BODY-SCRIPT
9494
* if EXPR SCRIPT (elseif EXPR SCRIPT)* ?else SCRIPT?
95
+ * info commands
9596
* info exists VARNAME
97
+ * info vars
9698
* lindex LIST INDEX
9799
* list ARG ...
98100
* llength LIST
99101
* proc NAME ARG-LIST BODY-SCRIPT
100102
* rename OLD NEW
@@ -109,12 +111,12 @@
109111
* string repeat STRING COUNT
110112
* unset VARNAME
111113
* uplevel ?LEVEL? SCRIPT
112114
* upvar ?FRAME? OTHERVAR MYVAR ?OTHERVAR MYVAR?
113115
114
-All of the above commands works as in the original TCL. Refer to the
115
-TCL documentation for details.
116
+All of the above commands works as in the original Tcl. Refer to the
117
+Tcl documentation for details.
116118
117119
TH1 Extended Commands
118120
---------------------
119121
120122
There are many new commands added to TH1 and used to access the special
@@ -128,16 +130,16 @@
128130
* date
129131
* decorate
130132
* enable_output
131133
* getParameter
132134
* globalState
133
- * httpize
134135
* hascap
135136
* hasfeature
136137
* html
137138
* htmlize
138139
* http
140
+ * httpize
139141
* linecount
140142
* puts
141143
* query
142144
* randhex
143145
* regexp
@@ -147,20 +149,420 @@
147149
* searchable
148150
* setParameter
149151
* setting
150152
* styleHeader
151153
* styleFooter
154
+ * tclEval
155
+ * tclExpr
156
+ * tclInvoke
152157
* tclReady
153158
* trace
154159
* stime
155160
* utime
156161
* wiki
157162
158163
Each of the commands above is documented by a block comment above their
159
-implementation in the th_main.c source file.
164
+implementation in the th\_main.c or th\_tcl.c source files.
165
+
166
+All commands starting with "tcl", with the exception of "tclReady",
167
+require the Tcl integration subsystem be included at compile-time.
168
+Additionally, the "tcl" repository setting must be enabled at runtime
169
+in order to successfully make use of these commands.
170
+
171
+TH1 anoncap Command
172
+-------------------
173
+
174
+ * anoncap STRING...
175
+
176
+Returns true if the anonymous user has all of the capabilities listed
177
+in STRING.
178
+
179
+TH1 anycap Command
180
+------------------
181
+
182
+ * anycap STRING
183
+
184
+Returns true if the current user user has any one of the capabilities
185
+listed in STRING.
186
+
187
+TH1 artifact Command
188
+--------------------
189
+
190
+ * artifact ID ?FILENAME?
191
+
192
+Attempts to locate the specified artifact and return its contents. An
193
+error is generated if the repository is not open or the artifact cannot
194
+be found.
195
+
196
+TH1 checkout Command
197
+--------------------
198
+
199
+ * checkout ?BOOLEAN?
200
+
201
+Return the fully qualified directory name of the current checkout or an
202
+empty string if it is not available. Optionally, it will attempt to find
203
+the current checkout, opening the configuration ("user") database and the
204
+repository as necessary, if the boolean argument is non-zero.
205
+
206
+TH1 combobox Command
207
+--------------------
208
+
209
+ * combobox NAME TEXT-LIST NUMLINES
210
+
211
+Generates and emits an HTML combobox. NAME is both the name of the
212
+CGI parameter and the name of a variable that contains the currently
213
+selected value. TEXT-LIST is a list of possible values for the
214
+combobox. NUMLINES is 1 for a true combobox. If NUMLINES is greater
215
+than one then the display is a listbox with the number of lines given.
216
+
217
+TH1 date Command
218
+----------------
219
+
220
+ * date ?-local?
221
+
222
+Return a strings which is the current time and date. If the -local
223
+option is used, the date appears using localtime instead of UTC.
224
+
225
+TH1 decorate Command
226
+--------------------
227
+
228
+ * decorate STRING
229
+
230
+Renders STRING as wiki content; however, only links are handled. No
231
+other markup is processed.
232
+
233
+TH1 enable_output Command
234
+-------------------------
235
+
236
+ * enable_output BOOLEAN
237
+
238
+Enable or disable sending output when the combobox, puts, or wiki
239
+commands are used.
240
+
241
+TH1 getParameter Command
242
+------------------------
243
+
244
+ * getParameter NAME ?DEFAULT?
245
+
246
+Returns the value of the specified query parameter or the specified
247
+default value when there is no matching query parameter.
248
+
249
+TH1 globalState Command
250
+-----------------------
251
+
252
+ * globalState NAME ?DEFAULT?
253
+
254
+Returns a string containing the value of the specified global state
255
+variable -OR- the specified default value. The supported items are:
256
+
257
+ 1. **checkout** -- _Active local checkout directory, if any._
258
+ 1. **configuration** -- _Active configuration database file name, if any._
259
+ 1. **executable** -- _Fully qualified executable file name._
260
+ 1. **flags** -- _TH1 initialization flags._
261
+ 1. **log** -- _Error log file name, if any._
262
+ 1. **repository** -- _Active local repository file name, if any._
263
+ 1. **top** -- _Base path for the active server instance, if applicable._
264
+ 1. **user** -- _Active user name, if any._
265
+ 1. **vfs** -- _SQLite VFS in use, if overridden._
266
+
267
+Attempts to query for unsupported global state variables will result
268
+in a script error. Additional global state variables may be exposed
269
+in the future.
270
+
271
+TH1 hascap Command
272
+------------------
273
+
274
+ * hascap STRING...
275
+
276
+Returns true if the current user has all of the capabilities listed
277
+in STRING.
278
+
279
+TH1 hasfeature Command
280
+----------------------
281
+
282
+ * hasfeature STRING
283
+
284
+Returns true if the binary has the given compile-time feature enabled.
285
+The possible features are:
286
+
287
+ 1. **ssl** -- _Support for the HTTPS transport._
288
+ 1. **th1Docs** -- _Support for TH1 in embedded documentation._
289
+ 1. **th1Hooks** -- _Support for TH1 command and web page hooks._
290
+ 1. **tcl** -- _Support for Tcl integration._
291
+ 1. **useTclStubs** -- _Tcl stubs enabled in the Tcl headers._
292
+ 1. **tclStubs** -- _Uses Tcl stubs (i.e. linking with stubs library)._
293
+ 1. **tclPrivateStubs** -- _Uses Tcl private stubs (i.e. header-only)._
294
+ 1. **json** -- _Support for the JSON APIs._
295
+ 1. **markdown** -- _Support for Markdown documentation format._
296
+ 1. **unicodeCmdLine** -- _The command line arguments are Unicode._
297
+
298
+TH1 html Command
299
+----------------
300
+
301
+ * html STRING
302
+
303
+Outputs the STRING escaped for HTML.
304
+
305
+TH1 htmlize Command
306
+-------------------
307
+
308
+ * htmlize STRING
309
+
310
+Escape all characters of STRING which have special meaning in HTML.
311
+Returns the escaped string.
312
+
313
+TH1 http Command
314
+----------------
315
+
316
+ * http ?-asynchronous? ?--? url ?payload?
317
+
318
+Performs an HTTP or HTTPS request for the specified URL. If a
319
+payload is present, it will be interpreted as text/plain and
320
+the POST method will be used; otherwise, the GET method will
321
+be used. Upon success, if the -asynchronous option is used, an
322
+empty string is returned as the result; otherwise, the response
323
+from the server is returned as the result. Synchronous requests
324
+are not currently implemented.
325
+
326
+TH1 httpize Command
327
+-------------------
328
+
329
+ * httpize STRING
330
+
331
+Escape all characters of STRING which have special meaning in URI
332
+components. Returns the escaped string.
333
+
334
+TH1 linecount Command
335
+---------------------
336
+
337
+ * linecount STRING MAX MIN
338
+
339
+Returns one more than the number of \n characters in STRING. But
340
+never returns less than MIN or more than MAX.
341
+
342
+TH1 puts Command
343
+----------------
344
+
345
+ * puts STRING
346
+
347
+Outputs the STRING unchanged.
348
+
349
+TH1 query Command
350
+-----------------
351
+
352
+ * query SQL CODE
353
+
354
+Runs the SQL query given by the SQL argument. For each row in the result
355
+set, run CODE.
356
+
357
+In SQL, parameters such as $var are filled in using the value of variable
358
+"var". Result values are stored in variables with the column name prior
359
+to each invocation of CODE.
360
+
361
+TH1 randhex Command
362
+-------------------
363
+
364
+ * randhex N
365
+
366
+Returns a string of N*2 random hexadecimal digits with N<50. If N is
367
+omitted, use a value of 10.
368
+
369
+TH1 regexp Command
370
+------------------
371
+
372
+ * regexp ?-nocase? ?--? exp string
373
+
374
+Checks the string against the specified regular expression and returns
375
+non-zero if it matches. If the regular expression is invalid or cannot
376
+be compiled, an error will be generated.
377
+
378
+TH1 reinitialize Command
379
+------------------------
380
+
381
+ * reinitialize ?FLAGS?
382
+
383
+Reinitializes the TH1 interpreter using the specified flags.
384
+
385
+TH1 render Command
386
+------------------
387
+
388
+ * render STRING
389
+
390
+Renders the TH1 template and writes the results.
391
+
392
+TH1 repository Command
393
+----------------------
394
+
395
+ * repository ?BOOLEAN?
396
+
397
+Returns the fully qualified file name of the open repository or an empty
398
+string if one is not currently open. Optionally, it will attempt to open
399
+the repository if the boolean argument is non-zero.
400
+
401
+TH1 searchable Command
402
+----------------------
403
+
404
+ * searchable STRING...
405
+
406
+Return true if searching in any of the document classes identified
407
+by STRING is enabled for the repository and user has the necessary
408
+capabilities to perform the search. The possible document classes
409
+are:
410
+
411
+ 1. **c** -- _Check-in comments_
412
+ 1. **d** -- _Embedded documentation_
413
+ 1. **t** -- _Tickets_
414
+ 1. **w** -- _Wiki_
415
+
416
+To be clear, only one of the document classes identified by each STRING
417
+needs to be searchable in order for that argument to be true. But all
418
+arguments must be true for this routine to return true. Hence, to see
419
+if ALL document classes are searchable:
420
+
421
+ if {[searchable c d t w]} {...}
422
+
423
+But to see if ANY document class is searchable:
424
+
425
+ if {[searchable cdtw]} {...}
426
+
427
+This command is useful for enabling or disabling a "Search" entry on the
428
+menu bar.
429
+
430
+TH1 setParameter Command
431
+------------------------
432
+
433
+ * setParameter NAME VALUE
434
+
435
+Sets the value of the specified query parameter.
436
+
437
+TH1 setting Command
438
+-------------------
439
+
440
+ * setting name
441
+
442
+Gets and returns the value of the specified setting.
443
+
444
+TH1 styleHeader Command
445
+-----------------------
446
+
447
+ * styleHeader TITLE
448
+
449
+Render the configured style header.
450
+
451
+TH1 styleFooter Command
452
+-----------------------
453
+
454
+ * styleFooter
455
+
456
+Render the configured style footer.
457
+
458
+TH1 tclEval Command
459
+-------------------
460
+
461
+**This command requires the Tcl integration feature.**
462
+
463
+ * tclEval arg ?arg ...?
464
+
465
+Evaluates the Tcl script and returns its result verbatim. If a Tcl script
466
+error is generated, it will be transformed into a TH1 script error. A Tcl
467
+interpreter will be created automatically if it has not been already.
468
+
469
+TH1 tclExpr Command
470
+-------------------
471
+
472
+**This command requires the Tcl integration feature.**
473
+
474
+ * tclExpr arg ?arg ...?
475
+
476
+Evaluates the Tcl expression and returns its result verbatim. If a Tcl
477
+script error is generated, it will be transformed into a TH1 script error.
478
+A Tcl interpreter will be created automatically if it has not been already.
479
+
480
+TH1 tclInvoke Command
481
+---------------------
482
+
483
+**This command requires the Tcl integration feature.**
484
+
485
+ * tclInvoke command ?arg ...?
486
+
487
+Invokes the Tcl command using the supplied arguments. No additional
488
+substitutions are performed on the arguments. A Tcl interpreter will
489
+be created automatically if it has not been already.
490
+
491
+TH1 tclReady Command
492
+--------------------
493
+
494
+ * tclReady
495
+
496
+Returns true if the binary has the Tcl integration feature enabled and it
497
+is currently available for use by TH1 scripts.
498
+
499
+TH1 trace Command
500
+-----------------
501
+
502
+ * trace STRING
503
+
504
+Generates a TH1 trace message if TH1 tracing is enabled.
505
+
506
+TH1 stime Command
507
+-----------------
508
+
509
+ * stime
510
+
511
+Returns the number of microseconds of CPU time consumed by the current
512
+process in system space.
513
+
514
+TH1 utime Command
515
+-----------------
516
+
517
+ * utime
518
+
519
+Returns the number of microseconds of CPU time consumed by the current
520
+process in user space.
521
+
522
+TH1 wiki Command
523
+----------------
524
+
525
+ * wiki STRING
526
+
527
+Renders STRING as wiki content.
528
+
529
+Tcl Integration Commands
530
+------------------------
531
+
532
+When the Tcl integration subsystem is enabled, several commands are added
533
+to the Tcl interpreter. They are used to allow Tcl scripts access to the
534
+Fossil functionality provided via TH1. The following is a summary of the
535
+Tcl commands:
536
+
537
+ * th1Eval
538
+ * th1Expr
539
+
540
+Tcl th1Eval Command
541
+-------------------
542
+
543
+**This command requires the Tcl integration feature.**
544
+
545
+ * th1Eval arg
546
+
547
+Evaluates the TH1 script and returns its result verbatim. If a TH1 script
548
+error is generated, it will be transformed into a Tcl script error.
549
+
550
+Tcl th1Expr Command
551
+-------------------
552
+
553
+**This command requires the Tcl integration feature.**
554
+
555
+ * th1Expr arg
556
+
557
+Evaluates the TH1 expression and returns its result verbatim. If a TH1
558
+script error is generated, it will be transformed into a Tcl script error.
559
+
560
+Further Notes
561
+-------------
160562
161563
**To Do:** We would like to have a community volunteer go through and
162564
copy the documentation for each of these commands (with appropriate
163565
format changes and spelling and grammar corrections) into subsequent
164566
sections of this document. It is suggested that the list of extension
165567
commands be left intact - as a quick reference. But it would be really
166568
nice to also have the details of what each command does.
167569
--- www/th1.md
+++ www/th1.md
@@ -5,22 +5,22 @@
5 content in Fossil.
6
7 Origins
8 -------
9
10 TH1 began as a minimalist re-implementation of the TCL scripting language.
11 There was a need to test the SQLite library on Symbian phones, but at that
12 time all of the test cases for SQLite were written in Tcl and Tcl could not
13 be easily compiled on the SymbianOS. So TH1 was developed as a cut-down
14 version of TCL that would facilitate running the SQLite test scripts on
15 SymbianOS.
16
17 The testing of SQLite on SymbianOS was eventually accomplished by other
18 means. But Fossil was first being designed at about the same time.
19 Early prototypes of Fossil were written in pure TCL. But as the development
20 shifted toward the use of C-code, the need arose to have a TCL-like
21 scripting language to help with code generation. TH1 was small and
22 light-weight and used minimal resources and seemed ideally suited for the
23 task.
24
25 The name "TH1" stands "Test Harness 1", since that was its original purpose.
26
@@ -78,11 +78,11 @@
78 just a single command.
79
80 Summary of Core TH1 Commands
81 ----------------------------
82
83 The original TCL language after when TH1 is modeled has a very rich
84 repertoire of commands. TH1, as it is designed to be minimalist and
85 embedded has a greatly reduced command set. The following bullets
86 summarize the commands available in TH1:
87
88 * break
@@ -90,11 +90,13 @@
90 * continue
91 * error ?STRING?
92 * expr EXPR
93 * for INIT-SCRIPT TEST-EXPR NEXT-SCRIPT BODY-SCRIPT
94 * if EXPR SCRIPT (elseif EXPR SCRIPT)* ?else SCRIPT?
 
95 * info exists VARNAME
 
96 * lindex LIST INDEX
97 * list ARG ...
98 * llength LIST
99 * proc NAME ARG-LIST BODY-SCRIPT
100 * rename OLD NEW
@@ -109,12 +111,12 @@
109 * string repeat STRING COUNT
110 * unset VARNAME
111 * uplevel ?LEVEL? SCRIPT
112 * upvar ?FRAME? OTHERVAR MYVAR ?OTHERVAR MYVAR?
113
114 All of the above commands works as in the original TCL. Refer to the
115 TCL documentation for details.
116
117 TH1 Extended Commands
118 ---------------------
119
120 There are many new commands added to TH1 and used to access the special
@@ -128,16 +130,16 @@
128 * date
129 * decorate
130 * enable_output
131 * getParameter
132 * globalState
133 * httpize
134 * hascap
135 * hasfeature
136 * html
137 * htmlize
138 * http
 
139 * linecount
140 * puts
141 * query
142 * randhex
143 * regexp
@@ -147,20 +149,420 @@
147 * searchable
148 * setParameter
149 * setting
150 * styleHeader
151 * styleFooter
 
 
 
152 * tclReady
153 * trace
154 * stime
155 * utime
156 * wiki
157
158 Each of the commands above is documented by a block comment above their
159 implementation in the th_main.c source file.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
161 **To Do:** We would like to have a community volunteer go through and
162 copy the documentation for each of these commands (with appropriate
163 format changes and spelling and grammar corrections) into subsequent
164 sections of this document. It is suggested that the list of extension
165 commands be left intact - as a quick reference. But it would be really
166 nice to also have the details of what each command does.
167
--- www/th1.md
+++ www/th1.md
@@ -5,22 +5,22 @@
5 content in Fossil.
6
7 Origins
8 -------
9
10 TH1 began as a minimalist re-implementation of the Tcl scripting language.
11 There was a need to test the SQLite library on Symbian phones, but at that
12 time all of the test cases for SQLite were written in Tcl and Tcl could not
13 be easily compiled on the SymbianOS. So TH1 was developed as a cut-down
14 version of Tcl that would facilitate running the SQLite test scripts on
15 SymbianOS.
16
17 The testing of SQLite on SymbianOS was eventually accomplished by other
18 means. But Fossil was first being designed at about the same time.
19 Early prototypes of Fossil were written in pure Tcl. But as the development
20 shifted toward the use of C-code, the need arose to have a Tcl-like
21 scripting language to help with code generation. TH1 was small and
22 light-weight and used minimal resources and seemed ideally suited for the
23 task.
24
25 The name "TH1" stands "Test Harness 1", since that was its original purpose.
26
@@ -78,11 +78,11 @@
78 just a single command.
79
80 Summary of Core TH1 Commands
81 ----------------------------
82
83 The original Tcl language after when TH1 is modeled has a very rich
84 repertoire of commands. TH1, as it is designed to be minimalist and
85 embedded has a greatly reduced command set. The following bullets
86 summarize the commands available in TH1:
87
88 * break
@@ -90,11 +90,13 @@
90 * continue
91 * error ?STRING?
92 * expr EXPR
93 * for INIT-SCRIPT TEST-EXPR NEXT-SCRIPT BODY-SCRIPT
94 * if EXPR SCRIPT (elseif EXPR SCRIPT)* ?else SCRIPT?
95 * info commands
96 * info exists VARNAME
97 * info vars
98 * lindex LIST INDEX
99 * list ARG ...
100 * llength LIST
101 * proc NAME ARG-LIST BODY-SCRIPT
102 * rename OLD NEW
@@ -109,12 +111,12 @@
111 * string repeat STRING COUNT
112 * unset VARNAME
113 * uplevel ?LEVEL? SCRIPT
114 * upvar ?FRAME? OTHERVAR MYVAR ?OTHERVAR MYVAR?
115
116 All of the above commands works as in the original Tcl. Refer to the
117 Tcl documentation for details.
118
119 TH1 Extended Commands
120 ---------------------
121
122 There are many new commands added to TH1 and used to access the special
@@ -128,16 +130,16 @@
130 * date
131 * decorate
132 * enable_output
133 * getParameter
134 * globalState
 
135 * hascap
136 * hasfeature
137 * html
138 * htmlize
139 * http
140 * httpize
141 * linecount
142 * puts
143 * query
144 * randhex
145 * regexp
@@ -147,20 +149,420 @@
149 * searchable
150 * setParameter
151 * setting
152 * styleHeader
153 * styleFooter
154 * tclEval
155 * tclExpr
156 * tclInvoke
157 * tclReady
158 * trace
159 * stime
160 * utime
161 * wiki
162
163 Each of the commands above is documented by a block comment above their
164 implementation in the th\_main.c or th\_tcl.c source files.
165
166 All commands starting with "tcl", with the exception of "tclReady",
167 require the Tcl integration subsystem be included at compile-time.
168 Additionally, the "tcl" repository setting must be enabled at runtime
169 in order to successfully make use of these commands.
170
171 TH1 anoncap Command
172 -------------------
173
174 * anoncap STRING...
175
176 Returns true if the anonymous user has all of the capabilities listed
177 in STRING.
178
179 TH1 anycap Command
180 ------------------
181
182 * anycap STRING
183
184 Returns true if the current user user has any one of the capabilities
185 listed in STRING.
186
187 TH1 artifact Command
188 --------------------
189
190 * artifact ID ?FILENAME?
191
192 Attempts to locate the specified artifact and return its contents. An
193 error is generated if the repository is not open or the artifact cannot
194 be found.
195
196 TH1 checkout Command
197 --------------------
198
199 * checkout ?BOOLEAN?
200
201 Return the fully qualified directory name of the current checkout or an
202 empty string if it is not available. Optionally, it will attempt to find
203 the current checkout, opening the configuration ("user") database and the
204 repository as necessary, if the boolean argument is non-zero.
205
206 TH1 combobox Command
207 --------------------
208
209 * combobox NAME TEXT-LIST NUMLINES
210
211 Generates and emits an HTML combobox. NAME is both the name of the
212 CGI parameter and the name of a variable that contains the currently
213 selected value. TEXT-LIST is a list of possible values for the
214 combobox. NUMLINES is 1 for a true combobox. If NUMLINES is greater
215 than one then the display is a listbox with the number of lines given.
216
217 TH1 date Command
218 ----------------
219
220 * date ?-local?
221
222 Return a strings which is the current time and date. If the -local
223 option is used, the date appears using localtime instead of UTC.
224
225 TH1 decorate Command
226 --------------------
227
228 * decorate STRING
229
230 Renders STRING as wiki content; however, only links are handled. No
231 other markup is processed.
232
233 TH1 enable_output Command
234 -------------------------
235
236 * enable_output BOOLEAN
237
238 Enable or disable sending output when the combobox, puts, or wiki
239 commands are used.
240
241 TH1 getParameter Command
242 ------------------------
243
244 * getParameter NAME ?DEFAULT?
245
246 Returns the value of the specified query parameter or the specified
247 default value when there is no matching query parameter.
248
249 TH1 globalState Command
250 -----------------------
251
252 * globalState NAME ?DEFAULT?
253
254 Returns a string containing the value of the specified global state
255 variable -OR- the specified default value. The supported items are:
256
257 1. **checkout** -- _Active local checkout directory, if any._
258 1. **configuration** -- _Active configuration database file name, if any._
259 1. **executable** -- _Fully qualified executable file name._
260 1. **flags** -- _TH1 initialization flags._
261 1. **log** -- _Error log file name, if any._
262 1. **repository** -- _Active local repository file name, if any._
263 1. **top** -- _Base path for the active server instance, if applicable._
264 1. **user** -- _Active user name, if any._
265 1. **vfs** -- _SQLite VFS in use, if overridden._
266
267 Attempts to query for unsupported global state variables will result
268 in a script error. Additional global state variables may be exposed
269 in the future.
270
271 TH1 hascap Command
272 ------------------
273
274 * hascap STRING...
275
276 Returns true if the current user has all of the capabilities listed
277 in STRING.
278
279 TH1 hasfeature Command
280 ----------------------
281
282 * hasfeature STRING
283
284 Returns true if the binary has the given compile-time feature enabled.
285 The possible features are:
286
287 1. **ssl** -- _Support for the HTTPS transport._
288 1. **th1Docs** -- _Support for TH1 in embedded documentation._
289 1. **th1Hooks** -- _Support for TH1 command and web page hooks._
290 1. **tcl** -- _Support for Tcl integration._
291 1. **useTclStubs** -- _Tcl stubs enabled in the Tcl headers._
292 1. **tclStubs** -- _Uses Tcl stubs (i.e. linking with stubs library)._
293 1. **tclPrivateStubs** -- _Uses Tcl private stubs (i.e. header-only)._
294 1. **json** -- _Support for the JSON APIs._
295 1. **markdown** -- _Support for Markdown documentation format._
296 1. **unicodeCmdLine** -- _The command line arguments are Unicode._
297
298 TH1 html Command
299 ----------------
300
301 * html STRING
302
303 Outputs the STRING escaped for HTML.
304
305 TH1 htmlize Command
306 -------------------
307
308 * htmlize STRING
309
310 Escape all characters of STRING which have special meaning in HTML.
311 Returns the escaped string.
312
313 TH1 http Command
314 ----------------
315
316 * http ?-asynchronous? ?--? url ?payload?
317
318 Performs an HTTP or HTTPS request for the specified URL. If a
319 payload is present, it will be interpreted as text/plain and
320 the POST method will be used; otherwise, the GET method will
321 be used. Upon success, if the -asynchronous option is used, an
322 empty string is returned as the result; otherwise, the response
323 from the server is returned as the result. Synchronous requests
324 are not currently implemented.
325
326 TH1 httpize Command
327 -------------------
328
329 * httpize STRING
330
331 Escape all characters of STRING which have special meaning in URI
332 components. Returns the escaped string.
333
334 TH1 linecount Command
335 ---------------------
336
337 * linecount STRING MAX MIN
338
339 Returns one more than the number of \n characters in STRING. But
340 never returns less than MIN or more than MAX.
341
342 TH1 puts Command
343 ----------------
344
345 * puts STRING
346
347 Outputs the STRING unchanged.
348
349 TH1 query Command
350 -----------------
351
352 * query SQL CODE
353
354 Runs the SQL query given by the SQL argument. For each row in the result
355 set, run CODE.
356
357 In SQL, parameters such as $var are filled in using the value of variable
358 "var". Result values are stored in variables with the column name prior
359 to each invocation of CODE.
360
361 TH1 randhex Command
362 -------------------
363
364 * randhex N
365
366 Returns a string of N*2 random hexadecimal digits with N<50. If N is
367 omitted, use a value of 10.
368
369 TH1 regexp Command
370 ------------------
371
372 * regexp ?-nocase? ?--? exp string
373
374 Checks the string against the specified regular expression and returns
375 non-zero if it matches. If the regular expression is invalid or cannot
376 be compiled, an error will be generated.
377
378 TH1 reinitialize Command
379 ------------------------
380
381 * reinitialize ?FLAGS?
382
383 Reinitializes the TH1 interpreter using the specified flags.
384
385 TH1 render Command
386 ------------------
387
388 * render STRING
389
390 Renders the TH1 template and writes the results.
391
392 TH1 repository Command
393 ----------------------
394
395 * repository ?BOOLEAN?
396
397 Returns the fully qualified file name of the open repository or an empty
398 string if one is not currently open. Optionally, it will attempt to open
399 the repository if the boolean argument is non-zero.
400
401 TH1 searchable Command
402 ----------------------
403
404 * searchable STRING...
405
406 Return true if searching in any of the document classes identified
407 by STRING is enabled for the repository and user has the necessary
408 capabilities to perform the search. The possible document classes
409 are:
410
411 1. **c** -- _Check-in comments_
412 1. **d** -- _Embedded documentation_
413 1. **t** -- _Tickets_
414 1. **w** -- _Wiki_
415
416 To be clear, only one of the document classes identified by each STRING
417 needs to be searchable in order for that argument to be true. But all
418 arguments must be true for this routine to return true. Hence, to see
419 if ALL document classes are searchable:
420
421 if {[searchable c d t w]} {...}
422
423 But to see if ANY document class is searchable:
424
425 if {[searchable cdtw]} {...}
426
427 This command is useful for enabling or disabling a "Search" entry on the
428 menu bar.
429
430 TH1 setParameter Command
431 ------------------------
432
433 * setParameter NAME VALUE
434
435 Sets the value of the specified query parameter.
436
437 TH1 setting Command
438 -------------------
439
440 * setting name
441
442 Gets and returns the value of the specified setting.
443
444 TH1 styleHeader Command
445 -----------------------
446
447 * styleHeader TITLE
448
449 Render the configured style header.
450
451 TH1 styleFooter Command
452 -----------------------
453
454 * styleFooter
455
456 Render the configured style footer.
457
458 TH1 tclEval Command
459 -------------------
460
461 **This command requires the Tcl integration feature.**
462
463 * tclEval arg ?arg ...?
464
465 Evaluates the Tcl script and returns its result verbatim. If a Tcl script
466 error is generated, it will be transformed into a TH1 script error. A Tcl
467 interpreter will be created automatically if it has not been already.
468
469 TH1 tclExpr Command
470 -------------------
471
472 **This command requires the Tcl integration feature.**
473
474 * tclExpr arg ?arg ...?
475
476 Evaluates the Tcl expression and returns its result verbatim. If a Tcl
477 script error is generated, it will be transformed into a TH1 script error.
478 A Tcl interpreter will be created automatically if it has not been already.
479
480 TH1 tclInvoke Command
481 ---------------------
482
483 **This command requires the Tcl integration feature.**
484
485 * tclInvoke command ?arg ...?
486
487 Invokes the Tcl command using the supplied arguments. No additional
488 substitutions are performed on the arguments. A Tcl interpreter will
489 be created automatically if it has not been already.
490
491 TH1 tclReady Command
492 --------------------
493
494 * tclReady
495
496 Returns true if the binary has the Tcl integration feature enabled and it
497 is currently available for use by TH1 scripts.
498
499 TH1 trace Command
500 -----------------
501
502 * trace STRING
503
504 Generates a TH1 trace message if TH1 tracing is enabled.
505
506 TH1 stime Command
507 -----------------
508
509 * stime
510
511 Returns the number of microseconds of CPU time consumed by the current
512 process in system space.
513
514 TH1 utime Command
515 -----------------
516
517 * utime
518
519 Returns the number of microseconds of CPU time consumed by the current
520 process in user space.
521
522 TH1 wiki Command
523 ----------------
524
525 * wiki STRING
526
527 Renders STRING as wiki content.
528
529 Tcl Integration Commands
530 ------------------------
531
532 When the Tcl integration subsystem is enabled, several commands are added
533 to the Tcl interpreter. They are used to allow Tcl scripts access to the
534 Fossil functionality provided via TH1. The following is a summary of the
535 Tcl commands:
536
537 * th1Eval
538 * th1Expr
539
540 Tcl th1Eval Command
541 -------------------
542
543 **This command requires the Tcl integration feature.**
544
545 * th1Eval arg
546
547 Evaluates the TH1 script and returns its result verbatim. If a TH1 script
548 error is generated, it will be transformed into a Tcl script error.
549
550 Tcl th1Expr Command
551 -------------------
552
553 **This command requires the Tcl integration feature.**
554
555 * th1Expr arg
556
557 Evaluates the TH1 expression and returns its result verbatim. If a TH1
558 script error is generated, it will be transformed into a Tcl script error.
559
560 Further Notes
561 -------------
562
563 **To Do:** We would like to have a community volunteer go through and
564 copy the documentation for each of these commands (with appropriate
565 format changes and spelling and grammar corrections) into subsequent
566 sections of this document. It is suggested that the list of extension
567 commands be left intact - as a quick reference. But it would be really
568 nice to also have the details of what each command does.
569

Keyboard Shortcuts

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