]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
More work on the JS end-user deliverables. Add tool/stripccomments.c to support that.
authorstephan <stephan@noemail.net>
Tue, 18 Oct 2022 20:36:50 +0000 (20:36 +0000)
committerstephan <stephan@noemail.net>
Tue, 18 Oct 2022 20:36:50 +0000 (20:36 +0000)
FossilOrigin-Name: 2156f0744acfe425457430a0f6a7e02de907de85edba81a6d4eef40293e561c8

ext/wasm/GNUmakefile
ext/wasm/README-dist.txt
ext/wasm/dist.make
manifest
manifest.uuid
tool/stripccomments.c [new file with mode: 0644]

index a683a914161f16b728b6f93be28bf15b488e020c..881eabfac9fabea712c8dff6f45bfc0bc2e31424 100644 (file)
@@ -1,11 +1,29 @@
 ########################################################################
 # This GNU makefile drives the build of the sqlite3 WASM
 # components. It is not part of the canonical build process.
+#
+# This build assumes a Linux platform and is not intended for
+# client-level use. It is for the sqlite project's own development of
+# the JS/WASM components.
+#
+# Primary targets:
+#
+#  default, all = build in dev mode
+#
+#  o0, o1, o2, o3, os, oz = full clean/rebuild with the -Ox level indicated
+#      by the target name. Rebuild is necessary for all components to get
+#      the desired optimization level.
+#
+#  dist = create end user deliverables. Add dist-opt=oX to build with a
+#      specific optimization level, where oX is one of the above-listed
+#      o? target names.
+#
+#  clean = clean up
 ########################################################################
 SHELL := $(shell which bash 2>/dev/null)
 MAKEFILE := $(lastword $(MAKEFILE_LIST))
-all:
-release: all
+default: all
+release: default
 
 # Emscripten SDK home dir and related binaries...
 EMSDK_HOME ?= $(word 1,$(wildcard $(HOME)/src/emsdk $(HOME)/emsdk))
@@ -46,7 +64,9 @@ dir.api := api
 dir.jacc := jaccwabyt
 dir.common := common
 dir.fiddle := fiddle
+dir.tool := $(dir.top)/tool
 CLEAN_FILES := *~ $(dir.jacc)/*~ $(dir.api)/*~ $(dir.common)/*~
+DISTCLEAN_FILES := ./-dummy
 emcc_enable_bigint ?= 1
 sqlite3.c := $(dir.top)/sqlite3.c
 sqlite3.h := $(dir.top)/sqlite3.h
@@ -113,8 +133,11 @@ emcc_opt_full := $(emcc_opt) -g3
 $(sqlite3.c) $(sqlite3.h):
        $(MAKE) -C $(dir.top) sqlite3.c
 
+.PHONY: clean distclean
 clean:
        -rm -f $(CLEAN_FILES)
+distclean: clean
+       -rm -f $(DISTCLEAN_FILES)
 
 ifeq (release,$(filter release,$(MAKECMDGOALS)))
   ifeq (,$(wasm-strip))
@@ -128,7 +151,12 @@ endif
 version-info := $(dir.wasm)/version-info
 $(version-info): $(dir.wasm)/version-info.c $(sqlite3.h) $(MAKEFILE)
        $(CC) -O0 -I$(dir.top) -o $@ $<
-CLEAN_FILES := $(version-info)
+DISTCLEAN_FILES += $(version-info)
+
+stripccomments := $(dir.tool)/stripccomments
+$(stripccomments): $(stripccomments).c $(MAKEFILE)
+       $(CC) -o $@ $<
+DISTCLEAN_FILES += $(stripccomments)
 
 EXPORTED_FUNCTIONS.api.in := $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-api
 
@@ -480,11 +508,7 @@ push-fiddle: $(fiddle_files)
 # painful.
 
 .PHONY: o0 o1 o2 o3 os oz
-o-xtra := -g3
-# ^^^ -g3 is important to keep higher -O levels from mangling (via
-# minification), or outright removing, otherwise working code.
-
-o-xtra += -flto
+o-xtra := -flto
 # ^^^^ -flto can have a considerably performance boost at -O0 but
 # doubles the build time and seems to have negligible effect on
 # higher optimization levels.
@@ -515,7 +539,9 @@ PLATFORMS_WITH_NO_WASMFS := aarch64 # add any others here
 THIS_ARCH := $(shell /usr/bin/uname -m)
 ifneq (,$(filter $(THIS_ARCH),$(PLATFORMS_WITH_NO_WASMFS)))
 $(info This platform does not support the WASMFS build.)
+HAVE_WASMFS := 0
 else
+HAVE_WASMFS := 1
 include wasmfs.make
 endif
 
index ecb906acdc74fd0f2b98caa21c6d604915b0864c..bbc82a1df891550650b02b141933d1f14b137ad7 100644 (file)
@@ -15,10 +15,10 @@ This archive contains two related deliverables:
   but is less portable than the main build, so is provided
   as a separate binary.
 
-Both directories contain small demonstration apps. Browsers will not
-server WASM files from file:// URLs, so the demonstrations require a
-web server and that server must include the following headers in its
-response when serving the files:
+Both directories contain small demonstration and test apps. Browsers
+will not serve WASM files from file:// URLs, so the demo/test apps
+require a web server and that server must include the following
+headers in its response when serving the files:
 
     Cross-Origin-Opener-Policy: same-origin
     Cross-Origin-Embedder-Policy: require-corp
index 84abe393a29acf1372f3b6f1adf86cc90d537e7c..cb13b0bd9291ce10ddb1a7f9018b26209afe4db9 100644 (file)
@@ -9,51 +9,87 @@
 #######################################################################
 MAKEFILE.dist := $(lastword $(MAKEFILE_LIST))
 
+ifeq (0,$(HAVE_WASMFS))
+$(error The 'dist' target needs to be run on a WASMFS-capable platform.)
+endif
 
 ########################################################################
 # Chicken/egg situation: we need $(version-info) to get the version
-# info for the archive name, but that binary may not yet be built, so
-# we have to use a temporary name for the archive.
+# info for the archive name, but that binary may not yet be built, and
+# won't be built until we expand the dependencies. We have to use a
+# temporary name for the archive.
 dist-name = sqlite-wasm-TEMP
 dist-archive = $(dist-name).zip
-
+.PHONY: $(dist-archive)
+CLEAN_FILES += $(wildcard sqlite-wasm-*.zip)
 #ifeq (0,1)
 #  $(info WARNING  *******************************************************************)
 #  $(info ** Be sure to create the desired build configuration before creating the)
 #  $(info ** distribution archive. Use one of the following targets to do so:)
+#  $(info **)
 #  $(info **   o2: builds with -O2, resulting in the fastest builds)
 #  $(info **   oz: builds with -Oz, resulting in the smallest builds)
 #  $(info /WARNING *******************************************************************)
 #endif
 
+########################################################################
+# dist-opt must be the name of a target which triggers the
+# build of the files to be packed into the dist archive.  The
+# intention is that it be one of (o0, o1, o2, o3, os, oz), each of
+# which uses like-named -Ox optimization level flags. The o2 target
+# provides the best overall runtime speeds. The oz target provides
+# slightly slower speeds (roughly 10%) with significantly smaller WASM
+# file sizes. Note that -O2 (the o2 target) results in faster binaries
+# than both -O3 and -Os (the o3 and os targets) in all tests run to
+# date.
+dist-opt ?= oz
+
 demo-123.html := $(dir.wasm)/demo-123.html
 demo-123-worker.html := $(dir.wasm)/demo-123-worker.html
 demo-123.js := $(dir.wasm)/demo-123.js
-demo-files := $(demo-123.js) $(demo-123.html) $(demo-123-worker.html)
+demo-files := $(demo-123.js) $(demo-123.html) $(demo-123-worker.html) \
+              tester1.html tester1.js tester1-worker.html
 README-dist := $(dir.wasm)/README-dist.txt
-$(dist-archive): $(sqlite3.wasm) $(sqlite3.js) $(sqlite3-wasmfs.wasm) $(sqlite3-wasmfs.js)
-#$(dist-archive): $(sqlite3.h) $(sqlite3.c) $(sqlite3-wasm.c)
-$(dist-archive): $(MAKEFILE.dist) $(version-info) $(demo-files) $(README-dist)
-$(dist-archive): oz
-       rm -fr $(dist-name)
-       mkdir -p $(dist-name)/main $(dist-name)/wasmfs
-       cp -p $(README-dist) $(dist-name)/README.txt
-       cp -p $(sqlite3.wasm) $(sqlite3.js) $(dist-name)/main
-       cp -p $(demo-files) $(dist-name)/main
-       cp -p $(sqlite3-wasmfs.wasm) $(sqlite3-wasmfs.js) $(dist-name)/wasmfs
-       for i in $(demo-123.js) $(demo-123.html); do \
+dist-dir-main := $(dist-name)/main
+dist-dir-wasmfs := $(dist-name)/wasmfs
+########################################################################
+# $(dist-archive): create the end-user deliverable archive.
+#
+# Maintenance reminder: because $(dist-archive) depends on
+# $(dist-opt), and $(dist-opt) will depend on clean, having any deps
+# on $(dist-archive) which themselves may be cleaned up by the clean
+# target will lead to grief in parallel builds (-j #). Thus
+# $(dist-target)'s deps must be trimmed to non-generated files or
+# files which are _not_ cleaned up by the clean target.
+$(dist-archive): \
+    $(stripccomments) $(version-info) \
+    $(dist-opt) \
+    $(MAKEFILE) $(MAKEFILE.dist)
+       @echo "Making end-user deliverables..."
+       @rm -fr $(dist-name)
+       @mkdir -p $(dist-dir-main) $(dist-dir-wasmfs)
+       @cp -p $(README-dist) $(dist-name)/README.txt
+       @cp -p $(sqlite3.wasm) $(dist-dir-main)
+       @$(stripccomments) -k -k < $(sqlite3.js) \
+               > $(dist-dir-main)/$(notdir $(sqlite3.js))
+       @cp -p $(demo-files) $(dist-dir-main)
+       @cp -p $(sqlite3-wasmfs.wasm) sqlite3-wasmfs.worker.js $(dist-dir-wasmfs)
+       @$(stripccomments) -k -k < $(sqlite3-wasmfs.js) \
+               > $(dist-dir-wasmfs)/$(notdir $(sqlite3-wasmfs.js))
+       @for i in $(demo-123.js) $(demo-123.html); do \
     sed -e 's/\bsqlite3\.js\b/sqlite3-wasmfs.js/' $$i \
-      > $(dist-name)/wasmfs/$${i##*/} || exit; \
+      > $(dist-dir-wasmfs)/$${i##*/} || exit; \
   done
-       vnum=$$($(version-info) --version-number); \
+       @vnum=$$($(version-info) --version-number); \
        vdir=sqlite-wasm-$$vnum; \
        arc=$$vdir.zip; \
+       echo "Making $$arc ..."; \
        rm -f $$arc; \
        mv $(dist-name) $$vdir; \
        zip -qr $$arc $$vdir; \
        rm -fr $$vdir; \
        ls -la $$arc; \
-       unzip -l $$arc
+       unzip -lv $$arc || echo "Missing unzip app? Not fatal."
 
 #$(shell $(version-info) --version-number)
 dist: $(dist-archive)
index cb6da43b7283d65d80a189693535ba864e72a00d..40f33190d9c8e926b8c58eebb218b90ffe8b6d16 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\snew\stest\sfile\swindowE.test,\sto\stest\sthe\swindow\sfunctions\smodules\sresponse\sto\san\sinconsistent\scollation\ssequence.
-D 2022-10-18T15:02:08.725
+C More\swork\son\sthe\sJS\send-user\sdeliverables.\sAdd\stool/stripccomments.c\sto\ssupport\sthat.
+D 2022-10-18T20:36:50.562
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -473,8 +473,8 @@ F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
 F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
 F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
 F ext/wasm/EXPORTED_RUNTIME_METHODS.fiddle 0e88c8cfc3719e4b7e74980d9da664c709e68acf863e48386cda376edfd3bfb0
-F ext/wasm/GNUmakefile 2fd83d7183bce3f9236fdd2dbe20a4ea37b1d7b26e1a422054ec63008319f065
-F ext/wasm/README-dist.txt bc1fb4f90a28ad2ed0e555a637f393b9249d8d928ac509dad6293b7cae628ea4
+F ext/wasm/GNUmakefile 279fd4589ba602e24d8e66ca795ec5a2275a0e329405e4e984e8ea0579339bae
+F ext/wasm/README-dist.txt 170be2d47b4b52504ef09088ca2f143aab657de0f9ac04d3a68e366f40929c3d
 F ext/wasm/README.md 1e5b28158b74ab3ffc9d54fcbc020f0bbeb82c2ff8bbd904214c86c70e8a3066
 F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 89983a8d122c35a90c65ec667844b95a78bcd04f3198a99c1e0c8368c1a0b03a
 F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
@@ -504,7 +504,7 @@ F ext/wasm/demo-123.html 7c239c9951d1b113f9f532969ac039294cf1dcfee2b3ae0a2c1ed2b
 F ext/wasm/demo-123.js e0cbeb3495e14103763d5c49794a24d67cf3d78e0ed5b82843be70c0c2ee4b3b
 F ext/wasm/demo-kvvfs1.html 7d4f28873de67f51ac18c584b7d920825139866a96049a49c424d6f5a0ea5e7f
 F ext/wasm/demo-kvvfs1.js 105596bd2ccd0b1deb5fde8e99b536e8242d4bb5932fac0c8403ff3a6bc547e8
-F ext/wasm/dist.make d7076e90f04396f1cc54cb41ee106451496179c10d54bbdebb65ae7b1ae12211
+F ext/wasm/dist.make 1d59fafdfcf6fc5ee0f3351b21199585dba21afcf0518241789fd5d37a1c011d
 F ext/wasm/fiddle.make b609dfde299b4523d7123b7e0cecaa1a0aff0dd984e62cea653aae91f5063c90
 F ext/wasm/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
 F ext/wasm/fiddle/fiddle-worker.js 531859a471924a0ea48afa218e6877f0c164ca324d51e15843ed6ecc1c65c7ee
@@ -2007,6 +2007,7 @@ F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaa
 F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
 F tool/srcck1.c 371de5363b70154012955544f86fdee8f6e5326f
 F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
+F tool/stripccomments.c 20b8aabc4694d0d4af5566e42da1f1a03aff057689370326e9269a9ddcffdc37
 F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
 F tool/symbols.sh 1612bd947750e21e7b47befad5f6b3825b06cce0705441f903bf35ced65ae9b9
 F tool/varint.c 5d94cb5003db9dbbcbcc5df08d66f16071aee003
@@ -2036,8 +2037,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 904b54625d985e742888e06ba792cab316b9ec9d6669d9cf509bac48030373ca
-R 609c010622cb8a1edf242ffa07ea33a0
-U dan
-Z 47ec91d5045ad14459bc2cd80292963b
+P 740a2eb0928d54fdf735a8e573c6a61a34dbd295b46e5b6ef39e957fd2623293
+R f3423b9e5fdd1b3c8749326c161b8bbf
+U stephan
+Z 8ed4b03e8c6243f1d25f4dc2d31715c7
 # Remove this line to create a well-formed Fossil manifest.
index d617a968ca8af3f2b67d2fe529d1d58a1a389d49..965ccd2dac0e40e1a06265dcd3ae386bfaa37019 100644 (file)
@@ -1 +1 @@
-740a2eb0928d54fdf735a8e573c6a61a34dbd295b46e5b6ef39e957fd2623293
\ No newline at end of file
+2156f0744acfe425457430a0f6a7e02de907de85edba81a6d4eef40293e561c8
\ No newline at end of file
diff --git a/tool/stripccomments.c b/tool/stripccomments.c
new file mode 100644 (file)
index 0000000..53933c0
--- /dev/null
@@ -0,0 +1,228 @@
+/**
+   Strips C- and C++-style comments from stdin, sending the results to
+   stdout. It assumes that its input is legal C-like code, and does
+   only little error handling.
+
+   It treats string literals as anything starting and ending with
+   matching double OR single quotes OR backticks (for use with
+   scripting languages which use those). It assumes that a quote
+   character within a string which uses the same quote type is escaped
+   by a backslash. It should not be used on any code which might
+   contain C/C++ comments inside heredocs, and similar constructs, as
+   it will strip those out.
+
+   Usage: $0 [--keep-first|-k] < input > output
+
+   The --keep-first (-k) flag tells it to retain the first comment in the
+   input stream (which is often a license or attribution block). It
+   may be given repeatedly, each one incrementing the number of
+   retained comments by one.
+
+   License: Public Domain
+   Author: Stephan Beal (stephan@wanderinghorse.net)
+*/
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+#if 1
+#define MARKER(pfexp)                                                \
+  do{ printf("MARKER: %s:%d:\t",__FILE__,__LINE__);                  \
+    printf pfexp;                                                    \
+  } while(0)
+#else
+#define MARKER(exp) if(0) printf
+#endif
+
+struct {
+  FILE * input;
+  FILE * output;
+  int rc;
+  int keepFirst;
+} App = {
+  0/*input*/,
+  0/*output*/,
+  0/*rc*/,
+  0/*keepFirst*/
+};
+
+void do_it_all(void){
+  enum states {
+    S_NONE = 0 /* not in comment */,
+    S_SLASH1 = 1 /* slash - possibly comment prefix */,
+    S_CPP = 2 /* in C++ comment */,
+    S_C = 3 /* in C comment */
+  };
+  int ch, prev = EOF;
+  FILE * out = App.output;
+  int const slash = '/';
+  int const star = '*';
+  int line = 1;
+  int col = 0;
+  enum states state = S_NONE /* current state */;
+  int elide = 0 /* true if currently eliding output */;
+  int state3Col = -99
+    /* huge kludge for odd corner case: */
+    /*/ <--- here. state3Col marks the source column in which a C-style
+      comment starts, so that it can tell if star-slash inside a
+      C-style comment is the end of the comment or is the weird corner
+      case marked at the start of _this_ comment block. */;
+  for( ; EOF != (ch = fgetc(App.input)); prev = ch,
+         ++col){
+    switch(state){
+      case S_NONE:
+        if('\''==ch || '"'==ch || '`'==ch){
+          /* Read string literal...
+             needed to properly catch comments in strings. */
+          int const quote = ch,
+            startLine = line, startCol = col;
+          int ch2, escaped = 0, endOfString = 0;
+          fputc(ch, out);
+          for( ++col; !endOfString && EOF != (ch2 = fgetc(App.input));
+               ++col ){
+            switch(ch2){
+              case '\\': escaped = !escaped;
+                break;
+              case '`':
+              case '\'':
+              case '"':
+                if(!escaped && quote == ch2) endOfString = 1;
+                escaped = 0;
+                break;
+              default:
+                escaped = 0;
+                break;
+            }
+            if('\n'==ch2){
+              ++line;
+              col = 0;
+            }
+            fputc(ch2, out);
+          }
+          if(EOF == ch2){
+            fprintf(stderr, "Unexpected EOF while reading %s literal "
+                    "on line %d column %d.\n",
+                    ('\''==ch) ? "char" : "string",
+                    startLine, startCol);
+            App.rc = 1;
+            return;
+          }
+          break;
+        }
+        else if(slash == ch){
+          /* MARKER(("state 0 ==> 1 @ %d:%d\n", line, col)); */
+          state = S_SLASH1;
+          break;
+        }
+        fputc(ch, out);
+        break;
+      case S_SLASH1: /* 1 slash */
+        /* MARKER(("SLASH1 @ %d:%d App.keepFirst=%d\n",
+           line, col, App.keepFirst)); */
+        switch(ch){
+          case '*':
+            /* Enter C comment */
+            if(App.keepFirst>0){
+              elide = 0;
+              --App.keepFirst;
+            }else{
+              elide = 1;
+            }
+            /*MARKER(("state 1 ==> 3 @ %d:%d\n", line, col));*/
+            state = S_C;
+            state3Col = col-1;
+            if(!elide){
+              fputc(prev, out);
+              fputc(ch, out);
+            }
+            break;
+          case '/':
+            /* Enter C++ comment */
+            if(App.keepFirst>0){
+              elide = 0;
+              --App.keepFirst;
+            }else{
+              elide = 1;
+            }
+            /*MARKER(("state 1 ==> 2 @ %d:%d\n", line, col));*/
+            state = S_CPP;
+            if(!elide){
+              fputc(prev, out);
+              fputc(ch, out);
+            }
+            break;
+          default:
+            /* It wasn't a comment after all. */
+            state = S_NONE;
+            if(!elide){
+              fputc(prev, out);
+              fputc(ch, out);
+            }
+        }
+        break;
+      case S_CPP: /* C++ comment */
+        if('\n' == ch){
+          /* MARKER(("state 2 ==> 0 @ %d:%d\n", line, col)); */
+          state = S_NONE;
+          elide = 0;
+        }
+        if(!elide){
+          fputc(ch, out);
+        }
+        break;
+      case S_C: /* C comment */
+        if(!elide){
+          fputc(ch, out);
+        }
+        if(slash == ch){
+          if(star == prev){
+            /* MARKER(("state 3 ==> 0 @ %d:%d\n", line, col)); */
+            /* Corner case which breaks this: */
+            /*/ <-- slash there */
+            /* That shows up twice in a piece of 3rd-party
+               code i use. */
+            /* And thus state3Col was introduced :/ */
+            if(col!=state3Col+2){
+              state = S_NONE;
+              elide = 0;
+              state3Col = -99;
+            }
+          }
+        }
+        break;
+      default:
+        assert(!"impossible!");
+        break;
+    }
+    if('\n' == ch){
+      ++line;
+      col = 0;
+      state3Col = -99;
+    }
+  }
+}
+
+static void usage(char const *zAppName){
+  fprintf(stderr, "Strips C- and C++-style comments from stdin and sends "
+          "the results to stdout.\n");
+  fprintf(stderr, "Usage: %s [--keep-first|-k] < input > output\n", zAppName);
+}
+
+int main( int argc, char const * const * argv ){
+  int i;
+  for(i = 1; i < argc; ++i){
+    char const * zArg = argv[i];
+    while( '-'==*zArg ) ++zArg;
+    if( 0==strcmp(zArg,"k")
+        || 0==strcmp(zArg,"keep-first") ){
+      ++App.keepFirst;
+    }else{
+      usage(argv[0]);
+      return 1;
+    }
+  }
+  App.input = stdin;
+  App.output = stdout;
+  do_it_all();
+  return App.rc ? 1 : 0;
+}