Document the --mmap option in the --help screen for kvtest.  Enhance kvtest so
that numeric arguments can have suffixes like "K" or "M".  Add kvtest to the
unix makefiles.

FossilOrigin-Name: 175bda87288c7ce15b163316159f53a60822ccad
diff --git a/Makefile.in b/Makefile.in
index b961070..d5fa831 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1177,8 +1177,13 @@
 wordcount$(TEXE):	$(TOP)/test/wordcount.c sqlite3.lo
 	$(LTLINK) -o $@ $(TOP)/test/wordcount.c sqlite3.lo $(TLIBS)
 
-speedtest1$(TEXE):	$(TOP)/test/speedtest1.c sqlite3.lo
-	$(LTLINK) -o $@ $(TOP)/test/speedtest1.c sqlite3.lo $(TLIBS)
+speedtest1$(TEXE):	$(TOP)/test/speedtest1.c sqlite3.c
+	$(LTLINK) $(ST_OPT) -o $@ $(TOP)/test/speedtest1.c sqlite3.c $(TLIBS)
+
+KV_OPT += -DSQLITE_DIRECT_OVERFLOW_READ
+
+kvtest$(TEXE):	$(TOP)/test/kvtest.c sqlite3.c
+	$(LTLINK) $(KV_OPT) -o $@ $(TOP)/test/kvtest.c sqlite3.c $(TLIBS)
 
 rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.lo 
 	$(LTLINK) -I. -o $@ $(TOP)/ext/rbu/rbu.c sqlite3.lo $(TLIBS)
diff --git a/main.mk b/main.mk
index 3b6e7f8..17e6468 100644
--- a/main.mk
+++ b/main.mk
@@ -478,6 +478,8 @@
 FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
 FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
 DBFUZZ_OPT =
+KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
+ST_OPT = -DSQLITE_THREADSAFE=0
 
 # This is the default Makefile target.  The objects listed here
 # are what get build when you type just "make" with no arguments.
@@ -892,8 +894,11 @@
 	$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o wordcount$(EXE) \
 		$(TOP)/test/wordcount.c sqlite3.c
 
-speedtest1$(EXE):	$(TOP)/test/speedtest1.c sqlite3.o
-	$(TCCX) -I. $(OTAFLAGS) -o speedtest1$(EXE) $(TOP)/test/speedtest1.c sqlite3.o $(THREADLIB) 
+speedtest1$(EXE):	$(TOP)/test/speedtest1.c sqlite3.c
+	$(TCCX) -I. $(ST_OPT) -o speedtest1$(EXE) $(TOP)/test/speedtest1.c sqlite3.c $(THREADLIB) 
+
+kvtest$(EXE):	$(TOP)/test/kvtest.c sqlite3.c
+	$(TCCX) -I. $(KV+OPT) -o kvtest$(EXE) $(TOP)/test/kvtest.c sqlite3.c $(THREADLIB) 
 
 rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.o 
 	$(TCC) -I. -o rbu$(EXE) $(TOP)/ext/rbu/rbu.c sqlite3.o \
diff --git a/manifest b/manifest
index d96fa45..f8cd52f 100644
--- a/manifest
+++ b/manifest
@@ -1,6 +1,6 @@
-C Add\sthe\s--mmap\soption\sto\sthe\skvtest\sutility\sprogram.
-D 2017-01-23T18:40:15.799
-F Makefile.in 41bd4cad981487345c4a84081074bcdb876e4b2e
+C Document\sthe\s--mmap\soption\sin\sthe\s--help\sscreen\sfor\skvtest.\s\sEnhance\skvtest\sso\nthat\snumeric\sarguments\scan\shave\ssuffixes\slike\s"K"\sor\s"M".\s\sAdd\skvtest\sto\sthe\nunix\smakefiles.
+D 2017-01-23T19:11:38.113
+F Makefile.in 5f415e7867296d678fed2e6779aea10c1318b4bc
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc b8ca53350ae545e3562403d5da2a69cec79308da
 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
@@ -314,7 +314,7 @@
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
-F main.mk 8f620f3418d7252a3f428f5aacf674b5507807a8
+F main.mk afc52937b4e5fe08678e8d5a4fe4487d44e3bc61
 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -898,7 +898,7 @@
 F test/json102.test bf3fe7a706d30936a76a0f7a0375e1e8e73aff5a
 F test/json103.test c5f6b85e69de05f6b3195f9f9d5ce9cd179099a0
 F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
-F test/kvtest.c 87e6e974eb9e1502e00e77bc2831f3c9174a6dfb
+F test/kvtest.c d2d7c434023498237cf731df21ca0687bf103858
 F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
 F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
 F test/like.test 0603f4fa0dad50987f70032c05800cbfa8985302
@@ -1547,7 +1547,7 @@
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P ee793d30c1dc1f78f49e6230d17750eceedbd8ed
-R c50065d103fe6e8d8104ae7a368dc7b9
+P 4948f7e6d2a1cfce36a7aab2f5b65be07c285ac3
+R 9f530d22e2b0a16555eacd054431a10f
 U drh
-Z a1392fb7660aa1d68b81ecf426bbd2cf
+Z 4864426d37a32c6f04be82da7889e371
diff --git a/manifest.uuid b/manifest.uuid
index 28766bd..82e31c7 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-4948f7e6d2a1cfce36a7aab2f5b65be07c285ac3
\ No newline at end of file
+175bda87288c7ce15b163316159f53a60822ccad
\ No newline at end of file
diff --git a/test/kvtest.c b/test/kvtest.c
index f87e494..c82a3f8 100644
--- a/test/kvtest.c
+++ b/test/kvtest.c
@@ -85,6 +85,7 @@
 "             --count N            Read N blobs\n"
 "             --desc               Read blobs in descending order\n"
 "             --max-id N           Maximum blob key to use\n"
+"             --mmap N             Mmap as much as N bytes of DBFILE\n"
 "             --random             Read blobs in a random order\n"
 "             --start N            Start reading with this blob key\n"
 "             --stats              Output operating stats before exiting\n"
@@ -133,6 +134,64 @@
 }
 
 /*
+** Return the value of a hexadecimal digit.  Return -1 if the input
+** is not a hex digit.
+*/
+static int hexDigitValue(char c){
+  if( c>='0' && c<='9' ) return c - '0';
+  if( c>='a' && c<='f' ) return c - 'a' + 10;
+  if( c>='A' && c<='F' ) return c - 'A' + 10;
+  return -1;
+}
+
+/*
+** Interpret zArg as an integer value, possibly with suffixes.
+*/
+static int integerValue(const char *zArg){
+  int v = 0;
+  static const struct { char *zSuffix; int iMult; } aMult[] = {
+    { "KiB", 1024 },
+    { "MiB", 1024*1024 },
+    { "GiB", 1024*1024*1024 },
+    { "KB",  1000 },
+    { "MB",  1000000 },
+    { "GB",  1000000000 },
+    { "K",   1000 },
+    { "M",   1000000 },
+    { "G",   1000000000 },
+  };
+  int i;
+  int isNeg = 0;
+  if( zArg[0]=='-' ){
+    isNeg = 1;
+    zArg++;
+  }else if( zArg[0]=='+' ){
+    zArg++;
+  }
+  if( zArg[0]=='0' && zArg[1]=='x' ){
+    int x;
+    zArg += 2;
+    while( (x = hexDigitValue(zArg[0]))>=0 ){
+      v = (v<<4) + x;
+      zArg++;
+    }
+  }else{
+    while( zArg[0]>='0' && zArg[0]<='9' ){
+      v = v*10 + zArg[0] - '0';
+      zArg++;
+    }
+  }
+  for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){
+    if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
+      v *= aMult[i].iMult;
+      break;
+    }
+  }
+  return isNeg? -v : v;
+}
+
+
+/*
 ** Check the filesystem object zPath.  Determine what it is:
 **
 **    PATH_DIR     A directory
@@ -205,19 +264,19 @@
     if( z[1]=='-' ) z++;
     if( strcmp(z, "-count")==0 ){
       if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
-      nCount = atoi(argv[++i]);
+      nCount = integerValue(argv[++i]);
       if( nCount<1 ) fatalError("the --count must be positive");
       continue;
     }
     if( strcmp(z, "-size")==0 ){
       if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
-      sz = atoi(argv[++i]);
+      sz = integerValue(argv[++i]);
       if( sz<1 ) fatalError("the --size must be positive");
       continue;
     }
     if( strcmp(z, "-pagesize")==0 ){
       if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
-      pgsz = atoi(argv[++i]);
+      pgsz = integerValue(argv[++i]);
       if( pgsz<512 || pgsz>65536 || ((pgsz-1)&pgsz)!=0 ){
         fatalError("the --pagesize must be power of 2 between 512 and 65536");
       }
@@ -491,6 +550,7 @@
 #define ORDER_DESC    2
 #define ORDER_RANDOM  3
 
+
 /*
 ** Run a performance test
 */
@@ -532,31 +592,31 @@
     if( z[1]=='-' ) z++;
     if( strcmp(z, "-count")==0 ){
       if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
-      nCount = atoi(argv[++i]);
+      nCount = integerValue(argv[++i]);
       if( nCount<1 ) fatalError("the --count must be positive");
       continue;
     }
     if( strcmp(z, "-mmap")==0 ){
       if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
-      mmapSize = atoi(argv[++i]);
+      mmapSize = integerValue(argv[++i]);
       if( nCount<0 ) fatalError("the --mmap must be non-negative");
       continue;
     }
     if( strcmp(z, "-max-id")==0 ){
       if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
-      iMax = atoi(argv[++i]);
+      iMax = integerValue(argv[++i]);
       if( iMax<1 ) fatalError("the --max-id must be positive");
       continue;
     }
     if( strcmp(z, "-start")==0 ){
       if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
-      iKey = atoi(argv[++i]);
+      iKey = integerValue(argv[++i]);
       if( iKey<1 ) fatalError("the --start must be positive");
       continue;
     }
     if( strcmp(z, "-cache-size")==0 ){
       if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
-      iCache = atoi(argv[++i]);
+      iCache = integerValue(argv[++i]);
       continue;
     }
     if( strcmp(z, "-random")==0 ){