Fossil SCM
Merge updates from trunk.
Commit
55f7ec6c5d0e338937b14b5b2bb0fb43bdeb9c8a
Parent
bc31308652f722c…
15 files changed
+24
-2
+24
-2
+63
-52
+52
-14
+1
-1
+69
-3
+6
+52
-2
+4
-2
+4
-2
+61
-16
+1
-1
+40
+8
+413
-11
+24
-2
| --- skins/blitz/css.txt | ||
| +++ skins/blitz/css.txt | ||
| @@ -1054,26 +1054,48 @@ | ||
| 1054 | 1054 | * Displays chronologically-ordered check-ins with a branch graph. |
| 1055 | 1055 | ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */ |
| 1056 | 1056 | tr.timelineCurrent { |
| 1057 | 1057 | border-left: 2px solid orange; |
| 1058 | 1058 | background-color: #ffc; |
| 1059 | + border-bottom: 1px solid #ddd; | |
| 1060 | + border-right: 1px solid #ddd; | |
| 1059 | 1061 | } |
| 1060 | 1062 | |
| 1061 | 1063 | tr.timelineSelected { |
| 1062 | 1064 | border-left: 2px solid orange; |
| 1063 | 1065 | background-color: #ffffe8; |
| 1066 | + border-bottom: 1px solid #ddd; | |
| 1067 | + border-right: 1px solid #ddd; | |
| 1064 | 1068 | } |
| 1065 | 1069 | |
| 1066 | 1070 | tr.timelineCurrent td.timelineTableCell { |
| 1067 | 1071 | } |
| 1068 | 1072 | |
| 1069 | 1073 | tr.timelineSpacer { |
| 1070 | 1074 | } |
| 1075 | + | |
| 1076 | +tr.timelineBottom td { | |
| 1077 | + border-bottom: 0; | |
| 1078 | +} | |
| 1071 | 1079 | |
| 1072 | 1080 | 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; | |
| 1075 | 1097 | } |
| 1076 | 1098 | |
| 1077 | 1099 | a.timelineHistLink { |
| 1078 | 1100 | text-transform: lowercase; |
| 1079 | 1101 | } |
| 1080 | 1102 |
| --- 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 |
+24
-2
| --- skins/blitz_no_logo/css.txt | ||
| +++ skins/blitz_no_logo/css.txt | ||
| @@ -1054,26 +1054,48 @@ | ||
| 1054 | 1054 | * Displays chronologically-ordered check-ins with a branch graph. |
| 1055 | 1055 | ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */ |
| 1056 | 1056 | tr.timelineCurrent { |
| 1057 | 1057 | border-left: 2px solid orange; |
| 1058 | 1058 | background-color: #ffc; |
| 1059 | + border-bottom: 1px solid #ddd; | |
| 1060 | + border-right: 1px solid #ddd; | |
| 1059 | 1061 | } |
| 1060 | 1062 | |
| 1061 | 1063 | tr.timelineSelected { |
| 1062 | 1064 | border-left: 2px solid orange; |
| 1063 | 1065 | background-color: #ffffe8; |
| 1066 | + border-bottom: 1px solid #ddd; | |
| 1067 | + border-right: 1px solid #ddd; | |
| 1064 | 1068 | } |
| 1065 | 1069 | |
| 1066 | 1070 | tr.timelineCurrent td.timelineTableCell { |
| 1067 | 1071 | } |
| 1068 | 1072 | |
| 1069 | 1073 | tr.timelineSpacer { |
| 1070 | 1074 | } |
| 1075 | + | |
| 1076 | +tr.timelineBottom td { | |
| 1077 | + border-bottom: 0; | |
| 1078 | +} | |
| 1071 | 1079 | |
| 1072 | 1080 | 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; | |
| 1075 | 1097 | } |
| 1076 | 1098 | |
| 1077 | 1099 | a.timelineHistLink { |
| 1078 | 1100 | text-transform: lowercase; |
| 1079 | 1101 | } |
| 1080 | 1102 |
| --- 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 @@ | ||
| 87 | 87 | ** On Win32 systems, the file is named "_fossil" and is located in |
| 88 | 88 | ** %LOCALAPPDATA%, %APPDATA% or %HOMEPATH%. |
| 89 | 89 | ** |
| 90 | 90 | ** Available operations are: |
| 91 | 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. | |
| 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. | |
| 130 | 132 | ** |
| 131 | 133 | ** In addition, the following maintenance operations are supported: |
| 132 | 134 | ** |
| 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. | |
| 145 | 147 | ** |
| 146 | 148 | ** Repositories are automatically added to the set of known repositories |
| 147 | 149 | ** when one of the following commands are run against the repository: |
| 148 | 150 | ** clone, info, pull, push, or sync. Even previously ignored repositories |
| 149 | 151 | ** are added back to the list of repositories by these commands. |
| @@ -174,11 +176,11 @@ | ||
| 174 | 176 | if( !dryRunFlag ){ |
| 175 | 177 | dryRunFlag = find_option("test",0,0)!=0; /* deprecated */ |
| 176 | 178 | } |
| 177 | 179 | |
| 178 | 180 | if( g.argc<3 ){ |
| 179 | - usage("changes|clean|extras|ignore|list|ls|pull|push|rebuild|sync"); | |
| 181 | + usage("SUBCOMMAND ..."); | |
| 180 | 182 | } |
| 181 | 183 | n = strlen(g.argv[2]); |
| 182 | 184 | db_open_config(1); |
| 183 | 185 | blob_zero(&extra); |
| 184 | 186 | zCmd = g.argv[2]; |
| @@ -284,10 +286,13 @@ | ||
| 284 | 286 | }else{ |
| 285 | 287 | db_multi_exec("%s", blob_sql_text(&sql)); |
| 286 | 288 | } |
| 287 | 289 | } |
| 288 | 290 | db_end_transaction(0); |
| 291 | + blob_reset(&sql); | |
| 292 | + blob_reset(&fn); | |
| 293 | + blob_reset(&extra); | |
| 289 | 294 | return; |
| 290 | 295 | }else if( strncmp(zCmd, "add", n)==0 ){ |
| 291 | 296 | int j; |
| 292 | 297 | Blob fn = BLOB_INITIALIZER; |
| 293 | 298 | Blob sql = BLOB_INITIALIZER; |
| @@ -313,18 +318,22 @@ | ||
| 313 | 318 | }else{ |
| 314 | 319 | db_multi_exec("%s", blob_sql_text(&sql)); |
| 315 | 320 | } |
| 316 | 321 | } |
| 317 | 322 | db_end_transaction(0); |
| 323 | + blob_reset(&sql); | |
| 324 | + blob_reset(&fn); | |
| 325 | + blob_reset(&extra); | |
| 318 | 326 | return; |
| 319 | 327 | }else if( strncmp(zCmd, "info", n)==0 ){ |
| 320 | 328 | zCmd = "info"; |
| 321 | 329 | showLabel = 1; |
| 322 | 330 | quiet = 1; |
| 323 | 331 | }else{ |
| 324 | 332 | 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"); | |
| 326 | 335 | } |
| 327 | 336 | verify_all_options(); |
| 328 | 337 | zFossil = quoteFilename(g.nameOfExe); |
| 329 | 338 | db_multi_exec("CREATE TEMP TABLE repolist(name,tag);"); |
| 330 | 339 | if( useCheckouts ){ |
| @@ -382,10 +391,12 @@ | ||
| 382 | 391 | if( stopOnError && rc ){ |
| 383 | 392 | break; |
| 384 | 393 | } |
| 385 | 394 | } |
| 386 | 395 | db_finalize(&q); |
| 396 | + | |
| 397 | + blob_reset(&extra); | |
| 387 | 398 | |
| 388 | 399 | /* If any repositories whose names appear in the ~/.fossil file could not |
| 389 | 400 | ** be found, remove those names from the ~/.fossil file. |
| 390 | 401 | */ |
| 391 | 402 | if( nToDel>0 ){ |
| 392 | 403 |
| --- 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 @@ | ||
| 317 | 317 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 318 | 318 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 319 | 319 | */ |
| 320 | 320 | #define SQLITE_VERSION "3.8.9" |
| 321 | 321 | #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" | |
| 323 | 323 | |
| 324 | 324 | /* |
| 325 | 325 | ** CAPI3REF: Run-Time Library Version Numbers |
| 326 | 326 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 327 | 327 | ** |
| @@ -29147,11 +29147,11 @@ | ||
| 29147 | 29147 | */ |
| 29148 | 29148 | static int unixFileControl(sqlite3_file *id, int op, void *pArg){ |
| 29149 | 29149 | unixFile *pFile = (unixFile*)id; |
| 29150 | 29150 | switch( op ){ |
| 29151 | 29151 | case SQLITE_FCNTL_WAL_BLOCK: { |
| 29152 | - pFile->ctrlFlags |= UNIXFILE_BLOCK; | |
| 29152 | + /* pFile->ctrlFlags |= UNIXFILE_BLOCK; // Deferred feature */ | |
| 29153 | 29153 | return SQLITE_OK; |
| 29154 | 29154 | } |
| 29155 | 29155 | case SQLITE_FCNTL_LOCKSTATE: { |
| 29156 | 29156 | *(int*)pArg = pFile->eFileLock; |
| 29157 | 29157 | return SQLITE_OK; |
| @@ -33323,12 +33323,14 @@ | ||
| 33323 | 33323 | |
| 33324 | 33324 | WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T); |
| 33325 | 33325 | #endif /* SQLITE_OS_WINRT */ |
| 33326 | 33326 | |
| 33327 | 33327 | /* |
| 33328 | -** This file mapping API is common to both Win32 and WinRT. | |
| 33328 | +** These file mapping APIs are common to both Win32 and WinRT. | |
| 33329 | 33329 | */ |
| 33330 | + | |
| 33331 | +WINBASEAPI BOOL WINAPI FlushViewOfFile(LPCVOID, SIZE_T); | |
| 33330 | 33332 | WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID); |
| 33331 | 33333 | #endif /* SQLITE_WIN32_FILEMAPPING_API */ |
| 33332 | 33334 | |
| 33333 | 33335 | /* |
| 33334 | 33336 | ** Some Microsoft compilers lack this definition. |
| @@ -34209,10 +34211,19 @@ | ||
| 34209 | 34211 | #endif |
| 34210 | 34212 | |
| 34211 | 34213 | #define osUuidCreateSequential \ |
| 34212 | 34214 | ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent) |
| 34213 | 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 | + | |
| 34214 | 34225 | }; /* End of the overrideable system calls */ |
| 34215 | 34226 | |
| 34216 | 34227 | /* |
| 34217 | 34228 | ** This is the xSetSystemCall() method of sqlite3_vfs for all of the |
| 34218 | 34229 | ** "win32" VFSes. Return SQLITE_OK opon successfully updating the |
| @@ -35094,11 +35105,11 @@ | ||
| 35094 | 35105 | /* |
| 35095 | 35106 | ** Log a I/O error retry episode. |
| 35096 | 35107 | */ |
| 35097 | 35108 | static void winLogIoerr(int nRetry, int lineno){ |
| 35098 | 35109 | if( nRetry ){ |
| 35099 | - sqlite3_log(SQLITE_IOERR, | |
| 35110 | + sqlite3_log(SQLITE_NOTICE, | |
| 35100 | 35111 | "delayed %dms for lock/sharing conflict at line %d", |
| 35101 | 35112 | winIoerrRetryDelay*nRetry*(nRetry+1)/2, lineno |
| 35102 | 35113 | ); |
| 35103 | 35114 | } |
| 35104 | 35115 | } |
| @@ -35914,10 +35925,26 @@ | ||
| 35914 | 35925 | #ifdef SQLITE_NO_SYNC |
| 35915 | 35926 | OSTRACE(("SYNC-NOP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", |
| 35916 | 35927 | osGetCurrentProcessId(), pFile, pFile->h)); |
| 35917 | 35928 | return SQLITE_OK; |
| 35918 | 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 | |
| 35919 | 35946 | rc = osFlushFileBuffers(pFile->h); |
| 35920 | 35947 | SimulateIOError( rc=FALSE ); |
| 35921 | 35948 | if( rc ){ |
| 35922 | 35949 | OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", |
| 35923 | 35950 | osGetCurrentProcessId(), pFile, pFile->h)); |
| @@ -35925,11 +35952,11 @@ | ||
| 35925 | 35952 | }else{ |
| 35926 | 35953 | pFile->lastErrno = osGetLastError(); |
| 35927 | 35954 | OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_FSYNC\n", |
| 35928 | 35955 | osGetCurrentProcessId(), pFile, pFile->h)); |
| 35929 | 35956 | return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno, |
| 35930 | - "winSync", pFile->zPath); | |
| 35957 | + "winSync2", pFile->zPath); | |
| 35931 | 35958 | } |
| 35932 | 35959 | #endif |
| 35933 | 35960 | } |
| 35934 | 35961 | |
| 35935 | 35962 | /* |
| @@ -38699,11 +38726,11 @@ | ||
| 38699 | 38726 | }; |
| 38700 | 38727 | #endif |
| 38701 | 38728 | |
| 38702 | 38729 | /* Double-check that the aSyscall[] array has been constructed |
| 38703 | 38730 | ** correctly. See ticket [bb3a86e890c8e96ab] */ |
| 38704 | - assert( ArraySize(aSyscall)==79 ); | |
| 38731 | + assert( ArraySize(aSyscall)==80 ); | |
| 38705 | 38732 | |
| 38706 | 38733 | /* get memory map allocation granularity */ |
| 38707 | 38734 | memset(&winSysInfo, 0, sizeof(SYSTEM_INFO)); |
| 38708 | 38735 | #if SQLITE_OS_WINRT |
| 38709 | 38736 | osGetNativeSystemInfo(&winSysInfo); |
| @@ -52246,10 +52273,11 @@ | ||
| 52246 | 52273 | u8 noPayload; /* True if internal intKey page (thus w/o data) */ |
| 52247 | 52274 | u8 leaf; /* True if a leaf page */ |
| 52248 | 52275 | u8 hdrOffset; /* 100 for page 1. 0 otherwise */ |
| 52249 | 52276 | u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */ |
| 52250 | 52277 | u8 max1bytePayload; /* min(maxLocal,127) */ |
| 52278 | + u8 bBusy; /* Prevent endless loops on corrupt database files */ | |
| 52251 | 52279 | u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */ |
| 52252 | 52280 | u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */ |
| 52253 | 52281 | u16 cellOffset; /* Index in aData of first cell pointer */ |
| 52254 | 52282 | u16 nFree; /* Number of free bytes on the page */ |
| 52255 | 52283 | u16 nCell; /* Number of cells on this page, local and ovfl */ |
| @@ -54894,20 +54922,22 @@ | ||
| 54894 | 54922 | ** If this Btree is a candidate for shared cache, try to find an |
| 54895 | 54923 | ** existing BtShared object that we can share with |
| 54896 | 54924 | */ |
| 54897 | 54925 | if( isTempDb==0 && (isMemdb==0 || (vfsFlags&SQLITE_OPEN_URI)!=0) ){ |
| 54898 | 54926 | if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){ |
| 54927 | + int nFilename = sqlite3Strlen30(zFilename)+1; | |
| 54899 | 54928 | int nFullPathname = pVfs->mxPathname+1; |
| 54900 | - char *zFullPathname = sqlite3Malloc(nFullPathname); | |
| 54929 | + char *zFullPathname = sqlite3Malloc(MAX(nFullPathname,nFilename)); | |
| 54901 | 54930 | MUTEX_LOGIC( sqlite3_mutex *mutexShared; ) |
| 54931 | + | |
| 54902 | 54932 | p->sharable = 1; |
| 54903 | 54933 | if( !zFullPathname ){ |
| 54904 | 54934 | sqlite3_free(p); |
| 54905 | 54935 | return SQLITE_NOMEM; |
| 54906 | 54936 | } |
| 54907 | 54937 | if( isMemdb ){ |
| 54908 | - memcpy(zFullPathname, zFilename, sqlite3Strlen30(zFilename)+1); | |
| 54938 | + memcpy(zFullPathname, zFilename, nFilename); | |
| 54909 | 54939 | }else{ |
| 54910 | 54940 | rc = sqlite3OsFullPathname(pVfs, zFilename, |
| 54911 | 54941 | nFullPathname, zFullPathname); |
| 54912 | 54942 | if( rc ){ |
| 54913 | 54943 | sqlite3_free(zFullPathname); |
| @@ -60913,32 +60943,33 @@ | ||
| 60913 | 60943 | int rc; |
| 60914 | 60944 | unsigned char *pCell; |
| 60915 | 60945 | int i; |
| 60916 | 60946 | int hdr; |
| 60917 | 60947 | u16 szCell; |
| 60918 | - u8 hasChildren; | |
| 60919 | 60948 | |
| 60920 | 60949 | assert( sqlite3_mutex_held(pBt->mutex) ); |
| 60921 | 60950 | if( pgno>btreePagecount(pBt) ){ |
| 60922 | 60951 | return SQLITE_CORRUPT_BKPT; |
| 60923 | 60952 | } |
| 60924 | - | |
| 60925 | 60953 | rc = getAndInitPage(pBt, pgno, &pPage, 0); |
| 60926 | 60954 | 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; | |
| 60929 | 60960 | hdr = pPage->hdrOffset; |
| 60930 | 60961 | for(i=0; i<pPage->nCell; i++){ |
| 60931 | 60962 | pCell = findCell(pPage, i); |
| 60932 | - if( hasChildren ){ | |
| 60963 | + if( !pPage->leaf ){ | |
| 60933 | 60964 | rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange); |
| 60934 | 60965 | if( rc ) goto cleardatabasepage_out; |
| 60935 | 60966 | } |
| 60936 | 60967 | rc = clearCell(pPage, pCell, &szCell); |
| 60937 | 60968 | if( rc ) goto cleardatabasepage_out; |
| 60938 | 60969 | } |
| 60939 | - if( hasChildren ){ | |
| 60970 | + if( !pPage->leaf ){ | |
| 60940 | 60971 | rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange); |
| 60941 | 60972 | if( rc ) goto cleardatabasepage_out; |
| 60942 | 60973 | }else if( pnChange ){ |
| 60943 | 60974 | assert( pPage->intKey ); |
| 60944 | 60975 | *pnChange += pPage->nCell; |
| @@ -60948,10 +60979,11 @@ | ||
| 60948 | 60979 | }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){ |
| 60949 | 60980 | zeroPage(pPage, pPage->aData[hdr] | PTF_LEAF); |
| 60950 | 60981 | } |
| 60951 | 60982 | |
| 60952 | 60983 | cleardatabasepage_out: |
| 60984 | + pPage->bBusy = 0; | |
| 60953 | 60985 | releasePage(pPage); |
| 60954 | 60986 | return rc; |
| 60955 | 60987 | } |
| 60956 | 60988 | |
| 60957 | 60989 | /* |
| @@ -72561,15 +72593,19 @@ | ||
| 72561 | 72593 | }else if( affinity==SQLITE_AFF_TEXT ){ |
| 72562 | 72594 | if( (pIn1->flags & MEM_Str)==0 && (pIn1->flags & (MEM_Int|MEM_Real))!=0 ){ |
| 72563 | 72595 | testcase( pIn1->flags & MEM_Int ); |
| 72564 | 72596 | testcase( pIn1->flags & MEM_Real ); |
| 72565 | 72597 | sqlite3VdbeMemStringify(pIn1, encoding, 1); |
| 72598 | + testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) ); | |
| 72599 | + flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask); | |
| 72566 | 72600 | } |
| 72567 | 72601 | if( (pIn3->flags & MEM_Str)==0 && (pIn3->flags & (MEM_Int|MEM_Real))!=0 ){ |
| 72568 | 72602 | testcase( pIn3->flags & MEM_Int ); |
| 72569 | 72603 | testcase( pIn3->flags & MEM_Real ); |
| 72570 | 72604 | sqlite3VdbeMemStringify(pIn3, encoding, 1); |
| 72605 | + testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) ); | |
| 72606 | + flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask); | |
| 72571 | 72607 | } |
| 72572 | 72608 | } |
| 72573 | 72609 | assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 ); |
| 72574 | 72610 | if( pIn1->flags & MEM_Zero ){ |
| 72575 | 72611 | sqlite3VdbeMemExpandBlob(pIn1); |
| @@ -72602,11 +72638,13 @@ | ||
| 72602 | 72638 | if( res ){ |
| 72603 | 72639 | pc = pOp->p2-1; |
| 72604 | 72640 | } |
| 72605 | 72641 | } |
| 72606 | 72642 | /* Undo any changes made by applyAffinity() to the input registers. */ |
| 72643 | + assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) ); | |
| 72607 | 72644 | pIn1->flags = flags1; |
| 72645 | + assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) ); | |
| 72608 | 72646 | pIn3->flags = flags3; |
| 72609 | 72647 | break; |
| 72610 | 72648 | } |
| 72611 | 72649 | |
| 72612 | 72650 | /* Opcode: Permutation * * * P4 * |
| 72613 | 72651 |
| --- 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 @@ | ||
| 111 | 111 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 112 | 112 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 113 | 113 | */ |
| 114 | 114 | #define SQLITE_VERSION "3.8.9" |
| 115 | 115 | #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" | |
| 117 | 117 | |
| 118 | 118 | /* |
| 119 | 119 | ** CAPI3REF: Run-Time Library Version Numbers |
| 120 | 120 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 121 | 121 | ** |
| 122 | 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-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 |
M
src/th.c
+69
-3
| --- src/th.c | ||
| +++ src/th.c | ||
| @@ -7,13 +7,14 @@ | ||
| 7 | 7 | #include "config.h" |
| 8 | 8 | #include "th.h" |
| 9 | 9 | #include <string.h> |
| 10 | 10 | #include <assert.h> |
| 11 | 11 | |
| 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; | |
| 15 | 16 | |
| 16 | 17 | /* |
| 17 | 18 | ** Interpreter structure. |
| 18 | 19 | */ |
| 19 | 20 | struct Th_Interp { |
| @@ -87,10 +88,21 @@ | ||
| 87 | 88 | int nRef; /* Number of references to this structure */ |
| 88 | 89 | int nData; /* Number of bytes at Th_Variable.zData */ |
| 89 | 90 | char *zData; /* Data for scalar variables */ |
| 90 | 91 | Th_Hash *pHash; /* Data for array variables */ |
| 91 | 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 | +}; | |
| 92 | 104 | |
| 93 | 105 | /* |
| 94 | 106 | ** Hash table API: |
| 95 | 107 | */ |
| 96 | 108 | #define TH_HASHSIZE 257 |
| @@ -298,10 +310,25 @@ | ||
| 298 | 310 | } |
| 299 | 311 | Th_Free((Th_Interp *)pContext, pEntry->pData); |
| 300 | 312 | pEntry->pData = 0; |
| 301 | 313 | return 1; |
| 302 | 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 | +} | |
| 303 | 330 | |
| 304 | 331 | /* |
| 305 | 332 | ** Push a new frame onto the stack. |
| 306 | 333 | */ |
| 307 | 334 | static int thPushFrame(Th_Interp *interp, Th_Frame *pFrame){ |
| @@ -2832,5 +2859,44 @@ | ||
| 2832 | 2859 | } |
| 2833 | 2860 | |
| 2834 | 2861 | *z = '\0'; |
| 2835 | 2862 | return Th_SetResult(interp, zBuf, -1); |
| 2836 | 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 | +} | |
| 2837 | 2903 |
| --- 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 |
M
src/th.h
+6
| --- src/th.h | ||
| +++ src/th.h | ||
| @@ -138,10 +138,16 @@ | ||
| 138 | 138 | int Th_ToInt(Th_Interp *, const char *, int, int *); |
| 139 | 139 | int Th_ToDouble(Th_Interp *, const char *, int, double *); |
| 140 | 140 | int Th_SetResultInt(Th_Interp *, int); |
| 141 | 141 | int Th_SetResultDouble(Th_Interp *, double); |
| 142 | 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 | + | |
| 143 | 149 | /* |
| 144 | 150 | ** Drop in replacements for the corresponding standard library functions. |
| 145 | 151 | */ |
| 146 | 152 | int th_strlen(const char *); |
| 147 | 153 | int th_isdigit(char); |
| 148 | 154 |
| --- 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 @@ | ||
| 848 | 848 | } |
| 849 | 849 | |
| 850 | 850 | /* |
| 851 | 851 | ** TH Syntax: |
| 852 | 852 | ** |
| 853 | -** info exists VAR | |
| 853 | +** info exists VARNAME | |
| 854 | 854 | */ |
| 855 | 855 | static int info_exists_command( |
| 856 | 856 | Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl |
| 857 | 857 | ){ |
| 858 | 858 | int rc; |
| @@ -862,10 +862,56 @@ | ||
| 862 | 862 | } |
| 863 | 863 | rc = Th_ExistsVar(interp, argv[2], argl[2]); |
| 864 | 864 | Th_SetResultInt(interp, rc); |
| 865 | 865 | return TH_OK; |
| 866 | 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 | +} | |
| 867 | 913 | |
| 868 | 914 | /* |
| 869 | 915 | ** TH Syntax: |
| 870 | 916 | ** |
| 871 | 917 | ** unset VAR |
| @@ -943,21 +989,25 @@ | ||
| 943 | 989 | } |
| 944 | 990 | |
| 945 | 991 | /* |
| 946 | 992 | ** TH Syntax: |
| 947 | 993 | ** |
| 994 | +** info commands | |
| 948 | 995 | ** info exists VARNAME |
| 996 | +** info vars | |
| 949 | 997 | */ |
| 950 | 998 | static int info_command( |
| 951 | 999 | Th_Interp *interp, |
| 952 | 1000 | void *ctx, |
| 953 | 1001 | int argc, |
| 954 | 1002 | const char **argv, |
| 955 | 1003 | int *argl |
| 956 | 1004 | ){ |
| 957 | 1005 | 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 }, | |
| 959 | 1009 | { 0, 0 } |
| 960 | 1010 | }; |
| 961 | 1011 | return Th_CallSubCommand(interp, ctx, argc, argv, argl, aSub); |
| 962 | 1012 | } |
| 963 | 1013 | |
| 964 | 1014 |
| --- 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 @@ | ||
| 174 | 174 | static int enableOutput = 1; |
| 175 | 175 | |
| 176 | 176 | /* |
| 177 | 177 | ** TH1 command: enable_output BOOLEAN |
| 178 | 178 | ** |
| 179 | -** Enable or disable the puts and hputs commands. | |
| 179 | +** Enable or disable the puts and wiki commands. | |
| 180 | 180 | */ |
| 181 | 181 | static int enableOutputCmd( |
| 182 | 182 | Th_Interp *interp, |
| 183 | 183 | void *p, |
| 184 | 184 | int argc, |
| @@ -339,13 +339,15 @@ | ||
| 339 | 339 | sendText((char*)argv[1], argl[1], *(unsigned int*)pConvert); |
| 340 | 340 | return TH_OK; |
| 341 | 341 | } |
| 342 | 342 | |
| 343 | 343 | /* |
| 344 | +** TH1 command: decorate STRING | |
| 344 | 345 | ** TH1 command: wiki STRING |
| 345 | 346 | ** |
| 346 | -** Render the input string as wiki. | |
| 347 | +** Render the input string as wiki. For the decorate command, only links | |
| 348 | +** are handled. | |
| 347 | 349 | */ |
| 348 | 350 | static int wikiCmd( |
| 349 | 351 | Th_Interp *interp, |
| 350 | 352 | void *p, |
| 351 | 353 | int argc, |
| 352 | 354 |
| --- 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 @@ | ||
| 174 | 174 | static int enableOutput = 1; |
| 175 | 175 | |
| 176 | 176 | /* |
| 177 | 177 | ** TH1 command: enable_output BOOLEAN |
| 178 | 178 | ** |
| 179 | -** Enable or disable the puts and hputs commands. | |
| 179 | +** Enable or disable the puts and wiki commands. | |
| 180 | 180 | */ |
| 181 | 181 | static int enableOutputCmd( |
| 182 | 182 | Th_Interp *interp, |
| 183 | 183 | void *p, |
| 184 | 184 | int argc, |
| @@ -339,13 +339,15 @@ | ||
| 339 | 339 | sendText((char*)argv[1], argl[1], *(unsigned int*)pConvert); |
| 340 | 340 | return TH_OK; |
| 341 | 341 | } |
| 342 | 342 | |
| 343 | 343 | /* |
| 344 | +** TH1 command: decorate STRING | |
| 344 | 345 | ** TH1 command: wiki STRING |
| 345 | 346 | ** |
| 346 | -** Render the input string as wiki. | |
| 347 | +** Render the input string as wiki. For the decorate command, only links | |
| 348 | +** are handled. | |
| 347 | 349 | */ |
| 348 | 350 | static int wikiCmd( |
| 349 | 351 | Th_Interp *interp, |
| 350 | 352 | void *p, |
| 351 | 353 | int argc, |
| 352 | 354 |
| --- 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 @@ | ||
| 250 | 250 | ** interpreter. Stores the created Tcl interpreter in the Tcl context supplied |
| 251 | 251 | ** by the caller. This must be declared here because quite a few functions in |
| 252 | 252 | ** this file need to use it before it can be defined. |
| 253 | 253 | */ |
| 254 | 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 | +} | |
| 255 | 289 | |
| 256 | 290 | /* |
| 257 | 291 | ** Returns a name for a Tcl return code. |
| 258 | 292 | */ |
| 259 | 293 | static const char *getTclReturnCodeName( |
| @@ -263,12 +297,12 @@ | ||
| 263 | 297 | static char zRc[32]; |
| 264 | 298 | |
| 265 | 299 | switch( rc ){ |
| 266 | 300 | case TCL_OK: return nullIfOk ? 0 : "TCL_OK"; |
| 267 | 301 | case TCL_ERROR: return "TCL_ERROR"; |
| 268 | - case TCL_BREAK: return "TCL_BREAK"; | |
| 269 | 302 | case TCL_RETURN: return "TCL_RETURN"; |
| 303 | + case TCL_BREAK: return "TCL_BREAK"; | |
| 270 | 304 | case TCL_CONTINUE: return "TCL_CONTINUE"; |
| 271 | 305 | default: { |
| 272 | 306 | sqlite3_snprintf(sizeof(zRc), zRc, "Tcl return code %d", rc); |
| 273 | 307 | } |
| 274 | 308 | } |
| @@ -350,13 +384,15 @@ | ||
| 350 | 384 | } |
| 351 | 385 | return rc; |
| 352 | 386 | } |
| 353 | 387 | |
| 354 | 388 | /* |
| 355 | -** Syntax: | |
| 389 | +** TH1 command: tclEval arg ?arg ...? | |
| 356 | 390 | ** |
| 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. | |
| 358 | 394 | */ |
| 359 | 395 | static int tclEval_command( |
| 360 | 396 | Th_Interp *interp, |
| 361 | 397 | void *ctx, |
| 362 | 398 | int argc, |
| @@ -400,18 +436,21 @@ | ||
| 400 | 436 | FREE_ARGV_TO_OBJV(); |
| 401 | 437 | } |
| 402 | 438 | zResult = getTclResult(tclInterp, &nResult); |
| 403 | 439 | Th_SetResult(interp, zResult, nResult); |
| 404 | 440 | 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)); | |
| 406 | 443 | return rc; |
| 407 | 444 | } |
| 408 | 445 | |
| 409 | 446 | /* |
| 410 | -** Syntax: | |
| 447 | +** TH1 command: tclExpr arg ?arg ...? | |
| 411 | 448 | ** |
| 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. | |
| 413 | 452 | */ |
| 414 | 453 | static int tclExpr_command( |
| 415 | 454 | Th_Interp *interp, |
| 416 | 455 | void *ctx, |
| 417 | 456 | int argc, |
| @@ -461,18 +500,21 @@ | ||
| 461 | 500 | zResult = getTclResult(tclInterp, &nResult); |
| 462 | 501 | } |
| 463 | 502 | Th_SetResult(interp, zResult, nResult); |
| 464 | 503 | if( rc==TCL_OK ) Tcl_DecrRefCount(resultObjPtr); |
| 465 | 504 | 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)); | |
| 467 | 507 | return rc; |
| 468 | 508 | } |
| 469 | 509 | |
| 470 | 510 | /* |
| 471 | -** Syntax: | |
| 511 | +** TH1 command: tclInvoke command ?arg ...? | |
| 472 | 512 | ** |
| 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. | |
| 474 | 516 | */ |
| 475 | 517 | static int tclInvoke_command( |
| 476 | 518 | Th_Interp *interp, |
| 477 | 519 | void *ctx, |
| 478 | 520 | int argc, |
| @@ -533,18 +575,20 @@ | ||
| 533 | 575 | FREE_ARGV_TO_OBJV(); |
| 534 | 576 | } |
| 535 | 577 | zResult = getTclResult(tclInterp, &nResult); |
| 536 | 578 | Th_SetResult(interp, zResult, nResult); |
| 537 | 579 | 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)); | |
| 539 | 582 | return rc; |
| 540 | 583 | } |
| 541 | 584 | |
| 542 | 585 | /* |
| 543 | -** Syntax: | |
| 586 | +** Tcl command: th1Eval arg | |
| 544 | 587 | ** |
| 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. | |
| 546 | 590 | */ |
| 547 | 591 | static int Th1EvalObjCmd( |
| 548 | 592 | ClientData clientData, |
| 549 | 593 | Tcl_Interp *interp, |
| 550 | 594 | int objc, |
| @@ -566,17 +610,18 @@ | ||
| 566 | 610 | } |
| 567 | 611 | arg = Tcl_GetStringFromObj(objv[1], &nArg); |
| 568 | 612 | rc = Th_Eval(th1Interp, 0, arg, nArg); |
| 569 | 613 | arg = Th_GetResult(th1Interp, &nArg); |
| 570 | 614 | Tcl_SetObjResult(interp, Tcl_NewStringObj(arg, nArg)); |
| 571 | - return rc; | |
| 615 | + return getTclReturnCode(rc); | |
| 572 | 616 | } |
| 573 | 617 | |
| 574 | 618 | /* |
| 575 | -** Syntax: | |
| 619 | +** Tcl command: th1Expr arg | |
| 576 | 620 | ** |
| 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. | |
| 578 | 623 | */ |
| 579 | 624 | static int Th1ExprObjCmd( |
| 580 | 625 | ClientData clientData, |
| 581 | 626 | Tcl_Interp *interp, |
| 582 | 627 | int objc, |
| @@ -598,11 +643,11 @@ | ||
| 598 | 643 | } |
| 599 | 644 | arg = Tcl_GetStringFromObj(objv[1], &nArg); |
| 600 | 645 | rc = Th_Expr(th1Interp, arg, nArg); |
| 601 | 646 | arg = Th_GetResult(th1Interp, &nArg); |
| 602 | 647 | Tcl_SetObjResult(interp, Tcl_NewStringObj(arg, nArg)); |
| 603 | - return rc; | |
| 648 | + return getTclReturnCode(rc); | |
| 604 | 649 | } |
| 605 | 650 | |
| 606 | 651 | /* |
| 607 | 652 | ** Array of Tcl integration commands. Used when adding or removing the Tcl |
| 608 | 653 | ** integration commands from TH1. |
| 609 | 654 |
| --- 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 @@ | ||
| 587 | 587 | int w; |
| 588 | 588 | /* style is not moved to css, because this is |
| 589 | 589 | ** a technical div for the timeline graph |
| 590 | 590 | */ |
| 591 | 591 | w = pGraph->mxRail*pGraph->iRailPitch + 28; |
| 592 | - @ <tr><td></td><td> | |
| 592 | + @ <tr class="timelineBottom"><td></td><td> | |
| 593 | 593 | @ <div id="grbtm" style="width:%d(w)px;"></div> |
| 594 | 594 | @ </td><td></td></tr> |
| 595 | 595 | } |
| 596 | 596 | } |
| 597 | 597 | @ </table> |
| 598 | 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><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 |
+40
| --- test/th1.test | ||
| +++ test/th1.test | ||
| @@ -848,5 +848,45 @@ | ||
| 848 | 848 | |
| 849 | 849 | ############################################################################### |
| 850 | 850 | |
| 851 | 851 | fossil test-th-eval "reinitialize 1; globalState configuration" |
| 852 | 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"} | |
| 853 | 893 |
| --- 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 |
+8
| --- www/changes.wiki | ||
| +++ www/changes.wiki | ||
| @@ -1,10 +1,18 @@ | ||
| 1 | 1 | <title>Change Log</title> |
| 2 | 2 | |
| 3 | 3 | <h2>Changes for Version 1.33 (not released yet)</h2> |
| 4 | 4 | * Add [/help?cmd=import|fossil import --svn], for importing a subversion |
| 5 | 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. | |
| 6 | 14 | |
| 7 | 15 | <h2>Changes for Version 1.32 (2015-03-14)</h2> |
| 8 | 16 | * When creating a new repository using [/help?cmd=init|fossil init], ensure |
| 9 | 17 | that the new repository is fully compatible with historical versions of |
| 10 | 18 | Fossil by having a valid manifest as RID 1. |
| 11 | 19 |
| --- 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 @@ | ||
| 5 | 5 | content in Fossil. |
| 6 | 6 | |
| 7 | 7 | Origins |
| 8 | 8 | ------- |
| 9 | 9 | |
| 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. | |
| 11 | 11 | There was a need to test the SQLite library on Symbian phones, but at that |
| 12 | 12 | time all of the test cases for SQLite were written in Tcl and Tcl could not |
| 13 | 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 | |
| 14 | +version of Tcl that would facilitate running the SQLite test scripts on | |
| 15 | 15 | SymbianOS. |
| 16 | 16 | |
| 17 | 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 | |
| 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 | 22 | light-weight and used minimal resources and seemed ideally suited for the |
| 23 | 23 | task. |
| 24 | 24 | |
| 25 | 25 | The name "TH1" stands "Test Harness 1", since that was its original purpose. |
| 26 | 26 | |
| @@ -78,11 +78,11 @@ | ||
| 78 | 78 | just a single command. |
| 79 | 79 | |
| 80 | 80 | Summary of Core TH1 Commands |
| 81 | 81 | ---------------------------- |
| 82 | 82 | |
| 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 | |
| 84 | 84 | repertoire of commands. TH1, as it is designed to be minimalist and |
| 85 | 85 | embedded has a greatly reduced command set. The following bullets |
| 86 | 86 | summarize the commands available in TH1: |
| 87 | 87 | |
| 88 | 88 | * break |
| @@ -90,11 +90,13 @@ | ||
| 90 | 90 | * continue |
| 91 | 91 | * error ?STRING? |
| 92 | 92 | * expr EXPR |
| 93 | 93 | * for INIT-SCRIPT TEST-EXPR NEXT-SCRIPT BODY-SCRIPT |
| 94 | 94 | * if EXPR SCRIPT (elseif EXPR SCRIPT)* ?else SCRIPT? |
| 95 | + * info commands | |
| 95 | 96 | * info exists VARNAME |
| 97 | + * info vars | |
| 96 | 98 | * lindex LIST INDEX |
| 97 | 99 | * list ARG ... |
| 98 | 100 | * llength LIST |
| 99 | 101 | * proc NAME ARG-LIST BODY-SCRIPT |
| 100 | 102 | * rename OLD NEW |
| @@ -109,12 +111,12 @@ | ||
| 109 | 111 | * string repeat STRING COUNT |
| 110 | 112 | * unset VARNAME |
| 111 | 113 | * uplevel ?LEVEL? SCRIPT |
| 112 | 114 | * upvar ?FRAME? OTHERVAR MYVAR ?OTHERVAR MYVAR? |
| 113 | 115 | |
| 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. | |
| 116 | 118 | |
| 117 | 119 | TH1 Extended Commands |
| 118 | 120 | --------------------- |
| 119 | 121 | |
| 120 | 122 | There are many new commands added to TH1 and used to access the special |
| @@ -128,16 +130,16 @@ | ||
| 128 | 130 | * date |
| 129 | 131 | * decorate |
| 130 | 132 | * enable_output |
| 131 | 133 | * getParameter |
| 132 | 134 | * globalState |
| 133 | - * httpize | |
| 134 | 135 | * hascap |
| 135 | 136 | * hasfeature |
| 136 | 137 | * html |
| 137 | 138 | * htmlize |
| 138 | 139 | * http |
| 140 | + * httpize | |
| 139 | 141 | * linecount |
| 140 | 142 | * puts |
| 141 | 143 | * query |
| 142 | 144 | * randhex |
| 143 | 145 | * regexp |
| @@ -147,20 +149,420 @@ | ||
| 147 | 149 | * searchable |
| 148 | 150 | * setParameter |
| 149 | 151 | * setting |
| 150 | 152 | * styleHeader |
| 151 | 153 | * styleFooter |
| 154 | + * tclEval | |
| 155 | + * tclExpr | |
| 156 | + * tclInvoke | |
| 152 | 157 | * tclReady |
| 153 | 158 | * trace |
| 154 | 159 | * stime |
| 155 | 160 | * utime |
| 156 | 161 | * wiki |
| 157 | 162 | |
| 158 | 163 | 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 | +------------- | |
| 160 | 562 | |
| 161 | 563 | **To Do:** We would like to have a community volunteer go through and |
| 162 | 564 | copy the documentation for each of these commands (with appropriate |
| 163 | 565 | format changes and spelling and grammar corrections) into subsequent |
| 164 | 566 | sections of this document. It is suggested that the list of extension |
| 165 | 567 | commands be left intact - as a quick reference. But it would be really |
| 166 | 568 | nice to also have the details of what each command does. |
| 167 | 569 |
| --- 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 |