]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
wasm: added utility C code to generate a JSON-format "enum" of the numerous SQLITE_xy...
authorstephan <stephan@noemail.net>
Sat, 25 Jun 2022 10:30:24 +0000 (10:30 +0000)
committerstephan <stephan@noemail.net>
Sat, 25 Jun 2022 10:30:24 +0000 (10:30 +0000)
FossilOrigin-Name: 778062e3b415dca5104eee398950741b6dbb9d4bdf7c998eef18371a42669946

Makefile.in
ext/fiddle/EXPORTED_FUNCTIONS.sqlite3-api
ext/fiddle/SqliteTestUtil.js
ext/fiddle/sqlite3-api.js
ext/fiddle/sqlite3-worker.js
ext/fiddle/testing1.js
ext/fiddle/wasm_util.c [new file with mode: 0644]
manifest
manifest.uuid

index da75b76a598423539c48aa26cfbe7a35b1e40614..2e0768b829506652e1f172b7351801f9cb666c9b 100644 (file)
@@ -1543,16 +1543,16 @@ $(fiddle_module_js): Makefile sqlite3.c shell.c \
         sqlite3.c shell.c
        gzip < $@ > $@.gz
        gzip < $(fiddle_dir)/fiddle-module.wasm > $(fiddle_dir)/fiddle-module.wasm.gz
-$(sqlite3_wasm_js): Makefile sqlite3.c \
+$(sqlite3_wasm_js): Makefile sqlite3.c $(fiddle_dir)/wasm_util.c \
     $(fiddle_dir)/sqlite3-api.js \
     $(fiddle_dir)/EXPORTED_RUNTIME_METHODS \
     $(fiddle_dir)/EXPORTED_FUNCTIONS.sqlite3-api
        emcc -o $@ $(emcc_flags) \
-        -sEXPORT_NAME=initSqlite3Module \
+        -sEXPORT_NAME=sqlite3InitModule \
         -sEXPORTED_FUNCTIONS=@$(fiddle_dir_abs)/EXPORTED_FUNCTIONS.sqlite3-api \
         --post-js=$(fiddle_dir)/sqlite3-api.js \
         --no-entry \
-        sqlite3.c
+        sqlite3.c $(fiddle_dir)/wasm_util.c
        gzip < $@ > $@.gz
        gzip < $(sqlite3_wasm) > $(sqlite3_wasm).gz
        gzip < $(fiddle_dir)/sqlite3-api.js > $(fiddle_dir)/sqlite3-api.js.gz
index 3127b294d93124b4ed514bb4e63f3c3861ee559b..59dfef45b603d67337602a3f4b5a15772c0befcc 100644 (file)
@@ -48,4 +48,5 @@ _sqlite3_value_bytes
 _sqlite3_value_double
 _sqlite3_value_text
 _sqlite3_value_type
+_sqlite3_wasm_enum_json
 _free
index cf78946dc720f5558275622c1165efc309717765..bcbdc59c51149462601cd8795b2edff4d54dd87a 100644 (file)
@@ -90,7 +90,7 @@
     
     /**
        This is a module object for use with the emscripten-installed
-       initSqlite3Module() factory function.
+       sqlite3InitModule() factory function.
     */
     self.sqlite3TestModule = {
         postRun: [
index 450bbb62ca283ca1b066b882b5e09874f6273060..d4a5993ba574940ad9dd60f84a3f16c44bd8b45a 100644 (file)
   This file is intended to be appended to the emcc-generated
   sqlite3.js via emcc:
 
-  emcc ... -sMODULARIZE -sEXPORT_NAME=initSqlite3Module --post-js=THIS_FILE
+  emcc ... -sMODULARIZE -sEXPORT_NAME=sqlite3InitModule --post-js=THIS_FILE
 
   It is loaded by importing the emcc-generated sqlite3.js, then:
 
-  initSqlite3Module({module object}).then(
+  sqlite3InitModule({module object}).then(
     function(theModule){
       theModule.sqlite3 == an object containing this file's
       deliverables:
@@ -29,7 +29,7 @@
 
   It is up to the caller to provide a module object compatible with
   emcc, but it can be a plain empty object. The object passed to
-  initSqlite3Module() will get populated by the emscripten-generated
+  sqlite3InitModule() will get populated by the emscripten-generated
   bits and, in part, by the code from this file. Specifically, this file
   installs the `theModule.sqlite3` part shown above.
 
@@ -151,49 +151,6 @@ Module.postRun.push(function(namespace/*the module object, the target for
       follows is strongly influenced by the sql.js implementation.
     */
     const api = {
-        /* It is important that the following integer values match
-           those from the C code. Ideally we could fetch them from the
-           C API, e.g., in the form of a JSON object, but getting that
-           JSON string constructed within our current confines is
-           currently not worth the effort.
-
-           Reminder to self: we could probably do so by adding the
-           proverbial level of indirection, calling in to C to get it,
-           and having that C func call an
-           emscripten-installed/JS-implemented library function which
-           builds the result object:
-
-           const obj = {};
-           sqlite3__get_enum(function(key,val){
-               obj[key] = val;
-           });
-
-           but whether or not we can pass a function that way, via a
-           (void*) is as yet unknown.
-        */
-        /* Minimum subset of sqlite result codes we'll need. */
-        SQLITE_OK: 0,
-        SQLITE_ROW: 100,
-        SQLITE_DONE: 101,
-        /* sqlite data types */
-        SQLITE_INTEGER: 1,
-        SQLITE_FLOAT: 2,
-        SQLITE_TEXT: 3,
-        SQLITE_BLOB: 4,
-        SQLITE_NULL: 5,
-        /* create_function() flags */
-        SQLITE_DETERMINISTIC: 0x000000800,
-        SQLITE_DIRECTONLY: 0x000080000,
-        SQLITE_INNOCUOUS: 0x000200000,
-        /* sqlite encodings, used for creating UDFs, noting that we
-           will only support UTF8. */
-        SQLITE_UTF8: 1,
-        /* Values for the final argument of sqlite3_result_blob(),
-           noting that these are interpreted in WASM as pointer
-           values. */
-        SQLITE_TRANSIENT: -1,
-        SQLITE_STATIC: 0,
-
         /**
            Holds state which are specific to the WASM-related
            infrastructure and glue code. It is not expected that client
@@ -343,7 +300,18 @@ Module.postRun.push(function(namespace/*the module object, the target for
                                    "number", "number"]),
     };
 
-    const uint8ToString = (str)=>new TextDecoder('utf-8').decode(str);
+    /* Import C-level constants... */
+    //console.log("wasmEnum=",SQM.ccall('sqlite3_wasm_enum_json', 'string', []));
+    const wasmEnum = JSON.parse(SQM.ccall('sqlite3_wasm_enum_json', 'string', []));
+    ['resultCodes','dataTypes','udfFlags',
+     'encodings','blobFinalizers'].forEach(function(t){
+        Object.keys(wasmEnum[t]).forEach(function(k){
+            api[k] = wasmEnum[t][k];
+        });
+    });
+
+    const utf8Decoder = new TextDecoder('utf-8');
+    const typedArrayToString = (str)=>utf8Decoder.decode(str);
     //const stringToUint8 = (sql)=>new TextEncoder('utf-8').encode(sql);
 
     /**
@@ -393,7 +361,7 @@ Module.postRun.push(function(namespace/*the module object, the target for
        parameters) requires using api.wasm.getValue().
     */
     api.sqlite3_prepare_v2 = function(pDb, sql, sqlLen, ppStmt, pzTail){
-        if(sql instanceof Uint8Array) sql = uint8ToString(sql);
+        if(isSupportedTypedArray(sql)) sql = typedArrayToString(sql);
         switch(typeof sql){
             case 'string': return prepareMethods.basic(pDb, sql, -1, ppStmt, null);
             case 'number': return prepareMethods.full(pDb, sql, -1, ppStmt, pzTail);
@@ -556,7 +524,7 @@ Module.postRun.push(function(namespace/*the module object, the target for
             case 1:
                 if('string'===typeof args[0]){
                     out.sql = args[0];
-                }else if(args[0] instanceof Uint8Array){
+                }else if(isSupportedTypedArray(args[0])){
                     out.sql = args[0];
                 }else if(args[0] && 'object'===typeof args[0]){
                     out.opt = args[0];
@@ -569,8 +537,8 @@ Module.postRun.push(function(namespace/*the module object, the target for
             break;
             default: toss("Invalid argument count for exec().");
         };
-        if(out.sql instanceof Uint8Array){
-            out.sql = uint8ToString(out.sql);
+        if(isSupportedTypedArray(out.sql)){
+            out.sql = typedArrayToString(out.sql);
         }else if(Array.isArray(out.sql)){
             out.sql = out.sql.join('');
         }else if('string'!==typeof out.sql){
@@ -829,8 +797,8 @@ Module.postRun.push(function(namespace/*the module object, the target for
                 (opt.callback && opt.rowMode)
                     ? opt.rowMode : false);
             try{
-                const sql = (arg.sql instanceof Uint8Array)
-                      ? uint8ToString(arg.sql)
+                const sql = isSupportedTypedArray(arg.sql)
+                      ? typedArrayToString(arg.sql)
                       : arg.sql;
                 let pSql = api.wasm.allocateUTF8OnStack(sql)
                 const ppStmt  = api.wasm.stackAlloc(8) /* output (sqlite3_stmt**) arg */;
@@ -1638,7 +1606,9 @@ Module.postRun.push(function(namespace/*the module object, the target for
 
            If passed no arguments then it returns an object mapping
            all known compilation options to their compile-time values,
-           or boolean true if they are defined with no value.
+           or boolean true if they are defined with no value. This
+           result, which is relatively expensive to compute, is cached
+           and returned for future no-argument calls.
 
            In all other cases it returns true if the given option was
            active when when compiling the sqlite3 module, else false.
@@ -1649,7 +1619,8 @@ Module.postRun.push(function(namespace/*the module object, the target for
         */
         compileOptionUsed: function f(optName){
             if(!arguments.length){
-                if(!f._opt){
+                if(f._result) return f._result;
+                else if(!f._opt){
                     f._rx = /^([^=]+)=(.+)/;
                     f._rxInt = /^-?\d+$/;
                     f._opt = function(opt, rv){
@@ -1664,16 +1635,14 @@ Module.postRun.push(function(namespace/*the module object, the target for
                     f._opt(k,ov);
                     rc[ov[0]] = ov[1];
                 }
-                return rc;
-            }
-            else if(Array.isArray(optName)){
+                return f._result = rc;
+            }else if(Array.isArray(optName)){
                 const rc = {};
                 optName.forEach((v)=>{
                     rc[v] = api.sqlite3_compileoption_used(v);
                 });
                 return rc;
-            }
-            else if('object' === typeof optName){
+            }else if('object' === typeof optName){
                 Object.keys(optName).forEach((k)=> {
                     optName[k] = api.sqlite3_compileoption_used(k);
                 });
index fe7423f4c4aceb9199ce36f3becd1d5c4873db53..ed369ad35b6be81685bfc70714c0ccc075a16d8e 100644 (file)
@@ -20,7 +20,7 @@
   loading sqlite3.js via a Worker. Loading sqlite3.js from the main
   window thread elides the Worker-specific API. Instantiating a worker
   with new Worker("sqlite.js") will not (cannot) call
-  initSqlite3Module() to initialize the module due to a
+  sqlite3InitModule() to initialize the module due to a
   timing/order-of-operations conflict (and that symbol is not exported
   in a way that a Worker loading it that way can see it).  Thus JS
   code wanting to load the sqlite3 Worker-specific API needs to pass
@@ -39,6 +39,6 @@
 */
 "use strict";
 importScripts('sqlite3.js');
-initSqlite3Module().then(function(){
+sqlite3InitModule().then(function(){
     setTimeout(()=>self.postMessage({type:'sqlite3-api',data:'ready'}), 0);
 });
index 9c17115f38d438a26893d374c887b59c1352873f..44e285f73a1833ea6d58deba1b40ef099430a864 100644 (file)
                     api.sqlite3_sourceid());
         log("Build options:",oo.compileOptionUsed());
         log("api.wasm.HEAP8 size =",api.wasm.HEAP8.length);
+        log("wasmEnum",JSON.parse(Module.ccall('sqlite3_wasm_enum_json', 'string', [])));
+        [ /* Spot-check a handful of constants to make sure they got installed... */
+            'SQLITE_SCHEMA','SQLITE_NULL','SQLITE_UTF8',
+            'SQLITE_STATIC', 'SQLITE_DIRECTONLY'
+        ].forEach(function(k){
+            T.assert('number' === typeof api[k]);
+        });
         const db = new oo.DB();
         try {
             log("DB:",db.filename);
             db.close();
         }
         log("Total Test count:",T.counter);
-        log("api.wasm.HEAP8 size =",api.wasm.HEAP8.length);
     };
 
-    initSqlite3Module(self.sqlite3TestModule).then(function(theModule){
-        /** Use a timeout so that we are (hopefully) out from
-            under the module init stack when our setup gets
-            run. Just on principle, not because we _need_ to
-            be. */
+    sqlite3InitModule(self.sqlite3TestModule).then(function(theModule){
+        /** Use a timeout so that we are (hopefully) out from under
+            the module init stack when our setup gets run. Just on
+            principle, not because we _need_ to be. */
         //console.debug("theModule =",theModule);
         setTimeout(()=>runTests(theModule), 0);
     });
diff --git a/ext/fiddle/wasm_util.c b/ext/fiddle/wasm_util.c
new file mode 100644 (file)
index 0000000..54326b2
--- /dev/null
@@ -0,0 +1,108 @@
+#include "sqlite3.h"
+#include <stdlib.h> /*atexit()*/
+/*
+**  2022-06-25
+**
+**  The author disclaims copyright to this source code.  In place of a
+**  legal notice, here is a blessing:
+**
+**  *   May you do good and not evil.
+**  *   May you find forgiveness for yourself and forgive others.
+**  *   May you share freely, never taking more than you give.
+**
+***********************************************************************
+**
+** Utility functions for use with the emscripten/WASM bits.  These
+** functions ARE NOT part of the sqlite3 public API. They are strictly
+** for internal use by the JS/WASM bindings.
+*/
+
+/** Result value of sqlite3_wasm_enum_json(). */
+static char * zWasmEnum = 0;
+/* atexit() handler to clean up any WASM-related state. */
+static void sqlite3_wasm_cleanup(void){
+  free(zWasmEnum);
+}
+
+/*
+** Returns a string containing a JSON-format "enum" of C-level
+** constants intended to be imported into the JS environment. The JSON
+** is initialized the first time this function is called and that
+** result is reused for all future calls and cleaned up via atexit().
+** (If we didn't cache the result, it would be leaked by the JS glue
+** code on each call during the WASM-to-JS conversion.)
+**
+** This function is NOT part of the sqlite3 public API. It is strictly
+** for use by the JS/WASM bindings.
+*/
+const char * sqlite3_wasm_enum_json(void){
+  sqlite3_str * s;
+  if(zWasmEnum) return zWasmEnum;
+  s = sqlite3_str_new(0);
+  sqlite3_str_appendall(s, "{");
+
+#define SD_(X,S,FINAL)                                                  \
+  sqlite3_str_appendf(s, "\"%s\": %d%s", S, (int)X, (FINAL ? "}" : ", "))
+#define SD(X) SD_(X,#X,0)
+#define SDFinal(X) SD_(X,#X,1)
+
+  sqlite3_str_appendall(s,"\"resultCodes\": {");
+  SD(SQLITE_OK);
+  SD(SQLITE_ERROR);
+  SD(SQLITE_INTERNAL);
+  SD(SQLITE_PERM);
+  SD(SQLITE_ABORT);
+  SD(SQLITE_BUSY);
+  SD(SQLITE_LOCKED);
+  SD(SQLITE_NOMEM);
+  SD(SQLITE_READONLY);
+  SD(SQLITE_INTERRUPT);
+  SD(SQLITE_IOERR);
+  SD(SQLITE_CORRUPT);
+  SD(SQLITE_NOTFOUND);
+  SD(SQLITE_FULL);
+  SD(SQLITE_CANTOPEN);
+  SD(SQLITE_PROTOCOL);
+  SD(SQLITE_EMPTY);
+  SD(SQLITE_SCHEMA);
+  SD(SQLITE_TOOBIG);
+  SD(SQLITE_CONSTRAINT);
+  SD(SQLITE_MISMATCH);
+  SD(SQLITE_MISUSE);
+  SD(SQLITE_NOLFS);
+  SD(SQLITE_AUTH);
+  SD(SQLITE_FORMAT);
+  SD(SQLITE_RANGE);
+  SD(SQLITE_NOTADB);
+  SD(SQLITE_NOTICE);
+  SD(SQLITE_WARNING);
+  SD(SQLITE_ROW);
+  SDFinal(SQLITE_DONE);
+
+  sqlite3_str_appendall(s,",\"dataTypes\": {");
+  SD(SQLITE_INTEGER);
+  SD(SQLITE_FLOAT);
+  SD(SQLITE_TEXT);
+  SD(SQLITE_BLOB);
+  SDFinal(SQLITE_NULL);
+
+  sqlite3_str_appendf(s,",\"encodings\": {");
+  SDFinal(SQLITE_UTF8);
+
+  sqlite3_str_appendall(s,",\"blobFinalizers\": {");
+  SD(SQLITE_STATIC);
+  SDFinal(SQLITE_TRANSIENT);
+
+  sqlite3_str_appendall(s,",\"udfFlags\": {");
+  SD(SQLITE_DETERMINISTIC);
+  SD(SQLITE_DIRECTONLY);
+  SDFinal(SQLITE_INNOCUOUS);
+
+#undef SD_
+#undef SD
+#undef SDFinal
+  sqlite3_str_appendall(s, "}");
+  zWasmEnum = sqlite3_str_finish(s);
+  atexit(sqlite3_wasm_cleanup);
+  return zWasmEnum;
+}
index 58086c0033a1eca00fff247c388fc19e7de1e3fc..3697a203f137ab98acfef5d955792dace9dbd185 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,9 +1,9 @@
-C wasm:\seliminated\sthe\sneed\sfor\sStmt\sobjects\sto\skeep\sahold\sof\smemory\sallocated\sfor\sbound\sstrings\sand\sblobs.\sAdded\salternate\sstring/blob\sbind\simpls\swhich\sare\shypothetically\smore\sefficient\sbut\snot\syet\sproven\sto\sbe\sso.
-D 2022-06-25T07:42:24.832
+C wasm:\sadded\sutility\sC\scode\sto\sgenerate\sa\sJSON-format\s"enum"\sof\sthe\snumerous\sSQLITE_xyz\sconstants\sso\sthat\swe\sdo\snot\srisk\sthose\sgetting\sout\sof\ssync\sin\sthe\sJS\scode.\sRenamed\sinitSqlite3Module\sto\ssqlite3InitModule.\sCleanups\sin\sthe\sTypedArray\shandling.
+D 2022-06-25T10:30:24.409
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
-F Makefile.in bccb0ed3f05fc41aee15da77c844c48b5da419cbb9af35b8a147536c9ad1c822
+F Makefile.in b3ccd1a79e6364d49c465b38cec5eccdc74dfdc06501be62ef8eb01dc1f93f43
 F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
 F Makefile.msc de7cb3e095ce2fdc33513ccd76ebdaeda1483d0ddab0410fe65cbdeadd4c0ee1
 F README.md 8b8df9ca852aeac4864eb1e400002633ee6db84065bd01b78c33817f97d31f5e
@@ -56,22 +56,23 @@ F ext/expert/sqlite3expert.c 6ca30d73b9ed75bd56d6e0d7f2c962d2affaa72c505458619d0
 F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b
 F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72
 F ext/fiddle/EXPORTED_FUNCTIONS.fiddle 7fb73f7150ab79d83bb45a67d257553c905c78cd3d693101699243f36c5ae6c3
-F ext/fiddle/EXPORTED_FUNCTIONS.sqlite3-api 540b9dec63a3a62a256e2f030827848a92e9b9d9b6fa5c0188295a4a1c5382cd
+F ext/fiddle/EXPORTED_FUNCTIONS.sqlite3-api 2ef8a8d58815a96de196d085b8aaf126400b8d13a5b7f724f86dfe9f61d0600d
 F ext/fiddle/EXPORTED_RUNTIME_METHODS a004bd5eeeda6d3b28d16779b7f1a80305bfe009dfc7f0721b042967f0d39d02
 F ext/fiddle/Makefile e25d34a0e1324f771d64c09c592601b97219282011587e6ce410fa8acdedb913
-F ext/fiddle/SqliteTestUtil.js 559731c3e8e0de330ec7d292e6c1846566408caee6637acc8a119ac338a8781c
+F ext/fiddle/SqliteTestUtil.js 2e87d424b12674476bdf8139934dcacc3ff8a7a5f5ff4392ba5e5a8d8cee9fbd
 F ext/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
 F ext/fiddle/fiddle-worker.js 88bc2193a6cb6a3f04d8911bed50a4401fe6f277de7a71ba833865ab64a1b4ae
 F ext/fiddle/fiddle.html 550c5aafce40bd218de9bf26192749f69f9b10bc379423ecd2e162bcef885c08
 F ext/fiddle/fiddle.js 812f9954cc7c4b191884ad171f36fcf2d0112d0a7ecfdf6087896833a0c079a8
 F ext/fiddle/index.md d9c1c308d8074341bc3b11d1d39073cd77754cb3ca9aeb949f23fdd8323d81cf
-F ext/fiddle/sqlite3-api.js 664a454d82694c6cfab36b8ad9e36620cfc44fa37e05642ba87109c37409f51f
-F ext/fiddle/sqlite3-worker.js a9c2b614beca187dbdd8c053ec2770cc61ec1ac9c0ec6398ceb49a79f705a421
+F ext/fiddle/sqlite3-api.js 03ac065f4bc68eefd3b09cf3957a58891cbfcebe2a5ffe1c8a10f16a58dfc70b
+F ext/fiddle/sqlite3-worker.js 50b7a9ce14c8fae0af965e35605fe12cafb79c1e01e99216d8110d8b02fbf4b5
 F ext/fiddle/testing.css 750572dded671d2cf142bbcb27af5542522ac08db128245d0b9fe410aa1d7f2a
 F ext/fiddle/testing1.html ea1f3be727f78e420007f823912c1a03b337ecbb8e79449abc2244ad4fe15d9a
-F ext/fiddle/testing1.js 5c04721d205b3d909ec6896682743051cb5e5202e9151a058e90600a42f48f48
+F ext/fiddle/testing1.js f9615ff58b9de6879e4836618b34322085510ec44c6754e725a92a097c908a6f
 F ext/fiddle/testing2.html 9063b2430ade2fe9da4e711addd1b51a2741cf0c7ebf6926472a5e5dd63c0bc4
 F ext/fiddle/testing2.js 7b45b4e7fddbd51dbaf89b6722c02758051b34bac5a98c11b569a7e7572f88ee
+F ext/fiddle/wasm_util.c b63e00c2f264ab4a9c45c9f9727627cbc4d8aa2f93c5dd09e8105d63ff7e0872
 F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
 F ext/fts1/ft_hash.c 3927bd880e65329bdc6f506555b228b28924921b
 F ext/fts1/ft_hash.h 06df7bba40dadd19597aa400a875dbc2fed705ea
@@ -1978,8 +1979,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 140618b212e3aa9ff2df20f22af846a1c4c5ffaeefd84330446f61362b39a8f1
-R ecfc68999ba200e5f9d0ce8c6a78fe70
+P da1d3151a440567f34a2f6c0b2bfc2e9fab81c256cc361c9ce7b46f2c23a2aa8
+R ff53072845ce3be319c8a5687950f355
 U stephan
-Z ec8563cad502dab169a1c4538eaf6ec1
+Z 0ce9f393ac2f284b021257ae10338830
 # Remove this line to create a well-formed Fossil manifest.
index 63c94d8ff4f7e165456de6228925dbf28e43371b..7a1e3598fa4e82a4e13851f42bd7b2cf68274f02 100644 (file)
@@ -1 +1 @@
-da1d3151a440567f34a2f6c0b2bfc2e9fab81c256cc361c9ce7b46f2c23a2aa8
\ No newline at end of file
+778062e3b415dca5104eee398950741b6dbb9d4bdf7c998eef18371a42669946
\ No newline at end of file