]> rtime.felk.cvut.cz Git - l4.git/commitdiff
update
authorl4check <l4check@d050ee49-bd90-4346-b210-929a50b99cfc>
Tue, 29 Jan 2013 07:12:37 +0000 (07:12 +0000)
committerl4check <l4check@d050ee49-bd90-4346-b210-929a50b99cfc>
Tue, 29 Jan 2013 07:12:37 +0000 (07:12 +0000)
git-svn-id: http://svn.tudos.org/repos/oc/tudos/trunk@44 d050ee49-bd90-4346-b210-929a50b99cfc

206 files changed:
kernel/fiasco/src/Makerules.VERSION
kernel/fiasco/src/drivers/io.cpp
kernel/fiasco/src/jdb/jdb_tbuf_show.cpp
kernel/fiasco/src/kern/arm/bsp/imx/uart-imx.cpp
kernel/fiasco/src/kern/arm/bsp/integrator/uart-arm-integrator.cpp
kernel/fiasco/src/kern/arm/bsp/realview/mem_layout-arm-realview.cpp
kernel/fiasco/src/kern/arm/bsp/realview/uart-arm-realview.cpp
kernel/fiasco/src/kern/arm/fpu-arm.cpp
kernel/fiasco/src/kern/arm/timer-arm.cpp
kernel/fiasco/src/kern/config.cpp
kernel/fiasco/src/kern/context.cpp
kernel/fiasco/src/kern/ia32/apic-ia32-mp.cpp
kernel/fiasco/src/kern/ia32/vm_svm.cpp
kernel/fiasco/src/kern/ia32/vm_vmx.cpp
kernel/fiasco/src/kern/ipc_timeout.cpp
kernel/fiasco/src/kern/kernel_uart.cpp
kernel/fiasco/src/kern/platform_control.cpp
kernel/fiasco/src/lib/uart/uart_pl011.cc
kernel/fiasco/src/lib/uart/uart_pl011.h
kernel/fiasco/tool/kconfig/Makefile
kernel/fiasco/tool/kconfig/README
kernel/fiasco/tool/kconfig/scripts/Kbuild.include
kernel/fiasco/tool/kconfig/scripts/Makefile
kernel/fiasco/tool/kconfig/scripts/Makefile.build
kernel/fiasco/tool/kconfig/scripts/Makefile.headersinst
kernel/fiasco/tool/kconfig/scripts/Makefile.modinst
kernel/fiasco/tool/kconfig/scripts/Makefile.modpost
kernel/fiasco/tool/kconfig/scripts/basic/.gitignore [new file with mode: 0644]
kernel/fiasco/tool/kconfig/scripts/kconfig/.gitignore
kernel/fiasco/tool/kconfig/scripts/kconfig/Makefile
kernel/fiasco/tool/kconfig/scripts/kconfig/check.sh
kernel/fiasco/tool/kconfig/scripts/kconfig/conf.c
kernel/fiasco/tool/kconfig/scripts/kconfig/confdata.c
kernel/fiasco/tool/kconfig/scripts/kconfig/expr.h
kernel/fiasco/tool/kconfig/scripts/kconfig/list.h [new file with mode: 0644]
kernel/fiasco/tool/kconfig/scripts/kconfig/lkc_proto.h
kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/check-lxdialog.sh
kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/dialog.h
kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/textbox.c
kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/util.c
kernel/fiasco/tool/kconfig/scripts/kconfig/mconf.c
kernel/fiasco/tool/kconfig/scripts/kconfig/menu.c
kernel/fiasco/tool/kconfig/scripts/kconfig/nconf.c
kernel/fiasco/tool/kconfig/scripts/kconfig/nconf.gui.c
kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.tab.c_shipped
kernel/fiasco/tool/preprocess/src/preprocess
kernel/fiasco/tool/preprocess/test/Makefile
kernel/fiasco/tool/preprocess/test/implement_template.cpp [new file with mode: 0644]
kernel/fiasco/tool/preprocess/test/verify/implement_template.cc [new file with mode: 0644]
kernel/fiasco/tool/preprocess/test/verify/implement_template.h [new file with mode: 0644]
kernel/fiasco/tool/preprocess/test/verify/implement_template_i.h [new file with mode: 0644]
kernel/fiasco/tool/preprocess/test/verify/line_nh.h
kernel/fiasco/tool/preprocess/test/verify/line_not.cc
kernel/fiasco/tool/preprocess/test/verify/line_not.h
kernel/fiasco/tool/preprocess/test/verify/operator.h
kernel/fiasco/tool/preprocess/test/verify/template.cc
kernel/fiasco/tool/preprocess/test/verify/template.h
l4/Makefile
l4/mk/defconfig/config.arm-rv
l4/pkg/bootstrap/server/src/Make.rules
l4/pkg/bootstrap/server/src/platform/integrator.cc
l4/pkg/bootstrap/server/src/platform/rv.cc
l4/pkg/bootstrap/server/src/platform/rv_vexpress.cc
l4/pkg/drivers-frst/uart/include/uart_pl011.h
l4/pkg/drivers-frst/uart/src/uart_pl011.cc
l4/pkg/examples/sys/vmtest/svmtest.c
l4/pkg/io/config/x86-legacy.devs
l4/pkg/io/server/libpciids/src/pci.ids
l4/pkg/io/server/src/Make.rules
l4/pkg/io/server/src/Makefile
l4/pkg/l4sys/include/__vm-svm.h
l4/pkg/l4util/lib/src/Makefile
l4/pkg/libio-io/lib/src/io.cc
l4/pkg/libstdc++-headers/include-std/Makefile
l4/pkg/libvcpu/include/vcpu
l4/pkg/libvcpu/include/vcpu.h
l4/pkg/libvcpu/lib/src/ARCH-amd64/arch.cc
l4/pkg/libvcpu/lib/src/ARCH-x86/arch.cc
l4/pkg/libvcpu/lib/src/vcpu.cc
l4/pkg/mag-gfx/include/gfx_colors
l4/pkg/mag/server/src/screen.cc
l4/pkg/moe/server/src/alloc.cc
l4/pkg/moe/server/src/quota.h
l4/pkg/plr/Control
l4/pkg/plr/Makefile
l4/pkg/plr/doc/romain.lua
l4/pkg/plr/doc/threadini.sh
l4/pkg/plr/ex/Makefile
l4/pkg/plr/ex/eventbuf/Makefile [new file with mode: 0644]
l4/pkg/plr/ex/eventbuf/main.cc [new file with mode: 0644]
l4/pkg/plr/ex/hello/Makefile [new file with mode: 0644]
l4/pkg/plr/ex/hello/cmain.c [new file with mode: 0644]
l4/pkg/plr/ex/hello/main.cc [new file with mode: 0644]
l4/pkg/plr/ex/pthread_hello/main.c
l4/pkg/plr/ex/pthread_mutex/Makefile
l4/pkg/plr/ex/pthread_mutex/main.c
l4/pkg/plr/include/measurements.h [new file with mode: 0644]
l4/pkg/plr/include/pthread_rep.h
l4/pkg/plr/include/uu.h [new file with mode: 0644]
l4/pkg/plr/lib/Makefile
l4/pkg/plr/lib/libevbuf_c/Makefile [new file with mode: 0644]
l4/pkg/plr/lib/libevbuf_c/eb.cc [new file with mode: 0644]
l4/pkg/plr/lib/libpthread_romain/src/Makefile
l4/pkg/plr/lib/libpthread_romain/src/descr.h [new file with mode: 0644]
l4/pkg/plr/lib/libpthread_romain/src/mutex.c
l4/pkg/plr/lib/libuu/Makefile [new file with mode: 0644]
l4/pkg/plr/lib/libuu/uu.c [new file with mode: 0644]
l4/pkg/plr/patches/fiasco_ud2yield.diff [new file with mode: 0644]
l4/pkg/plr/patches/l4sys_kdebug0x42.diff [new file with mode: 0644]
l4/pkg/plr/server/src/Makefile
l4/pkg/plr/server/src/app
l4/pkg/plr/server/src/app_loading
l4/pkg/plr/server/src/app_loading.cc
l4/pkg/plr/server/src/app_thread.cc
l4/pkg/plr/server/src/configuration
l4/pkg/plr/server/src/constants.h
l4/pkg/plr/server/src/emulation
l4/pkg/plr/server/src/emulation.cc
l4/pkg/plr/server/src/exceptions
l4/pkg/plr/server/src/fault_handlers/debugger.cc
l4/pkg/plr/server/src/fault_handlers/debugging.h
l4/pkg/plr/server/src/fault_handlers/kiptime.cc
l4/pkg/plr/server/src/fault_handlers/lock_observer.cc
l4/pkg/plr/server/src/fault_handlers/lock_observer.h
l4/pkg/plr/server/src/fault_handlers/observer.cc
l4/pkg/plr/server/src/fault_handlers/observers.h
l4/pkg/plr/server/src/fault_handlers/pagefault.cc
l4/pkg/plr/server/src/fault_handlers/replicalog.cc [new file with mode: 0644]
l4/pkg/plr/server/src/fault_handlers/swifi.h
l4/pkg/plr/server/src/fault_handlers/syscalls.cc
l4/pkg/plr/server/src/fault_handlers/syscalls_factory.h
l4/pkg/plr/server/src/fault_handlers/syscalls_handler.h
l4/pkg/plr/server/src/fault_handlers/trap_limit.cc
l4/pkg/plr/server/src/fault_handlers/trap_observer.cc
l4/pkg/plr/server/src/fault_observers
l4/pkg/plr/server/src/gdb_stub/connection
l4/pkg/plr/server/src/gdb_stub/gdb.cc
l4/pkg/plr/server/src/gdb_stub/gdbserver
l4/pkg/plr/server/src/gdb_stub/serial_connection.cc
l4/pkg/plr/server/src/gdb_stub/tcp_connection.cc
l4/pkg/plr/server/src/handler.cc
l4/pkg/plr/server/src/locking.h
l4/pkg/plr/server/src/log
l4/pkg/plr/server/src/logging.cc [new file with mode: 0644]
l4/pkg/plr/server/src/main.cc
l4/pkg/plr/server/src/manager
l4/pkg/plr/server/src/manager.cc
l4/pkg/plr/server/src/memory
l4/pkg/plr/server/src/memory.cc
l4/pkg/plr/server/src/redundancy.h
l4/pkg/plr/server/src/redundancy/dmr.cc
l4/pkg/plr/server/src/thread_group.h
l4/pkg/plr/tools/boris/boris
l4/pkg/plr/tools/igor/igor
l4/pkg/plr/tools/timur/timur
l4/pkg/plr/tools/tsar/tsar [new file with mode: 0755]
l4/pkg/plr/tools/tsar/tsar_events.py [new file with mode: 0644]
l4/pkg/serial-drv/server/src/main.cc
l4/pkg/sqlite/lib/README
l4/pkg/sqlite/lib/contrib/Makefile.am
l4/pkg/sqlite/lib/contrib/Makefile.in
l4/pkg/sqlite/lib/contrib/configure
l4/pkg/sqlite/lib/contrib/configure.ac
l4/pkg/sqlite/lib/contrib/shell.c
l4/pkg/sqlite/lib/contrib/sqlite3.c
l4/pkg/sqlite/lib/contrib/sqlite3.h
l4/pkg/uclibc/lib/libpthread/src/Makefile
l4/pkg/uclibc/lib/libpthread/src/signals.c [new file with mode: 0644]
l4/pkg/uclibc/lib/uclibc/ARCH-all/include/bits/sigthread.h
l4/pkg/valgrind/src/valgrind-3.6.0-svn/Makefile.in
l4/tool/kconfig/Makefile
l4/tool/kconfig/README
l4/tool/kconfig/scripts/Kbuild.include
l4/tool/kconfig/scripts/Makefile
l4/tool/kconfig/scripts/Makefile.build
l4/tool/kconfig/scripts/Makefile.headersinst
l4/tool/kconfig/scripts/Makefile.modinst
l4/tool/kconfig/scripts/Makefile.modpost
l4/tool/kconfig/scripts/kconfig/.gitignore
l4/tool/kconfig/scripts/kconfig/Makefile
l4/tool/kconfig/scripts/kconfig/check.sh
l4/tool/kconfig/scripts/kconfig/conf.c
l4/tool/kconfig/scripts/kconfig/confdata.c
l4/tool/kconfig/scripts/kconfig/expr.h
l4/tool/kconfig/scripts/kconfig/list.h [new file with mode: 0644]
l4/tool/kconfig/scripts/kconfig/lkc_proto.h
l4/tool/kconfig/scripts/kconfig/lxdialog/check-lxdialog.sh
l4/tool/kconfig/scripts/kconfig/lxdialog/dialog.h
l4/tool/kconfig/scripts/kconfig/lxdialog/textbox.c
l4/tool/kconfig/scripts/kconfig/lxdialog/util.c
l4/tool/kconfig/scripts/kconfig/mconf.c
l4/tool/kconfig/scripts/kconfig/menu.c
l4/tool/kconfig/scripts/kconfig/nconf.c
l4/tool/kconfig/scripts/kconfig/nconf.gui.c
tools/preprocess/src/preprocess
tools/preprocess/test/Makefile
tools/preprocess/test/implement_template.cpp [new file with mode: 0644]
tools/preprocess/test/verify/implement_template.cc [new file with mode: 0644]
tools/preprocess/test/verify/implement_template.h [new file with mode: 0644]
tools/preprocess/test/verify/implement_template_i.h [new file with mode: 0644]
tools/preprocess/test/verify/line_nh.h
tools/preprocess/test/verify/line_not.cc
tools/preprocess/test/verify/line_not.h
tools/preprocess/test/verify/operator.h
tools/preprocess/test/verify/template.cc
tools/preprocess/test/verify/template.h

index 3922d3f596fdb61cf1d1e07e8f281353ff01f0f9..cbfe5f92f49a27c35d321d13e1841387c4fd7961 100644 (file)
@@ -6,18 +6,19 @@ $(filter kip%.o,$(OBJ_ABI)): $(VERSION)
 
 $(VERSION): FORCE
                $(GENVER_MESSAGE)
-               $(VERBOSE)if [ -d $(srcdir)/.svn ]; then               \
-                  v=`svnversion -nc $(srcdir)`; v=$${v%[A-Z]};        \
-                  echo "#define CODE_VERSION \"r$${v#*:}\"" > $@;     \
-               elif [ -d $(srcdir)/.git ]; then                       \
-                  v=`git rev-parse --verify --short HEAD 2>/dev/null` \
-                  echo "#define CODE_VERSION \"$$v\"" > $@;           \
-               elif [ -d $(srcdir)/.hg ]; then                        \
-                  v=`hg id 2>/dev/null`                               \
-                  echo "#define CODE_VERSION \"$${v% *}\"" > $@;      \
-               else                                                   \
-                  echo "#define CODE_VERSION \"UNKNOWN\"" > $@;       \
-               fi
+               $(VERBOSE)v=`git rev-parse --verify --short HEAD 2>/dev/null`;\
+               if [ -z "$$v" ]; then                                  \
+                  v=`svnversion -nc $(srcdir)`;                       \
+                  if [ -n "$$v" ]; then                               \
+                    v=$${v%[A-Z]}; v="r$${v#*:}";                     \
+                  else                                                \
+                    v=`hg id 2>/dev/null`;                            \
+                    if [ -n "$$v" ]; then                             \
+                      v="$${v% *}";                                   \
+                    fi                                                \
+                  fi                                                  \
+               fi;                                                    \
+               echo "#define CODE_VERSION \"$$v\"" > $@
                $(VERBOSE)echo "#define BUILD_DATE \"$$(date)\"" >> $@
                $(VERBOSE)if [ -e .build_nr ]; then                    \
                  nr=$$(($$(cat .build_nr) + 1));                      \
index e1a0685ad431cbf802d40e15640936e45f6a90f9..412bdb5abab2b06e8910f61050ac5780f7925c59 100644 (file)
@@ -127,17 +127,17 @@ IMPLEMENTATION:
 IMPLEMENT inline
 template< typename T>
 void Io::mask(T mask, Address address)
-{ write(read<T>(address) & mask, address); }
+{ write<T>(read<T>(address) & mask, address); }
 
 IMPLEMENT inline
 template< typename T>
 void Io::clear(T clearbits, Address address)
-{ write(read<T>(address) & ~clearbits, address); }
+{ write<T>(read<T>(address) & ~clearbits, address); }
 
 IMPLEMENT inline
 template< typename T>
 void Io::set(T setbits, Address address)
-{ write(read<T>(address) | setbits, address); }
+{ write<T>(read<T>(address) | setbits, address); }
 
 
 
index d88ef390a25cec4cd19115784daff772d71f03d4..d91c4a952b34aea1928e7acb239c7573724247e4 100644 (file)
@@ -782,33 +782,37 @@ restart:
             {
               typedef Tb_entry::Group_order Group_order;
 
-              Tb_entry const *ce = Jdb_tbuf::lookup(_absy + addy);
-              Tb_entry_formatter const *fmt = Tb_entry_formatter::get_fmt(ce);
               Group_order pt;
+              Tb_entry const *ce = Jdb_tbuf::lookup(_absy + addy);
 
-              if (fmt)
-                pt = fmt->has_partner(ce);
-
-              if (!pt.not_grouped())
+              if (ce)
                 {
-                  if (!pt.is_first())
-                    find_group(&group, ce, true, lines, pt.depth());
-                  if (!pt.is_last())
-                    find_group(&group, ce, false, lines, pt.depth());
-                }
+                  Tb_entry_formatter const *fmt = Tb_entry_formatter::get_fmt(ce);
 
-              for (unsigned i = 0; i < group.size(); ++i)
-                {
-                  Entry_group::Item const &item = group[i];
-                  Jdb::cursor(item.y - _absy + Tbuf_start_line, 3);
-                  putstr(Jdb::esc_emph);
-                  if (item.order.is_first())
-                    putstr("<++");
-                  else if (item.order.is_last())
-                    putstr("++>");
-                  else if (item.order.grouped())
-                    putstr("+++");
-                  putstr("\033[m");
+                  if (fmt)
+                    pt = fmt->has_partner(ce);
+
+                  if (!pt.not_grouped())
+                    {
+                      if (!pt.is_first())
+                        find_group(&group, ce, true, lines, pt.depth());
+                      if (!pt.is_last())
+                        find_group(&group, ce, false, lines, pt.depth());
+                    }
+
+                  for (unsigned i = 0; i < group.size(); ++i)
+                    {
+                      Entry_group::Item const &item = group[i];
+                      Jdb::cursor(item.y - _absy + Tbuf_start_line, 3);
+                      putstr(Jdb::esc_emph);
+                      if (item.order.is_first())
+                        putstr("<++");
+                      else if (item.order.is_last())
+                        putstr("++>");
+                      else if (item.order.grouped())
+                        putstr("+++");
+                      putstr("\033[m");
+                    }
                 }
             }
 
index 67d7041d13c22ed39fc189e964cfe6b39e41c049..7f6e572f89731e6c760c464b2e64f0d8f09b3a10 100644 (file)
@@ -41,7 +41,7 @@ IMPLEMENTATION [imx6]:
 
 #include "uart_imx.h"
 
-IMPLEMENT int Uart::irq() const { return 90; }
+IMPLEMENT int Uart::irq() const { return 59; }
 
 IMPLEMENT L4::Uart *Uart::uart()
 {
index 78a837bddfa832a548f6630fa23d4600c4055dfc..dbef46c80ae08905e6f4f293cad6295024afaa00 100644 (file)
@@ -9,6 +9,6 @@ IMPLEMENT int Uart::irq() const { return 1; }
 
 IMPLEMENT L4::Uart *Uart::uart()
 {
-  static L4::Uart_pl011 uart;
+  static L4::Uart_pl011 uart(24019200);
   return &uart;
 }
index b7af3315bfe68c642687c526c9d728304e83200e..d33d22446311de27d523d873758513bc680686f4 100644 (file)
@@ -79,7 +79,7 @@ public:
   };
 
   enum Phys_layout_realview_mp : Address {
-    Devices1_phys_base   = 0x1f000000,
+    Devices1_phys_base   = 0x10100000,
     Devices2_phys_base   = Invalid_address,
   };
 };
index 9572d7444cf0ae951b4928a4fa636f8acd9d16f5..bd85d5648a9e4b4493e2cdd70cfed7cdfc00bb21 100644 (file)
@@ -19,6 +19,6 @@ IMPLEMENT Address Uart::base() const { return Mem_layout::Uart_base; }
 
 IMPLEMENT L4::Uart *Uart::uart()
 {
-  static L4::Uart_pl011 uart;
+  static L4::Uart_pl011 uart(24019200);
   return &uart;
 }
index 70ffc63be0af9d989f322675a8c4e605c9cb75f8..b221b76cf91037dfdc2ed08a4937193dbc537572 100644 (file)
@@ -77,7 +77,7 @@ Fpu::copro_enable()
                "orr  %0, %0, %1           \n"
                "mcr  p15, 0, %0, c1, c0, 2\n"
                : : "r" (0), "I" (0x00f00000));
-  Mem::dsb();
+  Mem::isb();
 }
 
 // ------------------------------------------------------------------------
index 685038d431a41fd4074ba68911fc758e0deb2945..9a03120d61b705ba4809b35bb08128b980d60c5a 100644 (file)
@@ -9,6 +9,26 @@ private:
   static inline void update_one_shot(Unsigned64 wakeup);
 };
 
+// ------------------------------------------------------------------------
+IMPLEMENTATION [arm && vcache]:
+
+#include "mem_unit.h"
+
+PRIVATE static inline NEEDS["mem_unit.h"]
+void
+Timer::kipclock_cache()
+{
+  Mem_unit::clean_dcache((void *)&Kip::k()->clock);
+}
+
+// ------------------------------------------------------------------------
+IMPLEMENTATION [arm && !vcache]:
+
+PRIVATE static inline
+void
+Timer::kipclock_cache()
+{}
+
 // ------------------------------------------------------------------------
 IMPLEMENTATION [arm]:
 
@@ -24,13 +44,14 @@ Timer::init_system_clock()
   Kip::k()->clock = 0;
 }
 
-IMPLEMENT inline NEEDS["config.h", "globals.h", "kip.h", "watchdog.h"]
+IMPLEMENT inline NEEDS["config.h", "globals.h", "kip.h", "watchdog.h", Timer::kipclock_cache]
 void
 Timer::update_system_clock(unsigned cpu)
 {
   if (cpu == 0)
     {
       Kip::k()->clock += Config::Scheduler_granularity;
+      kipclock_cache();
       Watchdog::touch();
     }
 }
index 9d0d17d92a96d9484fae2e1dc957dc391e0ca68a..15d125c5732c6289b10a1293f36b3b90c733ab8f 100644 (file)
@@ -142,7 +142,7 @@ INTERFACE:
 #define CONFIG_KERNEL_VERSION_STRING \
   GREETING_COLOR_ANSI_TITLE "Welcome to Fiasco.OC (" CONFIG_XARCH ")!\\n"            \
   GREETING_COLOR_ANSI_INFO "L4/Fiasco.OC " ARCH_NAME " "                \
-                           "microkernel (C) 1998-2012 TU Dresden\\n"           \
+                           "microkernel (C) 1998-2013 TU Dresden\\n"           \
                            "Rev: " CODE_VERSION " compiled with gcc " COMPILER \
                             " for " TARGET_NAME "    [" CONFIG_LABEL "]\\n"    \
                            "Build: #" BUILD_NR " " BUILD_DATE "\\n"            \
index a364e66a834bb0c7850f4791a6245d4bc4488d20..d78c1bc3dd3fc3c6daed786ed226d2b8a3361ede 100644 (file)
@@ -317,11 +317,13 @@ protected:
   Migration *_migration;
   bool _need_to_finish_migration;
 
+public:
   void arch_load_vcpu_kern_state(Vcpu_state *vcpu, bool do_load);
+
+protected:
   void arch_load_vcpu_user_state(Vcpu_state *vcpu, bool do_load);
   void arch_update_vcpu_state(Vcpu_state *vcpu);
 
-protected:
   // XXX Timeout for both, sender and receiver! In normal case we would have
   // to define own timeouts in Receiver and Sender but because only one
   // timeout can be set at one time we use the same timeout. The timeout
index 42ca49cbfa260cb7b60ab200ed5bca4b55c62d51..ddfcb98ac889e7f0121a0a517ec6946ea1f85dc9 100644 (file)
@@ -61,6 +61,15 @@ Apic::mp_ipi_idle_timeout(Cpu const *c, Unsigned32 wait)
   return mp_ipi_idle();
 }
 
+PRIVATE static inline
+void
+Apic::delay(Cpu const *c, Unsigned32 wait)
+{
+  Unsigned64 wait_till = c->time_us() + wait;
+  while (c->time_us() < wait_till)
+    Proc::pause();
+}
+
 PUBLIC static inline NEEDS [<cassert>]
 void
 Apic::mp_send_ipi(Unsigned32 dest, Unsigned32 vect,
@@ -133,6 +142,8 @@ Apic::mp_startup(Cpu const *current_cpu, Unsigned32 dest, Address tramp_page)
   // Send INIT IPI
   mp_send_ipi(dest, 0, APIC_IPI_INIT);
 
+  delay(current_cpu, 200);
+
   // delay for 10ms (=10,000us)
   if (!mp_ipi_idle_timeout(current_cpu, 10000))
     return;
index e16066513f0648b8adbf23ff0e8261cd0db5b2b1..f89770bdbebf510276d3b33ff64f243f5af88f16 100644 (file)
@@ -667,7 +667,10 @@ Vm_svm::resume_vcpu(Context *ctxt, Vcpu_state *vcpu, bool user_mode)
   assert_kdb (user_mode);
 
   if (EXPECT_FALSE(!(ctxt->state(true) & Thread_ext_vcpu_enabled)))
-    return -L4_err::EInval;
+    {
+      ctxt->arch_load_vcpu_kern_state(vcpu, true);
+      return -L4_err::EInval;
+    }
 
   Vmcb *vmcb_s = reinterpret_cast<Vmcb*>(reinterpret_cast<char *>(vcpu) + 0x400);
   for (;;)
@@ -678,6 +681,7 @@ Vm_svm::resume_vcpu(Context *ctxt, Vcpu_state *vcpu, bool user_mode)
          && (vcpu->sticky_flags & Vcpu_state::Sf_irq_pending))
        {
          vmcb_s->control_area.exitcode = 0x60;
+          ctxt->arch_load_vcpu_kern_state(vcpu, true);
          return 1; // return 1 to indicate pending IRQs (IPCs)
        }
 
@@ -685,7 +689,10 @@ Vm_svm::resume_vcpu(Context *ctxt, Vcpu_state *vcpu, bool user_mode)
 
       // test for error or non-IRQ exit reason
       if (r <= 0)
-       return r;
+        {
+          ctxt->arch_load_vcpu_kern_state(vcpu, true);
+          return r;
+        }
 
       // check for IRQ exits and allow to handle the IRQ
       if (r == 1)
@@ -699,8 +706,11 @@ Vm_svm::resume_vcpu(Context *ctxt, Vcpu_state *vcpu, bool user_mode)
       Thread *t = nonull_static_cast<Thread*>(ctxt);
 
       if (t->continuation_test_and_restore())
-        t->fast_return_to_user(vcpu->_entry_ip, vcpu->_entry_sp,
-                               t->vcpu_state().usr().get());
+        {
+          ctxt->arch_load_vcpu_kern_state(vcpu, true);
+          t->fast_return_to_user(vcpu->_entry_ip, vcpu->_entry_sp,
+                                 t->vcpu_state().usr().get());
+        }
     }
 }
 
index 6d8ebd6d52464fd209aad84e4e7c49dcb94585f8..586a4a381503dbeb6bc36048cd00e2651872e359 100644 (file)
@@ -481,7 +481,10 @@ Vm_vmx::resume_vcpu(Context *ctxt, Vcpu_state *vcpu, bool user_mode)
   assert_kdb (user_mode);
 
   if (EXPECT_FALSE(!(ctxt->state(true) & Thread_ext_vcpu_enabled)))
-    return -L4_err::EInval;
+    {
+      ctxt->arch_load_vcpu_kern_state(vcpu, true);
+      return -L4_err::EInval;
+    }
 
   void *vmcs_s = reinterpret_cast<char *>(vcpu) + 0x400;
 
@@ -494,6 +497,7 @@ Vm_vmx::resume_vcpu(Context *ctxt, Vcpu_state *vcpu, bool user_mode)
        {
          // XXX: check if this is correct, we set external irq exit as reason
          write<Unsigned32>(vmcs_s, Vmx::F_exit_reason, 1);
+          ctxt->arch_load_vcpu_kern_state(vcpu, true);
          return 1; // return 1 to indicate pending IRQs (IPCs)
        }
 
@@ -501,7 +505,10 @@ Vm_vmx::resume_vcpu(Context *ctxt, Vcpu_state *vcpu, bool user_mode)
 
       // test for error or non-IRQ exit reason
       if (r <= 0)
-       return r;
+        {
+          ctxt->arch_load_vcpu_kern_state(vcpu, true);
+          return r;
+        }
 
       // check for IRQ exits and allow to handle the IRQ
       if (r == 1)
@@ -514,7 +521,10 @@ Vm_vmx::resume_vcpu(Context *ctxt, Vcpu_state *vcpu, bool user_mode)
       // with bogus state.
       Thread *t = nonull_static_cast<Thread*>(ctxt);
       if (t->continuation_test_and_restore())
-        t->fast_return_to_user(vcpu->_entry_ip, vcpu->_entry_sp,
-                               t->vcpu_state().usr().get());
+        {
+          ctxt->arch_load_vcpu_kern_state(vcpu, true);
+          t->fast_return_to_user(vcpu->_entry_ip, vcpu->_entry_sp,
+                                 t->vcpu_state().usr().get());
+        }
     }
 }
index 08c20701eaae1143a552a6c02c6001dc0ba06a6b..9a382bb3a1ef84ee69b061c3c7547f24a981ca70 100644 (file)
@@ -55,7 +55,10 @@ IPC_timeout::expired()
 {
   Receiver * const _owner = owner();
 
-  // Set thread ready
+  Mword ipc_state = _owner->state() & Thread_ipc_mask;
+  if (!ipc_state || (ipc_state & Thread_receive_in_progress))
+    return false;
+
   _owner->state_change_dirty(~Thread_ipc_mask, Thread_ready | Thread_timeout);
 
   // Flag reschedule if owner's priority is higher than the current
index ce086afbaf258476fd14a4872c2bb87bc669a874..0d573239266549f3117b3979ea3df467a5746978 100644 (file)
@@ -108,9 +108,9 @@ public:
   {
     mask_and_ack();
     ui->ack();
+    unmask();
     if (!Vkey::check_())
       kdb_ke("IRQ ENTRY");
-    unmask();
   }
 };
 
index 339ac82db929ec64a5d9b38b523c5d368ddadb99..9780160376188fef0139575f8f938b72c7c61272 100644 (file)
@@ -20,6 +20,16 @@ void
 Platform_control::init(unsigned)
 {}
 
+IMPLEMENT inline NEEDS["l4_types.h"]
+int
+Platform_control::system_suspend()
+{ return -L4_err::EBusy; }
+
+// ------------------------------------------------------------------------
+IMPLEMENTATION [!cpu_suspend || !mp]:
+
+#include "l4_types.h"
+
 IMPLEMENT inline
 bool
 Platform_control::cpu_offline_available()
@@ -34,8 +44,3 @@ IMPLEMENT inline NEEDS["l4_types.h"]
 int
 Platform_control::resume_cpu(unsigned)
 { return -L4_err::ENodev; }
-
-IMPLEMENT inline NEEDS["l4_types.h"]
-int
-Platform_control::system_suspend()
-{ return -L4_err::EBusy; }
index 34174a4a2db80752dfd3261fc8167ee01194038d..02e8500c979917359e8c742866f393db0fbfb1cf 100644 (file)
@@ -41,16 +41,18 @@ namespace L4
     UART011_IMSC = 0x38,
     UART011_MIS  = 0x40,
     UART011_ICR  = 0x44,
-  };
 
+    Default_baud = 115200,
+  };
 
   bool Uart_pl011::startup(Io_register_block const *regs)
   {
     _regs = regs;
     _regs->write<unsigned int>(UART011_CR, UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE);
-    _regs->write<unsigned int>(UART011_FBRD, 2);
-    _regs->write<unsigned int>(UART011_IBRD, 13);
-    _regs->write<unsigned int>(UART011_LCRH, 0x60);
+    unsigned fi_val = _freq * 4 / Default_baud;
+    _regs->write<unsigned int>(UART011_FBRD, fi_val & 0x3f);
+    _regs->write<unsigned int>(UART011_IBRD, fi_val >> 6);
+    _regs->write<unsigned int>(UART011_LCRH, UART01x_LCRH_WLEN_8);
     _regs->write<unsigned int>(UART011_IMSC, 0);
     Poll_timeout_counter i(3000000);
     while (i.test() && _regs->read<unsigned int>(UART01x_FR) & UART01x_FR_BUSY)
@@ -80,14 +82,12 @@ namespace L4
 
   bool Uart_pl011::change_mode(Transfer_mode, Baud_rate r)
   {
-    if (r != 115200)
-      return false;
-
     unsigned long old_cr = _regs->read<unsigned int>(UART011_CR);
     _regs->write<unsigned int>(UART011_CR, 0);
 
-    _regs->write<unsigned int>(UART011_FBRD, 2);
-    _regs->write<unsigned int>(UART011_IBRD, 13);
+    unsigned fi_val = _freq * 4 / r;
+    _regs->write<unsigned int>(UART011_FBRD, fi_val & 0x3f);
+    _regs->write<unsigned int>(UART011_IBRD, fi_val >> 6);
     _regs->write<unsigned int>(UART011_LCRH, UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN);
 
     _regs->write<unsigned int>(UART011_CR, old_cr);
index 3e9019ea6bf124d40fa697e330436f77a81e6c1b..9d5322f1166ad1b7240e760f68c37676810485a3 100644 (file)
@@ -8,6 +8,7 @@ namespace L4
   class Uart_pl011 : public Uart
   {
   public:
+    Uart_pl011(unsigned freq) : _freq(freq) {}
     bool startup(Io_register_block const *);
     void shutdown();
     bool change_mode(Transfer_mode m, Baud_rate r);
@@ -16,6 +17,9 @@ namespace L4
     int char_avail() const;
     inline void out_char(char c) const;
     int write(char const *s, unsigned long count) const;
+
+  private:
+    unsigned _freq;
   };
 };
 
index c565ae059bd4066d9a298690976730a42e34fcc1..cc8a266ff302d1d380839b9929a8d3f1b80ec349 100644 (file)
@@ -1,8 +1,8 @@
 VERSION = 3
-PATCHLEVEL = 5
+PATCHLEVEL = 7
 SUBLEVEL = 0
 EXTRAVERSION =
-NAME = Saber-toothed Squirrel
+NAME = Terrified Chipmunk
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
@@ -350,12 +350,22 @@ AFLAGS_KERNEL     =
 CFLAGS_GCOV    = -fprofile-arcs -ftest-coverage
 
 
+# Use USERINCLUDE when you must reference the UAPI directories only.
+USERINCLUDE    := \
+               -I$(srctree)/arch/$(hdr-arch)/include/uapi \
+               -Iarch/$(hdr-arch)/include/generated/uapi \
+               -I$(srctree)/include/uapi \
+               -Iinclude/generated/uapi \
+                -include $(srctree)/include/linux/kconfig.h
+
 # Use LINUXINCLUDE when you must reference the include/ directory.
 # Needed to be compatible with the O= option
-LINUXINCLUDE    := -I$(srctree)/arch/$(hdr-arch)/include \
-                   -Iarch/$(hdr-arch)/include/generated -Iinclude \
-                   $(if $(KBUILD_SRC), -I$(srctree)/include) \
-                   -include $(srctree)/include/linux/kconfig.h
+LINUXINCLUDE    := \
+               -I$(srctree)/arch/$(hdr-arch)/include \
+               -Iarch/$(hdr-arch)/include/generated \
+               $(if $(KBUILD_SRC), -I$(srctree)/include) \
+               -Iinclude \
+               $(USERINCLUDE)
 
 KBUILD_CPPFLAGS := -D__KERNEL__
 
@@ -427,7 +437,9 @@ endif
 PHONY += asm-generic
 asm-generic:
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.asm-generic \
-                   obj=arch/$(SRCARCH)/include/generated/asm
+                   src=asm obj=arch/$(SRCARCH)/include/generated/asm
+       $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.asm-generic \
+                   src=uapi/asm obj=arch/$(SRCARCH)/include/generated/uapi/asm
 
 # To make sure we do not include .config for any of the *config targets
 # catch them early, and hand them over to scripts/kconfig/Makefile
@@ -437,9 +449,11 @@ asm-generic:
 # Detect when mixed targets is specified, and make a second invocation
 # of make so .config is not included in this case either (for *config).
 
+version_h := include/generated/uapi/linux/version.h
+
 no-dot-config-targets := clean mrproper distclean \
                         cscope gtags TAGS tags help %docs check% coccicheck \
-                        include/linux/version.h headers_% archheaders archscripts \
+                        $(version_h) headers_% archheaders archscripts \
                         kernelversion %src-pkg
 
 config-targets := 0
@@ -535,11 +549,11 @@ PHONY += include/config/auto.conf
 
 include/config/auto.conf:
        $(Q)test -e include/generated/autoconf.h -a -e $@ || (          \
-       echo;                                                           \
-       echo "  ERROR: Kernel configuration is invalid.";               \
-       echo "         include/generated/autoconf.h or $@ are missing.";\
-       echo "         Run 'make oldconfig && make prepare' on kernel src to fix it.";  \
-       echo;                                                           \
+       echo >&2;                                                       \
+       echo >&2 "  ERROR: Kernel configuration is invalid.";           \
+       echo >&2 "         include/generated/autoconf.h or $@ are missing.";\
+       echo >&2 "         Run 'make oldconfig && make prepare' on kernel src to fix it.";      \
+       echo >&2 ;                                                      \
        /bin/false)
 
 endif # KBUILD_EXTMOD
@@ -609,7 +623,11 @@ KBUILD_CFLAGS      += $(call cc-option, -femit-struct-debug-baseonly)
 endif
 
 ifdef CONFIG_FUNCTION_TRACER
-KBUILD_CFLAGS  += -pg
+ifdef CONFIG_HAVE_FENTRY
+CC_USING_FENTRY        := $(call cc-option, -mfentry -DCC_USING_FENTRY)
+endif
+KBUILD_CFLAGS  += -pg $(CC_USING_FENTRY)
+KBUILD_AFLAGS  += $(CC_USING_FENTRY)
 ifdef CONFIG_DYNAMIC_FTRACE
        ifdef CONFIG_HAVE_C_RECORDMCOUNT
                BUILD_C_RECORDMCOUNT := y
@@ -648,22 +666,9 @@ ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC)), y)
 endif
 
 # Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments
-# But warn user when we do so
-warn-assign = \
-$(warning "WARNING: Appending $$K$(1) ($(K$(1))) from $(origin K$(1)) to kernel $$$(1)")
-
-ifneq ($(KCPPFLAGS),)
-        $(call warn-assign,CPPFLAGS)
-        KBUILD_CPPFLAGS += $(KCPPFLAGS)
-endif
-ifneq ($(KAFLAGS),)
-        $(call warn-assign,AFLAGS)
-        KBUILD_AFLAGS += $(KAFLAGS)
-endif
-ifneq ($(KCFLAGS),)
-        $(call warn-assign,CFLAGS)
-        KBUILD_CFLAGS += $(KCFLAGS)
-endif
+KBUILD_CPPFLAGS += $(KCPPFLAGS)
+KBUILD_AFLAGS += $(KAFLAGS)
+KBUILD_CFLAGS += $(KCFLAGS)
 
 # Use --build-id when available.
 LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\
@@ -714,6 +719,17 @@ endif # INSTALL_MOD_STRIP
 export mod_strip_cmd
 
 
+ifeq ($(CONFIG_MODULE_SIG),y)
+MODSECKEY = ./signing_key.priv
+MODPUBKEY = ./signing_key.x509
+export MODPUBKEY
+mod_sign_cmd = perl $(srctree)/scripts/sign-file $(MODSECKEY) $(MODPUBKEY)
+else
+mod_sign_cmd = true
+endif
+export mod_sign_cmd
+
+
 ifeq ($(KBUILD_EXTMOD),)
 core-y         += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
 
@@ -796,8 +812,8 @@ prepare3: include/config/kernel.release
 ifneq ($(KBUILD_SRC),)
        @$(kecho) '  Using $(srctree) as source for kernel'
        $(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \
-               echo "  $(srctree) is not clean, please run 'make mrproper'"; \
-               echo "  in the '$(srctree)' directory.";\
+               echo >&2 "  $(srctree) is not clean, please run 'make mrproper'"; \
+               echo >&2 "  in the '$(srctree)' directory.";\
                /bin/false; \
        fi;
 endif
@@ -805,7 +821,7 @@ endif
 # prepare2 creates a makefile if using a separate output directory
 prepare2: prepare3 outputmakefile asm-generic
 
-prepare1: prepare2 include/linux/version.h include/generated/utsrelease.h \
+prepare1: prepare2 $(version_h) include/generated/utsrelease.h \
                    include/config/auto.conf
        $(cmd_crmodverdir)
 
@@ -838,7 +854,7 @@ define filechk_version.h
        echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';)
 endef
 
-include/linux/version.h: $(srctree)/Makefile FORCE
+$(version_h): $(srctree)/Makefile FORCE
        $(call filechk,version.h)
 
 include/generated/utsrelease.h: include/config/kernel.release FORCE
@@ -883,7 +899,7 @@ PHONY += archscripts
 archscripts:
 
 PHONY += __headers
-__headers: include/linux/version.h scripts_basic asm-generic archheaders archscripts FORCE
+__headers: $(version_h) scripts_basic asm-generic archheaders archscripts FORCE
        $(Q)$(MAKE) $(build)=scripts build_unifdef
 
 PHONY += headers_install_all
@@ -892,10 +908,10 @@ headers_install_all:
 
 PHONY += headers_install
 headers_install: __headers
-       $(if $(wildcard $(srctree)/arch/$(hdr-arch)/include/asm/Kbuild),, \
-       $(error Headers not exportable for the $(SRCARCH) architecture))
-       $(Q)$(MAKE) $(hdr-inst)=include
-       $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/asm $(hdr-dst)
+       $(if $(wildcard $(srctree)/arch/$(hdr-arch)/include/uapi/asm/Kbuild),, \
+         $(error Headers not exportable for the $(SRCARCH) architecture))
+       $(Q)$(MAKE) $(hdr-inst)=include/uapi
+       $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi/asm $(hdr-dst)
 
 PHONY += headers_check_all
 headers_check_all: headers_install_all
@@ -903,8 +919,8 @@ headers_check_all: headers_install_all
 
 PHONY += headers_check
 headers_check: headers_install
-       $(Q)$(MAKE) $(hdr-inst)=include HDRCHECK=1
-       $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/asm $(hdr-dst) HDRCHECK=1
+       $(Q)$(MAKE) $(hdr-inst)=include/uapi HDRCHECK=1
+       $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi/asm $(hdr-dst) HDRCHECK=1
 
 # ---------------------------------------------------------------------------
 # Modules
@@ -971,11 +987,11 @@ else # CONFIG_MODULES
 # ---------------------------------------------------------------------------
 
 modules modules_install: FORCE
-       @echo
-       @echo "The present kernel configuration has modules disabled."
-       @echo "Type 'make config' and enable loadable module support."
-       @echo "Then build a kernel with module support enabled."
-       @echo
+       @echo >&2
+       @echo >&2 "The present kernel configuration has modules disabled."
+       @echo >&2 "Type 'make config' and enable loadable module support."
+       @echo >&2 "Then build a kernel with module support enabled."
+       @echo >&2
        @exit 1
 
 endif # CONFIG_MODULES
@@ -993,9 +1009,11 @@ CLEAN_DIRS  += $(MODVERDIR)
 # Directories & files removed with 'make mrproper'
 MRPROPER_DIRS  += include/config usr/include include/generated          \
                   arch/*/include/generated
-MRPROPER_FILES += .config .config.old .version .old_version             \
-                  include/linux/version.h                               \
-                 Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS
+MRPROPER_FILES += .config .config.old .version .old_version $(version_h) \
+                 Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS \
+                 signing_key.priv signing_key.x509 x509.genkey         \
+                 extra_certificates signing_key.x509.keyid             \
+                 signing_key.x509.signer
 
 # clean - Delete most, but leave enough to build external modules
 #
@@ -1239,6 +1257,7 @@ clean: $(clean-dirs)
        $(call cmd,rmfiles)
        @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
                \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
+               -o -name '*.ko.*' \
                -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
                -o -name '*.symtypes' -o -name 'modules.order' \
                -o -name modules.builtin -o -name '.tmp_*.o.*' \
@@ -1302,10 +1321,12 @@ kernelversion:
 
 # Clear a bunch of variables before executing the submake
 tools/: FORCE
-       $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= -C $(src)/tools/
+       $(Q)mkdir -p $(objtree)/tools
+       $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= O=$(objtree) subdir=tools -C $(src)/tools/
 
 tools/%: FORCE
-       $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= -C $(src)/tools/ $*
+       $(Q)mkdir -p $(objtree)/tools
+       $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= O=$(objtree) subdir=tools -C $(src)/tools/ $*
 
 # Single targets
 # ---------------------------------------------------------------------------
index cebd46b7d860f58c014e25f615075920fade1ec5..3d87ce199d0032571691fc5e715282f2d832f85b 100644 (file)
@@ -1,3 +1,3 @@
 
-kconfig taken from vanilla Linux 3.5, and slightly patched.
+kconfig taken from vanilla Linux 3.7, and slightly patched.
 
index 6a3ee981931d3c2b4438cff1d220ec2e8039bd7e..978416dd31ca0efeacfd938e961b241aca7633af 100644 (file)
@@ -98,24 +98,24 @@ try-run = $(shell set -e;           \
 # Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,)
 
 as-option = $(call try-run,\
-       $(CC) $(KBUILD_CFLAGS) $(1) -c -xassembler /dev/null -o "$$TMP",$(1),$(2))
+       $(CC) $(KBUILD_CFLAGS) $(1) -c -x assembler /dev/null -o "$$TMP",$(1),$(2))
 
 # as-instr
 # Usage: cflags-y += $(call as-instr,instr,option1,option2)
 
 as-instr = $(call try-run,\
-       printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" -,$(2),$(3))
+       printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3))
 
 # cc-option
 # Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)
 
 cc-option = $(call try-run,\
-       $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",$(1),$(2))
+       $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2))
 
 # cc-option-yn
 # Usage: flag := $(call cc-option-yn,-march=winchip-c6)
 cc-option-yn = $(call try-run,\
-       $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",y,n)
+       $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n)
 
 # cc-option-align
 # Prefix align with either -falign or -malign
@@ -125,7 +125,7 @@ cc-option-align = $(subst -functions=0,,\
 # cc-disable-warning
 # Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable)
 cc-disable-warning = $(call try-run,\
-       $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -xc /dev/null -o "$$TMP",-Wno-$(strip $(1)))
+       $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1)))
 
 # cc-version
 # Usage gcc-ver := $(call cc-version)
@@ -143,7 +143,7 @@ cc-ifversion = $(shell [ $(call cc-version, $(CC)) $(1) $(2) ] && echo $(3))
 # cc-ldoption
 # Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both)
 cc-ldoption = $(call try-run,\
-       $(CC) $(1) -nostdlib -xc /dev/null -o "$$TMP",$(1),$(2))
+       $(CC) $(1) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2))
 
 # ld-option
 # Usage: LDFLAGS += $(call ld-option, -X)
@@ -209,7 +209,7 @@ endif
 # >$< substitution to preserve $ when reloading .cmd file
 # note: when using inline perl scripts [perl -e '...$$t=1;...']
 # in $(cmd_xxx) double $$ your perl vars
-make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))
+make-cmd = $(subst \\,\\\\,$(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))))
 
 # Find any prerequisites that is newer than target or that does not exist.
 # PHONY targets skipped in both cases.
index a55b0067758a0fb5b35115dbc5f1affa35e69719..01e7adb838d93287d391ec4fee925936115877c1 100644 (file)
@@ -16,8 +16,10 @@ hostprogs-$(CONFIG_VT)           += conmakehash
 hostprogs-$(CONFIG_IKCONFIG)     += bin2c
 hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount
 hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable
+hostprogs-$(CONFIG_ASN1)        += asn1_compiler
 
 HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include
+HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include
 
 always         := $(hostprogs-y) $(hostprogs-m)
 
index ff1720d28d0c80be0df2e1d0ae8f5697794e36e9..0e801c3cdaf8f4173ce5abbf9cee0554374bfbc7 100644 (file)
@@ -354,6 +354,17 @@ quiet_cmd_cpp_lds_S = LDS     $@
 $(obj)/%.lds: $(src)/%.lds.S FORCE
        $(call if_changed_dep,cpp_lds_S)
 
+# ASN.1 grammar
+# ---------------------------------------------------------------------------
+quiet_cmd_asn1_compiler = ASN.1   $@
+      cmd_asn1_compiler = $(objtree)/scripts/asn1_compiler $< \
+                               $(subst .h,.c,$@) $(subst .c,.h,$@)
+
+.PRECIOUS: $(objtree)/$(obj)/%-asn1.c $(objtree)/$(obj)/%-asn1.h
+
+$(obj)/%-asn1.c $(obj)/%-asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
+       $(call cmd,asn1_compiler)
+
 # Build the compiled-in targets
 # ---------------------------------------------------------------------------
 
index d3bae5e7b6018d7429c518681a706179e00c6d81..06ba4a70bd4d0db666a4b50b90b73f33e7c6b81e 100644 (file)
@@ -3,13 +3,12 @@
 #
 # header-y  - list files to be installed. They are preprocessed
 #             to remove __KERNEL__ section of the file
-# objhdr-y  - Same as header-y but for generated files
-# genhdr-y  - Same as objhdr-y but in a generated/ directory
+# genhdr-y  - Same as header-y but in a generated/ directory
 #
 # ==========================================================================
 
 # called may set destination dir (when installing to asm/)
-_dst := $(if $(dst),$(dst),$(obj))
+_dst := $(or $(destination-y),$(dst),$(obj))
 
 # generated header directory
 gen := $(if $(gen),$(gen),$(subst include/,include/generated/,$(obj)))
@@ -17,49 +16,64 @@ gen := $(if $(gen),$(gen),$(subst include/,include/generated/,$(obj)))
 kbuild-file := $(srctree)/$(obj)/Kbuild
 include $(kbuild-file)
 
-_dst := $(if $(destination-y),$(destination-y),$(_dst))
+old-kbuild-file := $(srctree)/$(subst uapi/,,$(obj))/Kbuild
+ifneq ($(wildcard $(old-kbuild-file)),)
+include $(old-kbuild-file)
+endif
 
 include scripts/Kbuild.include
 
-install       := $(INSTALL_HDR_PATH)/$(_dst)
+installdir    := $(INSTALL_HDR_PATH)/$(subst uapi/,,$(_dst))
 
 header-y      := $(sort $(header-y))
 subdirs       := $(patsubst %/,%,$(filter %/, $(header-y)))
 header-y      := $(filter-out %/, $(header-y))
 
 # files used to track state of install/check
-install-file  := $(install)/.install
-check-file    := $(install)/.check
+install-file  := $(installdir)/.install
+check-file    := $(installdir)/.check
 
 # generic-y list all files an architecture uses from asm-generic
 # Use this to build a list of headers which require a wrapper
 wrapper-files := $(filter $(header-y), $(generic-y))
 
+srcdir        := $(srctree)/$(obj)
+gendir        := $(objtree)/$(gen)
+
+oldsrcdir     := $(srctree)/$(subst /uapi,,$(obj))
+
 # all headers files for this dir
 header-y      := $(filter-out $(generic-y), $(header-y))
-all-files     := $(header-y) $(objhdr-y) $(genhdr-y) $(wrapper-files)
-input-files   := $(addprefix $(srctree)/$(obj)/,$(header-y)) \
-                 $(addprefix $(objtree)/$(obj)/,$(objhdr-y)) \
-                 $(addprefix $(objtree)/$(gen)/,$(genhdr-y))
-output-files  := $(addprefix $(install)/, $(all-files))
+all-files     := $(header-y) $(genhdr-y) $(wrapper-files)
+output-files  := $(addprefix $(installdir)/, $(all-files))
+
+input-files   := $(foreach hdr, $(header-y), \
+                  $(or \
+                       $(wildcard $(srcdir)/$(hdr)), \
+                       $(wildcard $(oldsrcdir)/$(hdr)), \
+                       $(error Missing UAPI file $(srcdir)/$(hdr)) \
+                  )) \
+                $(foreach hdr, $(genhdr-y), \
+                  $(or \
+                       $(wildcard $(gendir)/$(hdr)), \
+                       $(error Missing generated UAPI file $(gendir)/$(hdr)) \
+                  ))
 
 # Work out what needs to be removed
-oldheaders    := $(patsubst $(install)/%,%,$(wildcard $(install)/*.h))
+oldheaders    := $(patsubst $(installdir)/%,%,$(wildcard $(installdir)/*.h))
 unwanted      := $(filter-out $(all-files),$(oldheaders))
 
 # Prefix unwanted with full paths to $(INSTALL_HDR_PATH)
-unwanted-file := $(addprefix $(install)/, $(unwanted))
+unwanted-file := $(addprefix $(installdir)/, $(unwanted))
 
 printdir = $(patsubst $(INSTALL_HDR_PATH)/%/,%,$(dir $@))
 
 quiet_cmd_install = INSTALL $(printdir) ($(words $(all-files))\
                             file$(if $(word 2, $(all-files)),s))
       cmd_install = \
-        $(PERL) $< $(srctree)/$(obj) $(install) $(SRCARCH) $(header-y); \
-        $(PERL) $< $(objtree)/$(obj) $(install) $(SRCARCH) $(objhdr-y); \
-        $(PERL) $< $(objtree)/$(gen) $(install) $(SRCARCH) $(genhdr-y); \
+        $(PERL) $< $(installdir) $(SRCARCH) $(input-files); \
         for F in $(wrapper-files); do                                   \
-                echo "\#include <asm-generic/$$F>" > $(install)/$$F;    \
+                echo "\#include <asm-generic/$$F>" > $(installdir)/$$F;    \
         done;                                                           \
         touch $@
 
@@ -70,7 +84,7 @@ quiet_cmd_check = CHECK   $(printdir) ($(words $(all-files)) files)
 # Headers list can be pretty long, xargs helps to avoid
 # the "Argument list too long" error.
       cmd_check = for f in $(all-files); do                          \
-                  echo "$(install)/$${f}"; done                      \
+                  echo "$(installdir)/$${f}"; done                      \
                   | xargs                                            \
                   $(PERL) $< $(INSTALL_HDR_PATH)/include $(SRCARCH); \
                  touch $@
index efa5d940e6324caa0aa120343043b89475502e74..ecbb44797e28226e85027c277435d053415aec8c 100644 (file)
@@ -9,15 +9,16 @@ include scripts/Kbuild.include
 
 #
 
-__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
+__modules := $(sort $(shell grep -h '\.ko$$' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
 modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o)))
 
 PHONY += $(modules)
 __modinst: $(modules)
        @:
 
+# Don't stop modules_install if we can't sign external modules.
 quiet_cmd_modules_install = INSTALL $@
-      cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@)
+      cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@) $(patsubst %,|| true,$(KBUILD_EXTMOD))
 
 # Modules built outside the kernel source tree go into extra by default
 INSTALL_MOD_DIR ?= extra
index 08dce14f2dc862d78d30744e0e7cd7b4e915cc64..a1cb0222ebe642b6fd91093f2a01bd301b026e6e 100644 (file)
@@ -60,7 +60,7 @@ kernelsymfile := $(objtree)/Module.symvers
 modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers
 
 # Step 1), find all modules listed in $(MODVERDIR)/
-__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
+__modules := $(sort $(shell grep -h '\.ko$$' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
 modules   := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o)))
 
 # Stop after building .o files if NOFINAL is set. Makes compile tests quicker
diff --git a/kernel/fiasco/tool/kconfig/scripts/basic/.gitignore b/kernel/fiasco/tool/kconfig/scripts/basic/.gitignore
new file mode 100644 (file)
index 0000000..a776371
--- /dev/null
@@ -0,0 +1 @@
+fixdep
index ee120d441565422f0a6283b55ab5258fb61de9e7..be603c4fef624669ea2bac84e1f41311713a8065 100644 (file)
@@ -7,7 +7,6 @@ config*
 *.tab.h
 zconf.hash.c
 *.moc
-lkc_defs.h
 gconf.glade.h
 *.pot
 *.mo
index 79662658fb9158af1d7b3ee43dba0cfab0aa42cf..3091794e935488c797e73207e6d0b82a7dbf99b4 100644 (file)
@@ -76,11 +76,17 @@ PHONY += allnoconfig allyesconfig allmodconfig alldefconfig randconfig
 allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf
        $< --$@ $(Kconfig)
 
-PHONY += listnewconfig oldnoconfig savedefconfig defconfig
+PHONY += listnewconfig olddefconfig oldnoconfig savedefconfig defconfig
 
-listnewconfig oldnoconfig: $(obj)/conf
+listnewconfig olddefconfig: $(obj)/conf
        $< --$@ $(Kconfig)
 
+# oldnoconfig is an alias of olddefconfig, because people already are dependent
+# on its behavior(sets new symbols to their default value but not 'n') with the
+# counter-intuitive name.
+oldnoconfig: $(obj)/conf
+       $< --olddefconfig $(Kconfig)
+
 savedefconfig: $(obj)/conf
        $< --$@=defconfig $(Kconfig)
 
@@ -114,7 +120,7 @@ help:
        @echo  '  alldefconfig    - New config with all symbols set to default'
        @echo  '  randconfig      - New config with random answer to all options'
        @echo  '  listnewconfig   - List new options'
-       @echo  '  oldnoconfig     - Same as silentoldconfig but set new symbols to n (unset)'
+       @echo  '  olddefconfig    - Same as silentoldconfig but sets new symbols to their default value'
 
 # lxdialog stuff
 check-lxdialog  := $(srctree)/$(src)/lxdialog/check-lxdialog.sh
@@ -234,12 +240,12 @@ $(obj)/.tmp_qtcheck:
                if [ -f $$d/include/qconfig.h ]; then dir=$$d; break; fi; \
              done; \
              if [ -z "$$dir" ]; then \
-               echo "*"; \
-               echo "* Unable to find any QT installation. Please make sure that"; \
-               echo "* the QT4 or QT3 development package is correctly installed and"; \
-               echo "* either qmake can be found or install pkg-config or set"; \
-               echo "* the QTDIR environment variable to the correct location."; \
-               echo "*"; \
+               echo >&2 "*"; \
+               echo >&2 "* Unable to find any QT installation. Please make sure that"; \
+               echo >&2 "* the QT4 or QT3 development package is correctly installed and"; \
+               echo >&2 "* either qmake can be found or install pkg-config or set"; \
+               echo >&2 "* the QTDIR environment variable to the correct location."; \
+               echo >&2 "*"; \
                false; \
              fi; \
              libpath=$$dir/lib; lib=qt; osdir=""; \
@@ -260,8 +266,8 @@ $(obj)/.tmp_qtcheck:
        else \
          cflags="\$$(shell pkg-config QtCore QtGui Qt3Support --cflags)"; \
          libs="\$$(shell pkg-config QtCore QtGui Qt3Support --libs)"; \
-         binpath="\$$(shell pkg-config QtCore --variable=prefix)"; \
-         moc="$$binpath/bin/moc"; \
+         moc="\$$(shell pkg-config QtCore --variable=moc_location)"; \
+         [ -n "$$moc" ] || moc="\$$(shell pkg-config QtCore --variable=prefix)/bin/moc"; \
        fi; \
        echo "KC_QT_CFLAGS=$$cflags" > $@; \
        echo "KC_QT_LIBS=$$libs" >> $@; \
@@ -279,17 +285,17 @@ $(obj)/.tmp_gtkcheck:
                if `pkg-config --atleast-version=2.0.0 gtk+-2.0`; then                  \
                        touch $@;                                                               \
                else                                                                    \
-                       echo "*";                                                       \
-                       echo "* GTK+ is present but version >= 2.0.0 is required.";     \
-                       echo "*";                                                       \
+                       echo >&2 "*";                                                   \
+                       echo >&2 "* GTK+ is present but version >= 2.0.0 is required."; \
+                       echo >&2 "*";                                                   \
                        false;                                                          \
                fi                                                                      \
        else                                                                            \
-               echo "*";                                                               \
-               echo "* Unable to find the GTK+ installation. Please make sure that";   \
-               echo "* the GTK+ 2.0 development package is correctly installed...";    \
-               echo "* You need gtk+-2.0, glib-2.0 and libglade-2.0.";                 \
-               echo "*";                                                               \
+               echo >&2 "*";                                                           \
+               echo >&2 "* Unable to find the GTK+ installation. Please make sure that";       \
+               echo >&2 "* the GTK+ 2.0 development package is correctly installed...";        \
+               echo >&2 "* You need gtk+-2.0, glib-2.0 and libglade-2.0.";             \
+               echo >&2 "*";                                                           \
                false;                                                                  \
        fi
 endif
@@ -298,8 +304,11 @@ $(obj)/zconf.tab.o: $(obj)/zconf.lex.c $(obj)/zconf.hash.c
 
 $(obj)/qconf.o: $(obj)/qconf.moc
 
-$(obj)/%.moc: $(src)/%.h
-       $(KC_QT_MOC) -i $< -o $@
+quiet_cmd_moc = MOC     $@
+      cmd_moc = $(KC_QT_MOC) -i $< -o $@
+
+$(obj)/%.moc: $(src)/%.h $(obj)/.tmp_qtcheck
+       $(call cmd,moc)
 
 # Extract gconf menu items for I18N support
 $(obj)/gconf.glade.h: $(obj)/gconf.glade
index fa59cbf9d62cf464515662c8ae1e98e82eafc99d..854d9c7c675ca4782702e83e1fa04b17aa47d6f8 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 # Needed for systems without gettext
-$* -xc -o /dev/null - > /dev/null 2>&1 << EOF
+$* -x c -o /dev/null - > /dev/null 2>&1 << EOF
 #include <libintl.h>
 int main()
 {
index 0dc4a2c779b119ec51e2eb5b3f17c5a4d02645fb..4da3b4adfad233cb97728b0e0278f8143919cee3 100644 (file)
@@ -32,7 +32,7 @@ enum input_mode {
        defconfig,
        savedefconfig,
        listnewconfig,
-       oldnoconfig,
+       olddefconfig,
 } input_mode = oldaskconfig;
 
 static int indent = 1;
@@ -365,7 +365,7 @@ static void conf(struct menu *menu)
                case P_MENU:
                        if ((input_mode == silentoldconfig ||
                             input_mode == listnewconfig ||
-                            input_mode == oldnoconfig) &&
+                            input_mode == olddefconfig) &&
                            rootEntry != menu) {
                                check_conf(menu);
                                return;
@@ -429,7 +429,7 @@ static void check_conf(struct menu *menu)
                                if (sym->name && !sym_is_choice_value(sym)) {
                                        printf("%s%s\n", CONFIG_, sym->name);
                                }
-                       } else if (input_mode != oldnoconfig) {
+                       } else if (input_mode != olddefconfig) {
                                if (!conf_cnt++)
                                        printf(_("*\n* Restart config...\n*\n"));
                                rootEntry = menu_get_parent_menu(menu);
@@ -454,7 +454,13 @@ static struct option long_opts[] = {
        {"alldefconfig",    no_argument,       NULL, alldefconfig},
        {"randconfig",      no_argument,       NULL, randconfig},
        {"listnewconfig",   no_argument,       NULL, listnewconfig},
-       {"oldnoconfig",     no_argument,       NULL, oldnoconfig},
+       {"olddefconfig",    no_argument,       NULL, olddefconfig},
+       /*
+        * oldnoconfig is an alias of olddefconfig, because people already
+        * are dependent on its behavior(sets new symbols to their default
+        * value but not 'n') with the counter-intuitive name.
+        */
+       {"oldnoconfig",     no_argument,       NULL, olddefconfig},
        {NULL, 0, NULL, 0}
 };
 
@@ -467,7 +473,8 @@ static void conf_usage(const char *progname)
        printf("  --oldaskconfig          Start a new configuration using a line-oriented program\n");
        printf("  --oldconfig             Update a configuration using a provided .config as base\n");
        printf("  --silentoldconfig       Same as oldconfig, but quietly, additionally update deps\n");
-       printf("  --oldnoconfig           Same as silentoldconfig but set new symbols to no\n");
+       printf("  --olddefconfig          Same as silentoldconfig but sets new symbols to their default value\n");
+       printf("  --oldnoconfig           An alias of olddefconfig\n");
        printf("  --defconfig <file>      New config with default defined in <file>\n");
        printf("  --savedefconfig <file>  Save the minimal current configuration to <file>\n");
        printf("  --allnoconfig           New config where all options are answered with no\n");
@@ -520,7 +527,7 @@ int main(int ac, char **av)
                case allmodconfig:
                case alldefconfig:
                case listnewconfig:
-               case oldnoconfig:
+               case olddefconfig:
                        break;
                case '?':
                        conf_usage(progname);
@@ -565,7 +572,7 @@ int main(int ac, char **av)
        case oldaskconfig:
        case oldconfig:
        case listnewconfig:
-       case oldnoconfig:
+       case olddefconfig:
                conf_read(NULL);
                break;
        case allnoconfig:
@@ -645,7 +652,7 @@ int main(int ac, char **av)
                /* fall through */
        case oldconfig:
        case listnewconfig:
-       case oldnoconfig:
+       case olddefconfig:
        case silentoldconfig:
                /* Update until a loop caused no more changes */
                do {
@@ -653,7 +660,7 @@ int main(int ac, char **av)
                        check_conf(&rootmenu);
                } while (conf_cnt &&
                         (input_mode != listnewconfig &&
-                         input_mode != oldnoconfig));
+                         input_mode != olddefconfig));
                break;
        }
 
index bcc2719d9c1222207370a9ca4f796837098d2636..13d89e32a14895c7c5a5a134327489c6d085d840 100644 (file)
@@ -182,10 +182,66 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
        return 0;
 }
 
+#define LINE_GROWTH 16
+static int add_byte(int c, char **lineptr, size_t slen, size_t *n)
+{
+       char *nline;
+       size_t new_size = slen + 1;
+       if (new_size > *n) {
+               new_size += LINE_GROWTH - 1;
+               new_size *= 2;
+               nline = realloc(*lineptr, new_size);
+               if (!nline)
+                       return -1;
+
+               *lineptr = nline;
+               *n = new_size;
+       }
+
+       (*lineptr)[slen] = c;
+
+       return 0;
+}
+
+static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream)
+{
+       char *line = *lineptr;
+       size_t slen = 0;
+
+       for (;;) {
+               int c = getc(stream);
+
+               switch (c) {
+               case '\n':
+                       if (add_byte(c, &line, slen, n) < 0)
+                               goto e_out;
+                       slen++;
+                       /* fall through */
+               case EOF:
+                       if (add_byte('\0', &line, slen, n) < 0)
+                               goto e_out;
+                       *lineptr = line;
+                       if (slen == 0)
+                               return -1;
+                       return slen;
+               default:
+                       if (add_byte(c, &line, slen, n) < 0)
+                               goto e_out;
+                       slen++;
+               }
+       }
+
+e_out:
+       line[slen-1] = '\0';
+       *lineptr = line;
+       return -1;
+}
+
 int conf_read_simple(const char *name, int def)
 {
        FILE *in = NULL;
-       char line[1024];
+       char   *line = NULL;
+       size_t  line_asize = 0;
        char *p, *p2;
        struct symbol *sym;
        int i, def_flags;
@@ -247,7 +303,7 @@ load:
                }
        }
 
-       while (fgets(line, sizeof(line), in)) {
+       while (compat_getline(&line, &line_asize, in) != -1) {
                conf_lineno++;
                sym = NULL;
                if (line[0] == '#') {
@@ -335,6 +391,7 @@ setsym:
                        cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);
                }
        }
+       free(line);
        fclose(in);
 
        if (modules_sym)
index d4ecce8bc3a689daa2157e4f47e65e7c62192bd4..cdd48600e02a9bd842f2e43ab6b7f263949451ec 100644 (file)
@@ -12,6 +12,7 @@ extern "C" {
 
 #include <assert.h>
 #include <stdio.h>
+#include "list.h"
 #ifndef __cplusplus
 #include <stdbool.h>
 #endif
@@ -173,6 +174,15 @@ struct menu {
 #define MENU_CHANGED           0x0001
 #define MENU_ROOT              0x0002
 
+struct jump_key {
+       struct list_head entries;
+       size_t offset;
+       struct menu *target;
+       int index;
+};
+
+#define JUMP_NB                        9
+
 extern struct file *file_list;
 extern struct file *current_file;
 struct file *lookup_file(const char *name);
diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/list.h b/kernel/fiasco/tool/kconfig/scripts/kconfig/list.h
new file mode 100644 (file)
index 0000000..0ae730b
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef LIST_H
+#define LIST_H
+
+/*
+ * Copied from include/linux/...
+ */
+
+#undef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr:        the pointer to the member.
+ * @type:       the type of the container struct this is embedded in.
+ * @member:     the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({                      \
+       const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
+       (type *)( (char *)__mptr - offsetof(type,member) );})
+
+
+struct list_head {
+       struct list_head *next, *prev;
+};
+
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+       struct list_head name = LIST_HEAD_INIT(name)
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:       the &struct list_head pointer.
+ * @type:      the type of the struct this is embedded in.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+       container_of(ptr, type, member)
+
+/**
+ * list_for_each_entry -       iterate over list of given type
+ * @pos:       the type * to use as a loop cursor.
+ * @head:      the head for your list.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member)                         \
+       for (pos = list_entry((head)->next, typeof(*pos), member);      \
+            &pos->member != (head);    \
+            pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(const struct list_head *head)
+{
+       return head->next == head;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *_new,
+                             struct list_head *prev,
+                             struct list_head *next)
+{
+       next->prev = _new;
+       _new->next = next;
+       _new->prev = prev;
+       prev->next = _new;
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *_new, struct list_head *head)
+{
+       __list_add(_new, head->prev, head);
+}
+
+#endif
index 47fe9c340f9a20b9b6bd9871d18d79ea9ddc7d1d..ef1a7381f956d5e7d0ebb8d3ba6af2361a0c3c74 100644 (file)
@@ -21,8 +21,10 @@ P(menu_get_root_menu,struct menu *,(struct menu *menu));
 P(menu_get_parent_menu,struct menu *,(struct menu *menu));
 P(menu_has_help,bool,(struct menu *menu));
 P(menu_get_help,const char *,(struct menu *menu));
-P(get_symbol_str, void, (struct gstr *r, struct symbol *sym));
-P(get_relations_str, struct gstr, (struct symbol **sym_arr));
+P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct list_head
+                        *head));
+P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct list_head
+                                  *head));
 P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help));
 
 /* symbol.c */
index 82cc3a85e7f885e2c7ab52aa99a6f76242899aa5..c8e8a7154753b858e9f51e9c3d6816962d8f549b 100644 (file)
@@ -4,7 +4,7 @@
 # What library to link
 ldflags()
 {
-       for ext in so a dylib ; do
+       for ext in so a dll.a dylib ; do
                for lib in ncursesw ncurses curses ; do
                        $cc -print-file-name=lib${lib}.${ext} | grep -q /
                        if [ $? -eq 0 ]; then
@@ -19,12 +19,12 @@ ldflags()
 # Where is ncurses.h?
 ccflags()
 {
-       if [ -f /usr/include/ncurses/ncurses.h ]; then
+       if [ -f /usr/include/ncursesw/curses.h ]; then
+               echo '-I/usr/include/ncursesw -DCURSES_LOC="<ncursesw/curses.h>"'
+       elif [ -f /usr/include/ncurses/ncurses.h ]; then
                echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"'
        elif [ -f /usr/include/ncurses/curses.h ]; then
                echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"'
-       elif [ -f /usr/include/ncursesw/curses.h ]; then
-               echo '-I/usr/include/ncursesw -DCURSES_LOC="<ncursesw/curses.h>"'
        elif [ -f /usr/include/ncurses.h ]; then
                echo '-DCURSES_LOC="<ncurses.h>"'
        else
@@ -38,7 +38,7 @@ trap "rm -f $tmp" 0 1 2 3 15
 
 # Check if we can link to ncurses
 check() {
-        $cc -xc - -o $tmp 2>/dev/null <<'EOF'
+        $cc -x c - -o $tmp 2>/dev/null <<'EOF'
 #include CURSES_LOC
 main() {}
 EOF
index b5211fce0d946ab90eaf1ba239f3b20b40039b11..ee17a5264d5b456c0672a77b06964bfc1ccd29d7 100644 (file)
@@ -144,6 +144,7 @@ struct dialog_info {
  */
 extern struct dialog_info dlg;
 extern char dialog_input_result[];
+extern int saved_x, saved_y;           /* Needed in signal handler in mconf.c */
 
 /*
  * Function prototypes
@@ -209,7 +210,13 @@ int first_alpha(const char *string, const char *exempt);
 int dialog_yesno(const char *title, const char *prompt, int height, int width);
 int dialog_msgbox(const char *title, const char *prompt, int height,
                  int width, int pause);
-int dialog_textbox(const char *title, const char *file, int height, int width);
+
+
+typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void
+                              *_data);
+int dialog_textbox(const char *title, char *tbuf, int initial_height,
+                  int initial_width, int *keys, int *_vscroll, int *_hscroll,
+                  update_text_fn update_text, void *data);
 int dialog_menu(const char *title, const char *prompt,
                const void *selected, int *s_scroll);
 int dialog_checklist(const char *title, const char *prompt, int height,
index 154c2dd245b77536de60fd344d46e49dfbe41520..a48bb93e09073f05ea14786fea9370202f5039f9 100644 (file)
 #include "dialog.h"
 
 static void back_lines(int n);
-static void print_page(WINDOW * win, int height, int width);
-static void print_line(WINDOW * win, int row, int width);
+static void print_page(WINDOW *win, int height, int width, update_text_fn
+                      update_text, void *data);
+static void print_line(WINDOW *win, int row, int width);
 static char *get_line(void);
 static void print_position(WINDOW * win);
 
 static int hscroll;
 static int begin_reached, end_reached, page_length;
-static const char *buf;
-static const char *page;
+static char *buf;
+static char *page;
 
 /*
  * refresh window content
  */
 static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
-                                                         int cur_y, int cur_x)
+                            int cur_y, int cur_x, update_text_fn update_text,
+                            void *data)
 {
-       print_page(box, boxh, boxw);
+       print_page(box, boxh, boxw, update_text, data);
        print_position(dialog);
        wmove(dialog, cur_y, cur_x);    /* Restore cursor position */
        wrefresh(dialog);
@@ -47,14 +49,18 @@ static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
 
 /*
  * Display text from a file in a dialog box.
+ *
+ * keys is a null-terminated array
+ * update_text() may not add or remove any '\n' or '\0' in tbuf
  */
-int dialog_textbox(const char *title, const char *tbuf,
-                  int initial_height, int initial_width)
+int dialog_textbox(const char *title, char *tbuf, int initial_height,
+                  int initial_width, int *keys, int *_vscroll, int *_hscroll,
+                  update_text_fn update_text, void *data)
 {
        int i, x, y, cur_x, cur_y, key = 0;
        int height, width, boxh, boxw;
-       int passed_end;
        WINDOW *dialog, *box;
+       bool done = false;
 
        begin_reached = 1;
        end_reached = 0;
@@ -63,6 +69,15 @@ int dialog_textbox(const char *title, const char *tbuf,
        buf = tbuf;
        page = buf;     /* page is pointer to start of page to be displayed */
 
+       if (_vscroll && *_vscroll) {
+               begin_reached = 0;
+
+               for (i = 0; i < *_vscroll; i++)
+                       get_line();
+       }
+       if (_hscroll)
+               hscroll = *_hscroll;
+
 do_resize:
        getmaxyx(stdscr, height, width);
        if (height < 8 || width < 8)
@@ -120,25 +135,28 @@ do_resize:
 
        /* Print first page of text */
        attr_clear(box, boxh, boxw, dlg.dialog.atr);
-       refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
+       refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text,
+                        data);
 
-       while ((key != KEY_ESC) && (key != '\n')) {
+       while (!done) {
                key = wgetch(dialog);
                switch (key) {
                case 'E':       /* Exit */
                case 'e':
                case 'X':
                case 'x':
-                       delwin(box);
-                       delwin(dialog);
-                       return 0;
+               case 'q':
+               case '\n':
+                       done = true;
+                       break;
                case 'g':       /* First page */
                case KEY_HOME:
                        if (!begin_reached) {
                                begin_reached = 1;
                                page = buf;
                                refresh_text_box(dialog, box, boxh, boxw,
-                                                cur_y, cur_x);
+                                                cur_y, cur_x, update_text,
+                                                data);
                        }
                        break;
                case 'G':       /* Last page */
@@ -148,78 +166,48 @@ do_resize:
                        /* point to last char in buf */
                        page = buf + strlen(buf);
                        back_lines(boxh);
-                       refresh_text_box(dialog, box, boxh, boxw,
-                                        cur_y, cur_x);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case 'K':       /* Previous line */
                case 'k':
                case KEY_UP:
-                       if (!begin_reached) {
-                               back_lines(page_length + 1);
-
-                               /* We don't call print_page() here but use
-                                * scrolling to ensure faster screen update.
-                                * However, 'end_reached' and 'page_length'
-                                * should still be updated, and 'page' should
-                                * point to start of next page. This is done
-                                * by calling get_line() in the following
-                                * 'for' loop. */
-                               scrollok(box, TRUE);
-                               wscrl(box, -1); /* Scroll box region down one line */
-                               scrollok(box, FALSE);
-                               page_length = 0;
-                               passed_end = 0;
-                               for (i = 0; i < boxh; i++) {
-                                       if (!i) {
-                                               /* print first line of page */
-                                               print_line(box, 0, boxw);
-                                               wnoutrefresh(box);
-                                       } else
-                                               /* Called to update 'end_reached' and 'page' */
-                                               get_line();
-                                       if (!passed_end)
-                                               page_length++;
-                                       if (end_reached && !passed_end)
-                                               passed_end = 1;
-                               }
+                       if (begin_reached)
+                               break;
 
-                               print_position(dialog);
-                               wmove(dialog, cur_y, cur_x);    /* Restore cursor position */
-                               wrefresh(dialog);
-                       }
+                       back_lines(page_length + 1);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case 'B':       /* Previous page */
                case 'b':
+               case 'u':
                case KEY_PPAGE:
                        if (begin_reached)
                                break;
                        back_lines(page_length + boxh);
-                       refresh_text_box(dialog, box, boxh, boxw,
-                                        cur_y, cur_x);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case 'J':       /* Next line */
                case 'j':
                case KEY_DOWN:
-                       if (!end_reached) {
-                               begin_reached = 0;
-                               scrollok(box, TRUE);
-                               scroll(box);    /* Scroll box region up one line */
-                               scrollok(box, FALSE);
-                               print_line(box, boxh - 1, boxw);
-                               wnoutrefresh(box);
-                               print_position(dialog);
-                               wmove(dialog, cur_y, cur_x);    /* Restore cursor position */
-                               wrefresh(dialog);
-                       }
+                       if (end_reached)
+                               break;
+
+                       back_lines(page_length - 1);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case KEY_NPAGE: /* Next page */
                case ' ':
+               case 'd':
                        if (end_reached)
                                break;
 
                        begin_reached = 0;
-                       refresh_text_box(dialog, box, boxh, boxw,
-                                        cur_y, cur_x);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case '0':       /* Beginning of line */
                case 'H':       /* Scroll left */
@@ -234,8 +222,8 @@ do_resize:
                                hscroll--;
                        /* Reprint current page to scroll horizontally */
                        back_lines(page_length);
-                       refresh_text_box(dialog, box, boxh, boxw,
-                                        cur_y, cur_x);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case 'L':       /* Scroll right */
                case 'l':
@@ -245,11 +233,12 @@ do_resize:
                        hscroll++;
                        /* Reprint current page to scroll horizontally */
                        back_lines(page_length);
-                       refresh_text_box(dialog, box, boxh, boxw,
-                                        cur_y, cur_x);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case KEY_ESC:
-                       key = on_key_esc(dialog);
+                       if (on_key_esc(dialog) == KEY_ESC)
+                               done = true;
                        break;
                case KEY_RESIZE:
                        back_lines(height);
@@ -257,11 +246,31 @@ do_resize:
                        delwin(dialog);
                        on_key_resize();
                        goto do_resize;
+               default:
+                       for (i = 0; keys[i]; i++) {
+                               if (key == keys[i]) {
+                                       done = true;
+                                       break;
+                               }
+                       }
                }
        }
        delwin(box);
        delwin(dialog);
-       return key;             /* ESC pressed */
+       if (_vscroll) {
+               const char *s;
+
+               s = buf;
+               *_vscroll = 0;
+               back_lines(page_length);
+               while (s < page && (s = strchr(s, '\n'))) {
+                       (*_vscroll)++;
+                       s++;
+               }
+       }
+       if (_hscroll)
+               *_hscroll = hscroll;
+       return key;
 }
 
 /*
@@ -298,12 +307,23 @@ static void back_lines(int n)
 }
 
 /*
- * Print a new page of text. Called by dialog_textbox().
+ * Print a new page of text.
  */
-static void print_page(WINDOW * win, int height, int width)
+static void print_page(WINDOW *win, int height, int width, update_text_fn
+                      update_text, void *data)
 {
        int i, passed_end = 0;
 
+       if (update_text) {
+               char *end;
+
+               for (i = 0; i < height; i++)
+                       get_line();
+               end = page;
+               back_lines(height);
+               update_text(buf, page - buf, end - buf, data);
+       }
+
        page_length = 0;
        for (i = 0; i < height; i++) {
                print_line(win, i, width);
@@ -316,7 +336,7 @@ static void print_page(WINDOW * win, int height, int width)
 }
 
 /*
- * Print a new line of text. Called by dialog_textbox() and print_page().
+ * Print a new line of text.
  */
 static void print_line(WINDOW * win, int row, int width)
 {
@@ -354,10 +374,8 @@ static char *get_line(void)
        end_reached = 0;
        while (*page != '\n') {
                if (*page == '\0') {
-                       if (!end_reached) {
-                               end_reached = 1;
-                               break;
-                       }
+                       end_reached = 1;
+                       break;
                } else if (i < MAX_LEN)
                        line[i++] = *(page++);
                else {
@@ -370,7 +388,7 @@ static char *get_line(void)
        if (i <= MAX_LEN)
                line[i] = '\0';
        if (!end_reached)
-               page++;         /* move pass '\n' */
+               page++;         /* move past '\n' */
 
        return line;
 }
index f2375ad7ebc9bf07d306fc8de611f631b36cd7bf..109d53117d223682254502b51b6414d7404852e2 100644 (file)
@@ -23,6 +23,9 @@
 
 #include "dialog.h"
 
+/* Needed in signal handler in mconf.c */
+int saved_x, saved_y;
+
 struct dialog_info dlg;
 
 static void set_mono_theme(void)
@@ -273,6 +276,10 @@ int init_dialog(const char *backtitle)
        int height, width;
 
        initscr();              /* Init curses */
+
+       /* Get current cursor position for signal handler in mconf.c */
+       getyx(stdscr, saved_y, saved_x);
+
        getmaxyx(stdscr, height, width);
        if (height < 19 || width < 80) {
                endwin();
index f606738d421d99c29f7321236e3eebcd2ac6a760..53975cf876083ecba455a7033222b2ccc3690686 100644 (file)
@@ -105,10 +105,10 @@ static const char mconf_readme[] = N_(
 "Text Box    (Help Window)\n"
 "--------\n"
 "o  Use the cursor keys to scroll up/down/left/right.  The VI editor\n"
-"   keys h,j,k,l function here as do <SPACE BAR> and <B> for those\n"
-"   who are familiar with less and lynx.\n"
+"   keys h,j,k,l function here as do <u>, <d>, <SPACE BAR> and <B> for \n"
+"   those who are familiar with less and lynx.\n"
 "\n"
-"o  Press <E>, <X>, <Enter> or <Esc><Esc> to exit.\n"
+"o  Press <E>, <X>, <q>, <Enter> or <Esc><Esc> to exit.\n"
 "\n"
 "\n"
 "Alternate Configuration Files\n"
@@ -236,16 +236,19 @@ search_help[] = N_(
        "Result:\n"
        "-----------------------------------------------------------------\n"
        "Symbol: FOO [=m]\n"
+       "Type  : tristate\n"
        "Prompt: Foo bus is used to drive the bar HW\n"
-       "Defined at drivers/pci/Kconfig:47\n"
-       "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
-       "Location:\n"
-       "  -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
-       "    -> PCI support (PCI [=y])\n"
-       "      -> PCI access mode (<choice> [=y])\n"
-       "Selects: LIBCRC32\n"
-       "Selected by: BAR\n"
+       "  Defined at drivers/pci/Kconfig:47\n"
+       "  Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
+       "  Location:\n"
+       "    -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
+       "      -> PCI support (PCI [=y])\n"
+       "(1)     -> PCI access mode (<choice> [=y])\n"
+       "  Selects: LIBCRC32\n"
+       "  Selected by: BAR\n"
        "-----------------------------------------------------------------\n"
+       "o The line 'Type:' shows the type of the configuration option for\n"
+       "  this symbol (boolean, tristate, string, ...)\n"
        "o The line 'Prompt:' shows the text used in the menu structure for\n"
        "  this symbol\n"
        "o The 'Defined at' line tell at what file / line number the symbol\n"
@@ -254,8 +257,12 @@ search_help[] = N_(
        "  this symbol to be visible in the menu (selectable)\n"
        "o The 'Location:' lines tell where in the menu structure this symbol\n"
        "  is located\n"
-       "    A location followed by a [=y] indicate that this is a selectable\n"
-       "    menu item - and current value is displayed inside brackets.\n"
+       "    A location followed by a [=y] indicates that this is a\n"
+       "    selectable menu item - and the current value is displayed inside\n"
+       "    brackets.\n"
+       "    Press the key in the (#) prefix to jump directly to that\n"
+       "    location. You will be returned to the current search results\n"
+       "    after exiting this new menu.\n"
        "o The 'Selects:' line tell what symbol will be automatically\n"
        "  selected if this symbol is selected (y or m)\n"
        "o The 'Selected by' line tell what symbol has selected this symbol\n"
@@ -273,13 +280,15 @@ static struct menu *current_menu;
 static int child_count;
 static int single_menu_mode;
 static int show_all_options;
-static int saved_x, saved_y;
 
-static void conf(struct menu *menu);
+static void conf(struct menu *menu, struct menu *active_menu);
 static void conf_choice(struct menu *menu);
 static void conf_string(struct menu *menu);
 static void conf_load(void);
 static void conf_save(void);
+static int show_textbox_ext(const char *title, char *text, int r, int c,
+                           int *keys, int *vscroll, int *hscroll,
+                           update_text_fn update_text, void *data);
 static void show_textbox(const char *title, const char *text, int r, int c);
 static void show_helptext(const char *title, const char *text);
 static void show_help(struct menu *menu);
@@ -302,12 +311,47 @@ static void set_config_filename(const char *config_filename)
 }
 
 
+struct search_data {
+       struct list_head *head;
+       struct menu **targets;
+       int *keys;
+};
+
+static void update_text(char *buf, size_t start, size_t end, void *_data)
+{
+       struct search_data *data = _data;
+       struct jump_key *pos;
+       int k = 0;
+
+       list_for_each_entry(pos, data->head, entries) {
+               if (pos->offset >= start && pos->offset < end) {
+                       char header[4];
+
+                       if (k < JUMP_NB) {
+                               int key = '0' + (pos->index % JUMP_NB) + 1;
+
+                               sprintf(header, "(%c)", key);
+                               data->keys[k] = key;
+                               data->targets[k] = pos->target;
+                               k++;
+                       } else {
+                               sprintf(header, "   ");
+                       }
+
+                       memcpy(buf + pos->offset, header, sizeof(header) - 1);
+               }
+       }
+       data->keys[k] = 0;
+}
+
 static void search_conf(void)
 {
        struct symbol **sym_arr;
        struct gstr res;
        char *dialog_input;
-       int dres;
+       int dres, vscroll = 0, hscroll = 0;
+       bool again;
+
 again:
        dialog_clear();
        dres = dialog_inputbox(_("Search Configuration Parameter"),
@@ -330,10 +374,30 @@ again:
                dialog_input += strlen(CONFIG_);
 
        sym_arr = sym_re_search(dialog_input);
-       res = get_relations_str(sym_arr);
+       do {
+               LIST_HEAD(head);
+               struct menu *targets[JUMP_NB];
+               int keys[JUMP_NB + 1], i;
+               struct search_data data = {
+                       .head = &head,
+                       .targets = targets,
+                       .keys = keys,
+               };
+
+               res = get_relations_str(sym_arr, &head);
+               dres = show_textbox_ext(_("Search Results"), (char *)
+                                       str_get(&res), 0, 0, keys, &vscroll,
+                                       &hscroll, &update_text, (void *)
+                                       &data);
+               again = false;
+               for (i = 0; i < JUMP_NB && keys[i]; i++)
+                       if (dres == keys[i]) {
+                               conf(targets[i]->parent, targets[i]);
+                               again = true;
+                       }
+               str_free(&res);
+       } while (again);
        free(sym_arr);
-       show_textbox(_("Search Results"), str_get(&res), 0, 0);
-       str_free(&res);
 }
 
 static void build_conf(struct menu *menu)
@@ -514,12 +578,11 @@ conf_childs:
        indent -= doint;
 }
 
-static void conf(struct menu *menu)
+static void conf(struct menu *menu, struct menu *active_menu)
 {
        struct menu *submenu;
        const char *prompt = menu_get_prompt(menu);
        struct symbol *sym;
-       struct menu *active_menu = NULL;
        int res;
        int s_scroll = 0;
 
@@ -562,13 +625,13 @@ static void conf(struct menu *menu)
                                if (single_menu_mode)
                                        submenu->data = (void *) (long) !submenu->data;
                                else
-                                       conf(submenu);
+                                       conf(submenu, NULL);
                                break;
                        case 't':
                                if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
                                        conf_choice(submenu);
                                else if (submenu->prompt->type == P_MENU)
-                                       conf(submenu);
+                                       conf(submenu, NULL);
                                break;
                        case 's':
                                conf_string(submenu);
@@ -607,7 +670,7 @@ static void conf(struct menu *menu)
                        if (item_is_tag('t'))
                                sym_toggle_tristate_value(sym);
                        else if (item_is_tag('m'))
-                               conf(submenu);
+                               conf(submenu, NULL);
                        break;
                case 7:
                        search_conf();
@@ -619,10 +682,19 @@ static void conf(struct menu *menu)
        }
 }
 
-static void show_textbox(const char *title, const char *text, int r, int c)
+static int show_textbox_ext(const char *title, char *text, int r, int c, int
+                           *keys, int *vscroll, int *hscroll, update_text_fn
+                           update_text, void *data)
 {
        dialog_clear();
-       dialog_textbox(title, text, r, c);
+       return dialog_textbox(title, text, r, c, keys, vscroll, hscroll,
+                             update_text, data);
+}
+
+static void show_textbox(const char *title, const char *text, int r, int c)
+{
+       show_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL,
+                        NULL, NULL);
 }
 
 static void show_helptext(const char *title, const char *text)
@@ -862,9 +934,6 @@ int main(int ac, char **av)
                        single_menu_mode = 1;
        }
 
-       initscr();
-
-       getyx(stdscr, saved_y, saved_x);
        if (init_dialog(NULL)) {
                fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
                fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
@@ -873,7 +942,7 @@ int main(int ac, char **av)
 
        set_config_filename(conf_get_configname());
        do {
-               conf(&rootmenu);
+               conf(&rootmenu, NULL);
                res = handle_exit();
        } while (res == KEY_ESC);
 
index 8c2a97e60fafa701331949152261d162541482a1..e98a05c8e50882d3b2833a2f4d05761dcffd22d3 100644 (file)
@@ -507,10 +507,12 @@ const char *menu_get_help(struct menu *menu)
                return "";
 }
 
-static void get_prompt_str(struct gstr *r, struct property *prop)
+static void get_prompt_str(struct gstr *r, struct property *prop,
+                          struct list_head *head)
 {
        int i, j;
-       struct menu *submenu[8], *menu;
+       struct menu *submenu[8], *menu, *location = NULL;
+       struct jump_key *jump;
 
        str_printf(r, _("Prompt: %s\n"), _(prop->text));
        str_printf(r, _("  Defined at %s:%d\n"), prop->menu->file->name,
@@ -521,13 +523,44 @@ static void get_prompt_str(struct gstr *r, struct property *prop)
                str_append(r, "\n");
        }
        menu = prop->menu->parent;
-       for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
+       for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
+               bool accessible = menu_is_visible(menu);
+
                submenu[i++] = menu;
+               if (location == NULL && accessible)
+                       location = menu;
+       }
+       if (head && location) {
+               jump = malloc(sizeof(struct jump_key));
+
+               if (menu_is_visible(prop->menu)) {
+                       /*
+                        * There is not enough room to put the hint at the
+                        * beginning of the "Prompt" line. Put the hint on the
+                        * last "Location" line even when it would belong on
+                        * the former.
+                        */
+                       jump->target = prop->menu;
+               } else
+                       jump->target = location;
+
+               if (list_empty(head))
+                       jump->index = 0;
+               else
+                       jump->index = list_entry(head->prev, struct jump_key,
+                                                entries)->index + 1;
+
+               list_add_tail(&jump->entries, head);
+       }
+
        if (i > 0) {
                str_printf(r, _("  Location:\n"));
                for (j = 4; --i >= 0; j += 2) {
                        menu = submenu[i];
-                       str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu)));
+                       if (head && location && menu == location)
+                               jump->offset = r->len - 1;
+                       str_printf(r, "%*c-> %s", j, ' ',
+                                  _(menu_get_prompt(menu)));
                        if (menu->sym) {
                                str_printf(r, " (%s [=%s])", menu->sym->name ?
                                        menu->sym->name : _("<choice>"),
@@ -538,7 +571,11 @@ static void get_prompt_str(struct gstr *r, struct property *prop)
        }
 }
 
-void get_symbol_str(struct gstr *r, struct symbol *sym)
+/*
+ * head is optional and may be NULL
+ */
+void get_symbol_str(struct gstr *r, struct symbol *sym,
+                   struct list_head *head)
 {
        bool hit;
        struct property *prop;
@@ -557,7 +594,7 @@ void get_symbol_str(struct gstr *r, struct symbol *sym)
                }
        }
        for_all_prompts(sym, prop)
-               get_prompt_str(r, prop);
+               get_prompt_str(r, prop, head);
        hit = false;
        for_all_properties(sym, prop, P_SELECT) {
                if (!hit) {
@@ -577,14 +614,14 @@ void get_symbol_str(struct gstr *r, struct symbol *sym)
        str_append(r, "\n\n");
 }
 
-struct gstr get_relations_str(struct symbol **sym_arr)
+struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
 {
        struct symbol *sym;
        struct gstr res = str_new();
        int i;
 
        for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
-               get_symbol_str(&res, sym);
+               get_symbol_str(&res, sym, head);
        if (!i)
                str_append(&res, _("No matches found.\n"));
        return res;
@@ -603,5 +640,5 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help)
        }
        str_printf(help, "%s\n", _(help_text));
        if (sym)
-               get_symbol_str(help, sym);
+               get_symbol_str(help, sym, NULL);
 }
index 8c0eb65978c95aecedb73a7e71c6c4d788fe2255..87d4b15da951031896868789df7a992d21fcc73b 100644 (file)
@@ -83,10 +83,10 @@ static const char nconf_readme[] = N_(
 "Text Box    (Help Window)\n"
 "--------\n"
 "o  Use the cursor keys to scroll up/down/left/right.  The VI editor\n"
-"   keys h,j,k,l function here as do <SPACE BAR> for those\n"
-"   who are familiar with less and lynx.\n"
+"   keys h,j,k,l function here as do <u>, <d> and <SPACE BAR> for\n"
+"   those who are familiar with less and lynx.\n"
 "\n"
-"o  Press <Enter>, <F1>, <F5>, <F7> or <Esc> to exit.\n"
+"o  Press <Enter>, <F1>, <F5>, <F9>, <q> or <Esc> to exit.\n"
 "\n"
 "\n"
 "Alternate Configuration Files\n"
@@ -721,7 +721,7 @@ again:
                dialog_input += strlen(CONFIG_);
 
        sym_arr = sym_re_search(dialog_input);
-       res = get_relations_str(sym_arr);
+       res = get_relations_str(sym_arr, NULL);
        free(sym_arr);
        show_scroll_win(main_window,
                        _("Search Results"), str_get(&res));
@@ -1503,7 +1503,11 @@ int main(int ac, char **av)
        }
 
        notimeout(stdscr, FALSE);
+#if NCURSES_REENTRANT
+       set_escdelay(1);
+#else
        ESCDELAY = 1;
+#endif
 
        /* set btns menu */
        curses_menu = new_menu(curses_menu_items);
index 3b18dd839668b295cd3d06b1c4cac3d4c941ddf3..379003c7a2b4d8cef60e25548fcb9567ca3656c5 100644 (file)
@@ -604,9 +604,11 @@ void show_scroll_win(WINDOW *main_window,
                switch (res) {
                case KEY_NPAGE:
                case ' ':
+               case 'd':
                        start_y += text_lines-2;
                        break;
                case KEY_PPAGE:
+               case 'u':
                        start_y -= text_lines+2;
                        break;
                case KEY_HOME:
@@ -632,10 +634,10 @@ void show_scroll_win(WINDOW *main_window,
                        start_x++;
                        break;
                }
-               if (res == 10 || res == 27 || res == 'q'
-                   || res == KEY_F(F_BACK) || res == KEY_F(F_EXIT)) {
+               if (res == 10 || res == 27 || res == 'q' ||
+                       res == KEY_F(F_HELP) || res == KEY_F(F_BACK) ||
+                       res == KEY_F(F_EXIT))
                        break;
-               }
                if (start_y < 0)
                        start_y = 0;
                if (start_y >= total_lines-text_lines)
index d2c56f3c3d2e9a74a02b45f99d5f0f962fc84892..f636141e7bfd73526569bb96d300faba322761fe 100644 (file)
@@ -2259,7 +2259,7 @@ void conf_parse(const char *name)
        modules_sym = sym_lookup(NULL, 0);
        modules_sym->type = S_BOOLEAN;
        modules_sym->flags |= SYMBOL_AUTO;
-       rootmenu.prompt = menu_add_prompt(P_MENU, "Fiasco Kernel Configuration", NULL);
+       rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
 
        if (getenv("ZCONF_DEBUG"))
                zconfdebug = 1;
index 0e4d4553484e32f46d83f1028cb9e3c5d471218b..7abbe61de7aec319ae4ff28bba83896a2d478ca3 100755 (executable)
@@ -734,7 +734,8 @@ sub parse_file
            }
   
          # Member function definition?
-         if (/^([^\{\(]*?)             # pretext, maybe w template decl tag
+#          if (/^([^\{\(]*?)             # pretext, maybe w template decl tag
+          if (/^((?:[^\{\(]|\(\()*?)             # pretext, maybe w template decl tag
               \b ($identifier (?: $s :: $s $identifier)*) # class name
               ($s $template_arg)?      # optional class-template args
               $s :: $s
@@ -745,7 +746,7 @@ sub parse_file
            {
              my ($pretext, $class, $templateargs, $name, $args, $posttext)
                = ($1, $2, (defined $3 ? $3 : ''), $4, $5, $6);
-#print "P<$pretext> C<$class> T<$templateargs> N<$name> A<$args> P<$posttext>\n";
+#print "Member: P<$pretext> C<$class> T<$templateargs> N<$name> A<$args> P<$posttext>\n";
              # Canonify operator names
              $name =~ s/(?<=\w)(?:$s_once)+(?=\W)//gs;
              $name =~ s/(?<=\W)(?:$s_once)+(?=\w)//gs;
@@ -769,6 +770,7 @@ sub parse_file
                $s( \( $paren_expr \) [^:\{\(\)=]*) # arg list
                (\{.*)$/sx)              # body
            {
+#print "Free function: $2 T(" . (defined $3 ? $3 : "") . ") PRE($1) ARGS($4) POST($5)\n";
              my $function = { class => '',
                               name => $2,
                               templateargs => (defined $3
@@ -869,7 +871,7 @@ sub read_more ()    # Read one more line of code. Stow away
          s/\003/$saved/s;
        }
 
-      while (s|(//(?!-\s*\n).*)$|\001$number\001|m) # Do not match magic "//-"
+      while (s|(//(?!-\s*\n).*\n)|\001$number\001|m) # Do not match magic "//-"
        {                       # The \001 signifies whitespace.
          push @comments, $1;
          $number++;
@@ -1145,7 +1147,6 @@ sub handle_function
            if ($match =~ /^(?:${s}template$s<${s}>)+${s}$/s);
 
           $func->{pretext} =~ s/\Q$match//s;
-#         $func->{pretext} =~ s|$template[ \t]*||s;
          next;
         }
 
index 652866c642ba3677858a85d7f73f5bd56110e4fe..3d48137ab24edde0497f77a2d90dfd4a75e24b51 100644 (file)
@@ -13,7 +13,7 @@ TOOL_TESTS = mapping mapping_inline random random_inline extern_c static \
   parser parser_noinline \
   multifile variable line line_not line_nh interface comment_in_string \
   default_args drop_single1 drop_single2 drop_single3 drop_multi1 \
-  drop_multi2
+  drop_multi2 implement_template
 
 mapping_inline_src = mapping
 mapping_inline_flags = -i
diff --git a/kernel/fiasco/tool/preprocess/test/implement_template.cpp b/kernel/fiasco/tool/preprocess/test/implement_template.cpp
new file mode 100644 (file)
index 0000000..ae81de0
--- /dev/null
@@ -0,0 +1,31 @@
+INTERFACE:
+
+template< typename T >
+class Test
+{
+public:
+  void test_func();
+};
+
+
+IMPLEMENTATION:
+
+IMPLEMENT
+template< typename T >
+// comment
+void __attribute__((deprecated))
+Test<T>::test_func()
+{
+}
+
+PUBLIC
+template< typename T > // comment 1
+template<
+  typename X, // comment within template args list
+  typename X2 // another comment in tl args
+>
+// comment 2
+void __attribute__((deprecated))
+Test<T>::test_func2<X, X2>()
+{
+}
diff --git a/kernel/fiasco/tool/preprocess/test/verify/implement_template.cc b/kernel/fiasco/tool/preprocess/test/verify/implement_template.cc
new file mode 100644 (file)
index 0000000..89fa57e
--- /dev/null
@@ -0,0 +1,5 @@
+// AUTOMATICALLY GENERATED -- DO NOT EDIT!         -*- c++ -*-
+
+#include "implement_template.h"
+#include "implement_template_i.h"
+
diff --git a/kernel/fiasco/tool/preprocess/test/verify/implement_template.h b/kernel/fiasco/tool/preprocess/test/verify/implement_template.h
new file mode 100644 (file)
index 0000000..4cd4433
--- /dev/null
@@ -0,0 +1,58 @@
+// AUTOMATICALLY GENERATED -- DO NOT EDIT!         -*- c++ -*-
+
+#ifndef implement_template_h
+#define implement_template_h
+
+//
+// INTERFACE definition follows 
+//
+
+#line 2 "implement_template.cpp"
+
+template< typename T >
+class Test
+{
+public:
+  void test_func();
+
+public:  
+#line 23 "implement_template.cpp"
+  // comment 2
+   // comment 1
+  template<
+    typename X, // comment within template args list
+    typename X2 // another comment in tl args
+  > void __attribute__((deprecated))
+  test_func2<X,X2>();
+};
+
+//
+// IMPLEMENTATION of function templates
+//
+
+
+#line 12 "implement_template.cpp"
+
+
+
+// comment
+template< typename T > void __attribute__((deprecated))
+Test<T>::test_func()
+{
+}
+
+#line 20 "implement_template.cpp"
+
+
+
+// comment 2
+ // comment 1
+template< typename T > template<
+  typename X, // comment within template args list
+  typename X2 // another comment in tl args
+> void __attribute__((deprecated))
+Test<T>::test_func2<X,X2>()
+{
+}
+
+#endif // implement_template_h
diff --git a/kernel/fiasco/tool/preprocess/test/verify/implement_template_i.h b/kernel/fiasco/tool/preprocess/test/verify/implement_template_i.h
new file mode 100644 (file)
index 0000000..da19d7d
--- /dev/null
@@ -0,0 +1,6 @@
+// AUTOMATICALLY GENERATED -- DO NOT EDIT!         -*- c++ -*-
+
+#ifndef implement_template_i_h
+#define implement_template_i_h
+
+#endif // implement_template_i_h
index bbe70c07280505b4a81fa7209065ef4d36ebabae..154804e2ade21528260db94b5dbaed6149ffd4ed 100644 (file)
@@ -15,6 +15,7 @@ class Foo
 public:  
   // A long, multiline comment in front of this function definition.
   // Also, a lot of specifiers that need to be handled.
+  
   static void func1();
 };
 
index eb1d7ca68943a05b022901495df692708810082c..ff1bbb81fb354422c2e7168e8c37ba014de32ed2 100644 (file)
@@ -8,6 +8,7 @@
 // A long, multiline comment in front of this function definition.
 // Also, a lot of specifiers that need to be handled.
 
+
 void
 Foo::func1()
 {
index 11ab555d22fd011a4d879aa5a6f7abc04d609167..f563d556edd46504eedfc8f215725b7659bc05f5 100644 (file)
@@ -15,6 +15,7 @@ class Foo
 public:  
   // A long, multiline comment in front of this function definition.
   // Also, a lot of specifiers that need to be handled.
+  
   static void func1();
 };
 
index 1ce3cf4f236cb261ba57049ff4a9b1e70c936a37..4d63c04e8ac8460162e6cf2a79ca2f351bb9d0de 100644 (file)
@@ -17,17 +17,21 @@ public:
   void * 
   operator new(size_t);        // funny comment
   
+  
 #line 16 "operator.cpp"
   Foo&
   operator+(const Foo&);       // funny comment
   
+  
 #line 22 "operator.cpp"
   Foo&
   operator=(const Foo&);       // funny comment
   
+  
 #line 28 "operator.cpp"
   Foo&
   operator*(const Foo&);       // funny comment
+  
 };
 
 #line 34 "operator.cpp"
index 2e60849fa44b157d5404b6428a4b89171ae50323..f3fd7d6bef5370e313c5316dd7ace426102ff59c 100644 (file)
@@ -12,13 +12,3 @@ create_stack<int>()
 {
   return new stack<int>();
 }
-
-#line 192 "template.cpp"
-
-
-
-template <> stack_t<bool>*
-create_stack<bool>()
-{
-  return new stack<bool>();
-}
index 320fceb28490163d748b93bb37ad13a12f476b4a..79ab22e2ee56cbd0fdc01ff5f417c85ebcf9fe20 100644 (file)
@@ -109,9 +109,24 @@ template <> stack_t<int>*
 create_stack();
 
 #line 195 "template.cpp"
-template <> stack_t<bool>*
+template <> inline stack_t<bool>*
 create_stack();
 
+//
+// IMPLEMENTATION of inline functions (and needed classes)
+//
+
+
+#line 192 "template.cpp"
+
+
+
+template <> inline stack_t<bool>*
+create_stack<bool>()
+{
+  return new stack<bool>();
+}
+
 //
 // IMPLEMENTATION of function templates
 //
index 259d6cc71bc4e9d21c6987a80afe5a0af98c3de9..f8ce99a73219fac4e3adc8dc53b82f19dff65bc5 100644 (file)
@@ -388,9 +388,7 @@ define genimage
 endef
 
 define switch_ram_base_func
-       echo "  ... Regenerating RAM_BASE settings"; \
-       echo "# File semi-automatically generated by 'make switch_ram_base'" > $(OBJ_BASE)/Makeconf.ram_base; \
-       echo "# Currently being regenerated"                                >> $(OBJ_BASE)/Makeconf.ram_base; \
+       echo "  ... Regenerating RAM_BASE settings"; set -e; \
        PWD=$(PWD)/pkg/sigma0/server/src $(MAKE) RAM_BASE=$(1) -C pkg/sigma0/server/src;                      \
        PWD=$(PWD)/pkg/moe/server/src    $(MAKE) RAM_BASE=$(1) -C pkg/moe/server/src;                         \
        echo "# File semi-automatically generated by 'make switch_ram_base'" > $(OBJ_BASE)/Makeconf.ram_base; \
@@ -411,7 +409,7 @@ check_and_adjust_ram_base:
          echo "Platform \"$(PLATFORM_TYPE)\" not known."; \
          exit 1;                                          \
        fi
-       $(VERBOSE)if [ $$(($(RAM_BASE))) != $$(($(PLATFORM_RAM_BASE))) ]; then                  \
+       $(VERBOSE)if [ $$(($(RAM_BASE))) != $$(($(PLATFORM_RAM_BASE))) -o -z "$(RAM_BASE)" ]; then               \
          echo "=========== Updating RAM_BASE for platform $(PLATFORM_TYPE) to $(PLATFORM_RAM_BASE) =========" ; \
          $(call switch_ram_base_func,$(PLATFORM_RAM_BASE)); \
        fi
@@ -458,7 +456,7 @@ vbox: $(if $(VBOX_ISOTARGET),$(VBOX_ISOTARGET),grub2iso)
          echo "Need to set name of configured VirtualBox VM im 'VBOX_VM'.";   \
          exit 1;                                                              \
        fi
-       $(VERBOSE)VBoxSDL                       \
+       $(VERBOSE)VirtualBox                    \
            --startvm $(VBOX_VM)                \
            --cdrom $(IMAGES_DIR)/.current.iso  \
            --boot d                            \
index c737cd67cfd987c96e60748712cbf6acef3808e3..6ab421af255d4c732e1835654cb72c27bba67702 100644 (file)
@@ -25,14 +25,17 @@ CONFIG_CPU_ARM_ARMV5TE=y
 # CONFIG_PLATFORM_TYPE_imx21 is not set
 # CONFIG_PLATFORM_TYPE_imx35 is not set
 # CONFIG_PLATFORM_TYPE_imx51 is not set
+# CONFIG_PLATFORM_TYPE_imx6 is not set
 # CONFIG_PLATFORM_TYPE_integrator is not set
 # CONFIG_PLATFORM_TYPE_kirkwood is not set
 # CONFIG_PLATFORM_TYPE_omap3_am33xx is not set
 # CONFIG_PLATFORM_TYPE_omap3evm is not set
 # CONFIG_PLATFORM_TYPE_pandaboard is not set
+# CONFIG_PLATFORM_TYPE_rpi_b is not set
 CONFIG_PLATFORM_TYPE_rv=y
 # CONFIG_PLATFORM_TYPE_rv_pbx is not set
 # CONFIG_PLATFORM_TYPE_rv_vexpress is not set
+# CONFIG_PLATFORM_TYPE_rv_vexpress_a15 is not set
 # CONFIG_PLATFORM_TYPE_tegra2 is not set
 # CONFIG_PLATFORM_TYPE_custom is not set
 CONFIG_PLATFORM_TYPE="rv"
index 98658136e924f19b0ddfe1be14d4279c52c195e5..746e2cfac8f1217dfb18e0d042b21dc305d355eb 100644 (file)
@@ -286,7 +286,7 @@ processing-of-module-list-failed:
        @echo
        @exit 1
 
-mod.make.inc: $(GENERAL_D_LOC) $(shell $(call BUILD_MOD_CMD,list))
+mod.make.inc $(od)mbi_modules.bin: $(GENERAL_D_LOC) $(shell $(call BUILD_MOD_CMD,list))
        @echo Building entry \""$(ENTRY)"\".
        $(VERBOSE)$(call BUILD_MOD_CMD,build)
 
index 4521ed8bf70213a6384b41f1cabbf4c5f75847ba..d651e4aa230466462ef15f29b06d0ffce31c6a59 100644 (file)
@@ -26,7 +26,7 @@ class Platform_arm_int : public Platform_single_region_ram
   void init()
   {
     static L4::Io_register_block_mmio r(0x16000000);
-    static L4::Uart_pl011 _uart;
+    static L4::Uart_pl011 _uart(24019200);
     _uart.startup(&r);
     set_stdio_uart(&_uart);
   }
index ad10986b48c000c08723bf0c275e76c9cbd71b5e..6fcad0b61d230707d32f3275e46e2c89c01ac115 100644 (file)
@@ -27,7 +27,7 @@ class Platform_arm_rv : public Platform_single_region_ram
   void init()
   {
     static L4::Io_register_block_mmio r(0x10009000);
-    static L4::Uart_pl011 _uart;
+    static L4::Uart_pl011 _uart(24019200);
     _uart.startup(&r);
     set_stdio_uart(&_uart);
   }
index 3b92289f39354f1739800682ad292cfce1f02a6e..b6565ac54331c8a8c649079a25af3c8f7fcd2ff2 100644 (file)
@@ -27,7 +27,7 @@ class Platform_arm_rv_vexpress : public Platform_single_region_ram
   void init()
   {
     static L4::Io_register_block_mmio r(0x10009000);
-    static L4::Uart_pl011 _uart;
+    static L4::Uart_pl011 _uart(24019200);
     _uart.startup(&r);
     set_stdio_uart(&_uart);
   }
index 0442bcc8d016d7b3e50d50cdd9c488bba117d228..e2e6af0f13b0fb909a68368858afb86b86249ee8 100644 (file)
@@ -16,6 +16,7 @@ namespace L4
   class Uart_pl011 : public Uart
   {
   public:
+    Uart_pl011(unsigned freq) : _freq(freq) {}
     bool startup(Io_register_block const *);
     void shutdown();
     bool change_mode(Transfer_mode m, Baud_rate r);
@@ -24,6 +25,9 @@ namespace L4
     int char_avail() const;
     inline void out_char(char c) const;
     int write(char const *s, unsigned long count) const;
+
+  private:
+    unsigned _freq;
   };
 };
 
index 5167a993f266404edb3e9a69471b04fce5e189a5..e0d0abf8b730320b932899b3fad96b9aed65ea4d 100644 (file)
@@ -49,16 +49,18 @@ namespace L4
     UART011_IMSC = 0x38,
     UART011_MIS  = 0x40,
     UART011_ICR  = 0x44,
-  };
 
+    Default_baud = 115200,
+  };
 
   bool Uart_pl011::startup(Io_register_block const *regs)
   {
     _regs = regs;
     _regs->write<unsigned int>(UART011_CR, UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE);
-    _regs->write<unsigned int>(UART011_FBRD, 2);
-    _regs->write<unsigned int>(UART011_IBRD, 13);
-    _regs->write<unsigned int>(UART011_LCRH, 0x60);
+    unsigned fi_val = _freq * 4 / Default_baud;
+    _regs->write<unsigned int>(UART011_FBRD, fi_val & 0x3f);
+    _regs->write<unsigned int>(UART011_IBRD, fi_val >> 6);
+    _regs->write<unsigned int>(UART011_LCRH, UART01x_LCRH_WLEN_8);
     _regs->write<unsigned int>(UART011_IMSC, 0);
     Poll_timeout_counter i(3000000);
     while (i.test() && _regs->read<unsigned int>(UART01x_FR) & UART01x_FR_BUSY)
@@ -88,14 +90,12 @@ namespace L4
 
   bool Uart_pl011::change_mode(Transfer_mode, Baud_rate r)
   {
-    if (r != 115200)
-      return false;
-
     unsigned long old_cr = _regs->read<unsigned int>(UART011_CR);
     _regs->write<unsigned int>(UART011_CR, 0);
 
-    _regs->write<unsigned int>(UART011_FBRD, 2);
-    _regs->write<unsigned int>(UART011_IBRD, 13);
+    unsigned fi_val = _freq * 4 / r;
+    _regs->write<unsigned int>(UART011_FBRD, fi_val & 0x3f);
+    _regs->write<unsigned int>(UART011_IBRD, fi_val >> 6);
     _regs->write<unsigned int>(UART011_LCRH, UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN);
 
     _regs->write<unsigned int>(UART011_CR, old_cr);
index 28e280ae16381cffc68acd1d38c1ba6c3e6cea9a..14802718fcbddab1d53f489b0e39788a0bfdac79 100644 (file)
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <assert.h>
 
 #include <pthread.h>
 
@@ -37,8 +38,8 @@ static unsigned long gdt[32 * 2] __attribute__((aligned(4096)));
 
 void vm_resume(void);
 void handle_vmexit(void);
-l4_vcpu_state_t *vcpu;
-l4_vm_svm_vmcb_t *vmcb_s;
+static l4_vcpu_state_t *vcpu;
+static l4_vm_svm_vmcb_t *vmcb_s;
 
 static void init_vmcb(l4_vm_svm_vmcb_t *vmcb_s) {
 
@@ -131,7 +132,7 @@ static int check_svm_npt(void) {
     return (!(dx & 1));
 }
 
-int vmexit = 0;
+static int vmexit = 0;
 
 static int cnt_triggered, cnt_received;
 
@@ -237,16 +238,14 @@ void handle_vmexit(void) {
     }
 }
 
-static l4_vcpu_state_t *get_state_mem(l4_addr_t *extstate) {
-    static int done;
+static l4_addr_t get_state_mem(void)
+{
     long r;
     l4_msgtag_t tag;
     static l4_addr_t ext_state;
 
-    if (done) {
-        *extstate = ext_state;
-        return vcpu;
-    }
+    if (ext_state)
+        return ext_state;
 
     if ((r = l4vcpu_ext_alloc(&vcpu, &ext_state, L4_BASE_TASK_CAP,
             l4re_env()->rm))) {
@@ -254,6 +253,8 @@ static l4_vcpu_state_t *get_state_mem(l4_addr_t *extstate) {
         exit(1);
     }
 
+    assert(ext_state);
+
     vcpu->state = L4_VCPU_F_FPU_ENABLED;
     vcpu->saved_state = L4_VCPU_F_USER_MODE | L4_VCPU_F_FPU_ENABLED | L4_VCPU_F_IRQ;
 
@@ -270,10 +271,7 @@ static l4_vcpu_state_t *get_state_mem(l4_addr_t *extstate) {
         exit(1);
     }
 
-    done = 1;
-    *extstate = ext_state;
-
-    return vcpu;
+    return ext_state;
 }
 
 
@@ -283,8 +281,7 @@ static void run_test(int np_available) {
     l4_cap_idx_t vm_task = l4re_util_cap_alloc();
 //    int i;
     l4_umword_t ip; //, marker, test_end;
-    l4_addr_t vmcx;
-    get_state_mem(&vmcx);
+    l4_addr_t vmcx = get_state_mem();
 
     printf("run test, np_available=%d\n", np_available);
 
index 1a348b3d28a16660e76101edd789fb791ebfa9c3..85887195fc50783fbf69947ac6b35d4ac61d3543 100644 (file)
@@ -24,6 +24,7 @@ Io.hw_add_devices
     hid = "PNP0900";
     Res.io(0x3b0, 0x3bf); -- MDA
     Res.io(0x3c0, 0x3df); -- EGA/VGA
+    Res.io(0x1ce, 0x1d0); -- Vbox
     Res.mmio(0xa0000, 0xbffff, 0xc000);
   },
 
index 211c0a9482b723cf0a296186b31649d92d492edf..6a6b9efc66d5cac64b8727541bda2c9797aa959e 100644 (file)
@@ -1,8 +1,8 @@
 #
 #      List of PCI ID's
 #
-#      Version: 2012.08.15
-#      Date:    2012-08-15 03:15:02
+#      Version: 2013.01.05
+#      Date:    2013-01-05 03:15:02
 #
 #      Maintained by Martin Mares <mj@ucw.cz> and other volunteers from the
 #      PCI ID Project at http://pci-ids.ucw.cz/.
@@ -21,7 +21,6 @@
 #      device  device_name                             <-- single tab
 #              subvendor subdevice  subsystem_name     <-- two tabs
 
-0000  Gammagraphx, Inc. (or missing ID)
 0010  Allied Telesis, Inc
 # This is a relabelled RTL-8139
        8139  AT-2500TX V3 Ethernet
 0357  TTTech AG
        000a  TTP-Monitoring Card V2.0
 036f  Trigem Computer Inc.
-0403  Future Technology Devices International Ltd
 0432  SCM Microsystems, Inc.
        0001  Pluto2 DVB-T Receiver for PCMCIA [EasyWatch MobilSet]
-0482  Kyocera
-# vendor code used for (at a minimum) RSA cards
-04b3  IBM Corp.
-       4001  Remote System Administration device [RSA2]
-050d  Belkin
-05a9  OmniVision
-       8519  OV519 series
-05e3  CyberDoor
-       0701  CBD516
-066f  SigmaTel
-       3410  SMTP3410
-       3500  SMTP3500
 0675  Dynalink
        1700  IS64PH ISDN Adapter
        1702  IS64PH ISDN Adapter
        1703  ISDN Adapter (PCI Bus, DV, W)
        1704  ISDN Adapter (PCI Bus, D, C)
-069d  Hughes Network Systems (HNS)
 0721  Sapphire, Inc.
 0777  Ubiquiti Networks, Inc.
 # Atheros, 6th Generation, AR5414, 802.11a, 5GHz
                4c53 1080  CT8 mainboard
                4c53 1300  P017 mezzanine (32-bit PMC)
                4c53 1310  P017 mezzanine (64-bit PMC)
+       002f  MegaRAID SAS 2208 IOV [Thunderbolt]
+               1028 1f3e  SPERC 8
        0030  53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI
                0e11 00da  ProLiant ML 350
                1028 0123  LSI Logic 1020/1030
        005b  MegaRAID SAS 2208 [Thunderbolt]
                1000 9265  MegaRAID SAS 9265-8i
                1000 9266  MegaRAID SAS 9266-8i
+               1000 9267  MegaRAID SAS 9267-8i
                1000 9268  MegaRAID SAS 9265CV-8i / 9270CV-8i
+               1000 9269  MegaRAID SAS 9266-4i
+               1000 9270  MegaRAID SAS 9270-8i
+               1000 9271  MegaRAID SAS 9271-8i
+               1000 9272  MegaRAID SAS 9272-8i
+               1000 9273  MegaRAID SAS 9270CV-8i
+               1000 9274  MegaRAID SAS 9270-4i
+               1000 9275  MegaRAID SAS 9271-8iCC
+               1000 9276  MegaRAID SAS 9271-4i
+               1000 9285  MegaRAID SAS 9285-8e
+               1000 9288  MegaRAID SAS 9285CV-8e
+               1000 9290  MegaRAID SAS 9286-8e
+               1000 9291  MegaRAID SAS 9286CV-8e
+               1000 9295  MegaRAID SAS 9286CV-8eCC
                1014 040b  ServeRAID M5110 SAS/SATA Controller
                1014 0412  ServeRAID M5110e SAS/SATA Controller
                1028 1f2d  PERC H810 Adapter
                1028 014a  PowerEdge 1750
                1028 0165  PowerEdge 750
                103c 10e1  NetServer Rage XL
+               103c 3208  ProLiant DL140 G2
                107b 6400  6400 Server
                1734 007a  PRIMERGY RX/TX series onboard VGA
                8086 3411  SDS2 Mainboard
        5a1e  RD890 PCI to PCI bridge (external gfx1 port B)
        5a1f  RD890 PCI to PCI bridge (NB-SB link)
                15d9 a811  H8DGU
+       5a20  RD890S PCI Express bridge for GPP2 port 1
        5a23  RD990 I/O Memory Management Unit (IOMMU)
        5a33  Radeon Xpress 200 Host Bridge
        5a34  RS480 PCI-X Root Port
        5e6d  RV410 [Radeon X700 (PCIE)] (Secondary)
                148c 2117  PowerColor Bravo X700
        5f57  R423 [Radeon X800XT (PCIE)]
+       6600  Mars [Radeon HD 8600/8700M Series]
+       6601  Mars [Radeon HD 8500/8700M Series]
+       6606  Mars [Radeon HD 8790M]
+       6610  Oland [Radeon HD 8600 Series]
+       6611  Oland [Radeon HD 8500 Series]
+       6704  Cayman PRO GL [FirePro V7900]
        6707  Cayman LE GL [FirePro V5900]
        6718  Cayman XT [Radeon HD 6970]
        6719  Cayman PRO [Radeon HD 6950]
        6798  Tahiti XT [Radeon HD 7970]
        6799  New Zealand [Radeon HD 7990]
        679a  Tahiti PRO [Radeon HD 7950]
-       6800  WIMBLEDON XT [Radeon HD 7970M]
-       6818  PITCAIRN [Radeon HD 7800]
-       6819  PITCAIRN PRO [Radeon HD 7800 Series]
+       679e  Tahiti LE [Radeon HD 7800 Series]
+       6800  Wimbledon XT [Radeon HD 7970M]
+       6818  Pitcairn [Radeon HD 7800]
+       6819  Pitcairn PRO [Radeon HD 7800]
+       6820  Radeon HD 8800M Series
+       6821  Radeon HD 8800M Series
+       6823  Radeon HD 8800M Series
+       6825  Cape Verde [Radeon HD 7800M Series]
+       682b  Radeon HD 8800M Series
        682f  Cape Verde [Radeon HD 7700M Series]
+       683b  Cape Verde [Radeon HD 7700 Series]
        683d  Cape Verde [Radeon HD 7700 Series]
        683f  Cape Verde PRO [Radeon HD 7700 Series]
        6840  Thames XT/GL [Radeon HD 7600M Series]
        6841  Thames [Radeon 7500M/7600M Series]
+       6842  Thames LE [Radeon HD 7000M Series]
        6843  Thames [Radeon HD 7670M]
        6850  Lombok GL AIO [Radeon HD 7570]
        6858  Lombok [Radeon HD 7400 series]
+       6888  Cypress [FirePro 3D V8800]
        6889  Cypress [FirePro V7800]
+       688a  Cypress XT [FirePro 3D V9800]
        688c  Cypress [AMD FireStream 9370]
        688d  Cypress [AMD FireStream 9350]
        6898  Cypress XT [Radeon HD 5870]
                17f2 5000  KI690-AM2 Motherboard
        791f  RS690M [Radeon X1200 Series]
                1179 ff50  Satellite P305D-S8995E
-       7930  Radeon Xpress 7930 Host Bridge
-       7932  RS7932 PCI Bridge
-       7933  RS7933 PCI Bridge
-       7936  RS7936 PCI Bridge
-       793b  RS600 audio device [Radeon Xpress 12xx Series]
-       793f  RS600 [Radeon Xpress 1200 Series]
-       7941  RS600 [Radeon Xpress 1200 Series]
-       7942  Radeon Xpress 1250
+       7930  RS600 Host Bridge
+       7932  RS600 PCI to PCI Bridge (Internal gfx)
+       7933  RS600 PCI to PCI Bridge (PCI Express Graphics Port 0)
+       7935  RS600 PCI to PCI Bridge (PCI Express Port 1)
+       7936  RS600 PCI to PCI Bridge (PCI Express Port 2)
+       7937  RS690 PCI to PCI Bridge (PCI Express Port 3)
+       793b  RS600 HDMI Audio [Radeon Xpress 1250]
+       793f  RS600 [Radeon Xpress 1250]
+       7941  RS600 [Radeon Xpress 1250]
+       7942  RS600 [Radeon Xpress 1250]
        796e  Radeon 2100
        7c37  RV350 AQ [Radeon 9600 SE]
        9400  R600 [Radeon HD 2900 Series]
        9804  Wrestler [Radeon HD 6250]
        9806  Wrestler [Radeon HD 6320]
        9807  Wrestler [Radeon HD 6290]
+# AMD A10-5800K CPU
+       9901  Trinity [Radeon HD 7660D]
+       9902  Trinity HDMI Audio Controller
+       9904  Trinity [Radeon HD 7560D]
+       9990  Trinity [Radeon HD 7520G]
        aa00  R600 Audio Device [Radeon HD 2900 Series]
        aa08  RV630 audio device [Radeon HD 2600 Series]
        aa10  RV610 HDMI Audio [Radeon HD 2350/2400 Series]
        aa98  Caicos HDMI Audio [Radeon HD 6400 Series]
                174b aa98  Sapphire HD 6450 1GB DDR3
        aaa0  Tahiti XT HDMI Audio [Radeon HD 7970 Series]
+       aab0  Cape Verde HDMI Audio [Radeon HD 7700 Series]
        ac00  Theater 600 Pro
        ac02  TV Wonder HD 600 PCIe
        ac12  Theater HD T507 (DVB-T) TV tuner/capture device
        0339  Obsidian-E PCI-E SCSI controller
                1014 030a  PCIe 3Gb SAS RAID Adapter (574E)
                1014 033a  PCIe 3Gb SAS Adapter (57B3)
+               1014 035c  PCIe x8 Internal 3Gb SAS adapter (57CC)
                1014 0360  PCI-E Auxiliary Cache Adapter (57B7)
        033d  PCI-E IPR SAS Adapter (FPGA)
                1014 033c  PCIe2 1.8GB Cache 6Gb SAS RAID Adapter Tri-port (57B5)
                1014 0357  PCIe2 6Gb SAS Adapter Quad-port (57C6)
                1014 035d  PCIe3 1.8GB Cache RAID SAS Adapter Quad-port 6GB (57C8)
                1014 035e  PCIe2 3.6GB Cache 6Gb SAS RAID Adapter Quad-port (57CE)
+               1014 03fb  PCIe3 28GB Cache RAID SAS Enclosure 6Gb x 16 (57D5)
        3022  QLA3022 Network Adapter
        4022  QLA3022 Network Adapter
        ffff  MPIC-2 interrupt controller
        1417  Family 15h (Models 10h-1fh) Processor Root Port
        1418  Family 15h (Models 10h-1fh) Processor Root Port
        1419  Family 15h (Models 10h-1fh) I/O Memory Management Unit
+       1439  Family 16h Processor Functions 5:1
        1510  Family 14h Processor Root Complex
                174b 1001  Sapphire PURE Fusion Mini
        1512  Family 14h Processor Root Port
        1514  Family 14h Processor Root Port
        1515  Family 14h Processor Root Port
        1516  Family 14h Processor Root Port
+       1530  Family 16h Processor Function 0
+       1531  Family 16h Processor Function 1
+       1532  Family 16h Processor Function 2
+       1533  Family 16h Processor Function 3
+       1534  Family 16h Processor Function 4
+       1535  Family 16h Processor Function 5
+       1536  Family 16h Processor Root Complex
+       1538  Family 16h Processor Function 0
        1600  Family 15h Processor Function 0
        1601  Family 15h Processor Function 1
        1602  Family 15h Processor Function 2
        2097  CS5536 [Geode companion] UOC
        209a  CS5536 [Geode companion] IDE
        3000  ELanSC520 Microcontroller
+       43a0  Hudson PCI to PCI bridge (PCIE port 0)
+       43a1  Hudson PCI to PCI bridge (PCIE port 1)
+       43a2  Hudson PCI to PCI bridge (PCIE port 2)
+       43a3  Hudson PCI to PCI bridge (PCIE port 3)
        7006  AMD-751 [Irongate] System Controller
        7007  AMD-751 [Irongate] AGP Bridge
        700a  AMD-IGR4 AGP Host to PCI Bridge
                161f 3017  HDAMB
        746e  AMD-8111 MC97 Modem
        756b  AMD-8111 ACPI
-       7800  Hudson SATA Controller [IDE mode]
-       7801  Hudson SATA Controller [AHCI mode]
-       7802  Hudson SATA Controller [RAID mode]
-       7803  Hudson SATA Controller [RAID mode]
-       7804  Hudson SATA Controller [AHCI mode]
-       7805  Hudson SATA Controller [RAID mode]
-       7806  Hudson SD Flash Controller
-       7807  Hudson USB OHCI Controller
-       7808  Hudson USB EHCI Controller
-       7809  Hudson USB OHCI Controller
-       780b  Hudson SMBus Controller
-       780c  Hudson IDE Controller
-       780d  Hudson Azalia Controller
-               103c 168b  Integrated Device Technology, Inc. [IDT] 92HD87B1/3 Audio Processor
-       780e  Hudson LPC Bridge
-       780f  Hudson PCI Bridge
-       7812  Hudson USB XHCI Controller
+       7800  FCH SATA Controller [IDE mode]
+       7801  FCH SATA Controller [AHCI mode]
+       7802  FCH SATA Controller [RAID mode]
+       7803  FCH SATA Controller [RAID mode]
+       7804  FCH SATA Controller [AHCI mode]
+       7805  FCH SATA Controller [RAID mode]
+       7806  FCH SD Flash Controller
+       7807  FCH USB OHCI Controller
+       7808  FCH USB EHCI Controller
+       7809  FCH USB OHCI Controller
+       780b  FCH SMBus Controller
+       780c  FCH IDE Controller
+       780d  FCH Azalia Controller
+       780e  FCH LPC Bridge
+       780f  FCH PCI Bridge
+       7812  FCH USB XHCI Controller
+       7813  FCH SD Flash Controller
+       7814  FCH USB XHCI Controller
        9600  RS780 Host Bridge
                1043 82f1  M3A78-EH Motherboard
        9601  RS880 Host Bridge
                102b ff04  Marvel G200 AGP
                110a 0032  MGA-G200 AGP
        0522  MGA G200e [Pilot] ServerEngines (SEP1)
+               103c 31fa  ProLiant DL140 G3
        0525  MGA G400/G450
                0e11 b16f  MGA-G400 AGP
                102b 0328  Millennium G400 16Mb SDRAM
        7007  FireWire Controller
                1462 701d  MS-6701
        7012  SiS7012 AC'97 Sound Controller
+               1019 0f05  A928 (i-Buddie)
                1039 7012  SiS 7012 onboard [Asus P4SC-EA] AC'97 Sound Controller
                1043 818f  A8S-X Motherboard
                13f6 0300  CMI9739(A) on ECS K7SOM+ motherboard
                103c 330e  iLO3
                103c 3381  iLO4
        3307  Integrated Lights-Out Standard Management Processor Support and Messaging
+# HP DL380 G6
+               103c 3309  iLO 2
                103c 330e  iLO3
                103c 3381  iLO4
        3308  Integrated Lights-Out Standard MS Watchdog Timer
        4037  PCIe Local Bus Adapter
        403b  PCIe Root Port
        60e8  NetRAID-2M : ZX1/M (OEM AMI MegaRAID 493)
-       780d  Hudson Azalia Controller (rev 01) - Soundcard
 103e  Solliday Engineering
 103f  Synopsys/Logic Modeling Group
 1040  Accelgraphics Inc.
                103c 006a  NX9500
                1043 808d  A7V333 mainboard.
        8027  PCI4451 IEEE-1394 Controller
+               1028 00e5  Latitude C810
                1028 00e6  PCI4451 IEEE-1394 Controller (Dell Inspiron 8100)
        8029  PCI4510 IEEE-1394 Controller
                1028 0163  Latitude D505
        823f  XIO2213A/B/XIO2221 IEEE-1394b OHCI Controller [Cheetah Express]
                1546 803c  FWB-PCIE1X11B
        8240  XIO2001 PCI Express-to-PCI Bridge
+       8241  TUSB73x0 SuperSpeed USB 3.0 xHCI Host Controller
        8400  ACX 100 22Mbps Wireless Interface
                1186 3b00  DWL-650+ PC Card cardbus 22Mbs Wireless Adapter [AirPlus]
                1186 3b01  DWL-520+ 22Mbps PCI Wireless Adapter
                10b4 237e  Velocity 4400
 10b5  PLX Technology, Inc.
        0001  i960 PCI bus interface
+       0557  PCI9030 32-bit 33MHz PCI <-> IOBus Bridge
+               105b 9030  Digium Tormenta 2 T400P-SS7 or E400P-SS7 Quad T1 or E1 PCI card
+       1000  PCI9030 32-bit 33MHz PCI <-> IOBus Bridge
+               105b 9030  ATCOM AT400P Quad T1 PCI card
        1024  Acromag, Inc. IndustryPack Carrier Card
        1042  Brandywine / jxi2, Inc. - PMC-SyncClock32, IRIG A & B, Nasa 36
        106a  Dual OX16C952 4 port serial adapter [Megawolf Romulus/4]
        1103  VScom 200 2 port serial adaptor
        1146  VScom 010 1 port parallel adaptor
        1147  VScom 020 2 port parallel adaptor
+       2000  PCI9030 32-bit 33MHz PCI <-> IOBus Bridge
+               105b 9030  ATCOM AE400P Quad E1 PCI card
        2540  IXXAT CAN-Interface PC-I 04/PCI
        2724  Thales PCSM Security Card
        3376  Cosateq 4 Port CAN Card
+       4000  PCI9030 32-bit 33MHz PCI <-> IOBus Bridge
+               10b5 9030  Tormenta 3 Varion V400P/ATCOM TE400P Quad E1/T1/J1 PCI card
+       4001  PCI9030 32-bit 33MHz PCI <-> IOBus Bridge
+               105b 9030  ATCOM A400PE Quad E1 PCI card
+       4002  PCI9030 32-bit 33MHz PCI <-> IOBus Bridge
+               105b 9030  ATCOM A400PT Quad T1 PCI card
        6140  PCI6140 32-bit 33MHz PCI-to-PCI Bridge
        6150  PCI6150 32-bit 33MHz PCI-to-PCI Bridge
        6152  PCI6152 32-bit 66MHz PCI-to-PCI Bridge
        8547  PEX 8547 48-lane, 3-port PCI Express Switch
        8548  PEX 8548 48-lane, 9-port PCI Express Switch
        8604  PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch
+       8605  PEX 8605 PCI Express 4-port Gen2 Switch
        8606  PEX 8606 6 Lane, 6 Port PCI Express Gen 2 (5.0 GT/s) Switch
        8608  PEX 8608 8-lane, 8-Port PCI Express Gen 2 (5.0 GT/s) Switch
        8609  PEX 8609 8-lane, 8-Port PCI Express Gen 2 (5.0 GT/s) Switch with DMA
        87b0  PEX 8732 32-lane, 8-Port PCI Express Gen 3 (8.0 GT/s) Switch
        9016  PLX 9016 8-port serial controller
        9030  PCI9030 32-bit 33MHz PCI <-> IOBus Bridge
-               10b5 2695  Hilscher CIF50-PB Profibus Master Board
+               10b5 2695  Hilscher CIF50-PB/DPS Profibus
                10b5 2862  Alpermann+Velte PCL PCI LV (3V/5V): Timecode Reader Board
                10b5 2906  Alpermann+Velte PCI TS (3V/5V): Time Synchronisation Board
                10b5 2940  Alpermann+Velte PCL PCI D (3V/5V): Timecode Reader Board
                10b5 3354  Alpermann+Velte PCL PCIe LV: Timecode Reader Board
                10b5 3355  Alpermann+Velte PCL PCIe L: Timecode Reader Board
                10b5 3415  Alpermann+Velte PCIe TS: Time Synchronisation Board
+               10b5 3493  Alpermann+Velte PCL PCIe 3G: Timecode Reader Board
                1369 c001  LX6464ES
                1369 c201  LX1616ES
                14b4 d10a  DekTec DTA-110T
        a100  Blackmagic Design DeckLink
        bb04  B&B 3PCIOSD1A Isolated PCI Serial
        c001  CronyxOmega-PCI (8-port RS232)
+       d00d  PCI9030 32-bit 33MHz PCI <-> IOBus Bridge
+               10b5 9030  Digium Tormenta 2 T400P or E400P Quad T1 or E1 PCI card
+       d33d  PCI9030 32-bit 33MHz PCI <-> IOBus Bridge
+               105b 9030  Tormenta 3 Varion V401PT Quad T1/J1 PCI card
+       d44d  PCI9030 32-bit 33MHz PCI <-> IOBus Bridge
+               105b 9030  Tormenta 3 Varion V401PE Quad E1 PCI card
+               10b5 17f6  Allo CP100P/E 1-port E1/T1/J1 PCI/PCIe card
+               10b5 17f7  Allo CP400P/E 4-port E1/T1/J1 PCI/PCIe card
+               10b5 17f8  Allo CP200P/E 2-port E1/T1/J1 PCI/PCIe card
 10b6  Madge Networks
        0001  Smart 16/4 PCI Ringnode
        0002  Smart 16/4 PCI Ringnode Mk2
        0259  NV25GL [Quadro4 750 XGL]
        025b  NV25GL [Quadro4 700 XGL]
        0260  MCP51 LPC Bridge
+               103c 2a34  Pavilion a1677c
                103c 30b7  Presario V6133CL
                1043 81bc  A8N-VM CSM Mainboard
                1458 5001  GA-M55plus-S3G
        0262  MCP51 LPC Bridge
        0263  MCP51 LPC Bridge
        0264  MCP51 SMBus
+               103c 2a34  Pavilion a1677c
                103c 30b7  Presario V6133CL
                1043 81bc  A8N-VM CSM Mainboard
                105b 0cad  Winfast 6100K8MB
                1462 7207  K8NGM2 series
        0265  MCP51 IDE
+               103c 2a34  Pavilion a1677c
                103c 30b7  Presario V6133CL
                1043 81bc  A8N-VM CSM Mainboard
                1462 7207  K8NGM2 series
 # Foxconn has used a wrong vendor ID for this one
                f05b 0cad  Winfast 6100K8MB
        0266  MCP51 Serial ATA Controller
+               103c 2a34  Pavilion a1677c
                103c 30b7  Presario V6133CL
                1043 81bc  A8N-VM CSM Mainboard
                1462 7207  K8NGM2 series
        0267  MCP51 Serial ATA Controller
+               103c 2a34  Pavilion a1677c
                1043 81bc  A8N-VM CSM Mainboard
                1462 7207  K8NGM2 series
        0268  MCP51 Ethernet Controller
        0269  MCP51 Ethernet Controller
+               103c 2a34  Pavilion a1677c
                103c 30b7  Presario V6133CL
                1043 8141  A8N-VM CSM Mainboard
                1462 7207  K8NGM2 series
        026b  MCP51 AC97 Audio Controller
                105b 0cad  Winfast 6100K8MB
        026c  MCP51 High Definition Audio
+               103c 2a34  Pavilion a1677c
                103c 30b5  Presario V3242AU
                103c 30b7  Presario V6133CL
                10de cb84  ASUSTeK Computer Inc. A8N-VM CSM Mainboard
                1462 7207  K8NGM2 series
        026d  MCP51 USB Controller
+               103c 2a34  Pavilion a1677c
                103c 30b7  Presario V6133CL
                1043 81bc  A8N-VM CSM Mainboard
                105b 0cad  Winfast 6100K8MB
                1462 7207  K8NGM2 series
        026e  MCP51 USB Controller
+               103c 2a34  Pavilion a1677c
                103c 30b7  Presario V6133CL
                1043 81bc  A8N-VM CSM Mainboard
                105b 0cad  Winfast 6100K8MB
        026f  MCP51 PCI Bridge
                103c 30b7  Presario V6133CL
        0270  MCP51 Host Bridge
+               103c 2a34  Pavilion a1677c
                103c 30b7  Presario V6133CL
                1043 81bc  A8N-VM CSM Mainboard
                105b 0cad  Winfast 6100K8MB
                103c 30b5  Presario V3242AU
                103c 30b7  Presario V6133CL
        0272  MCP51 Memory Controller 0
+               103c 2a34  Pavilion a1677c
                105b 0cad  Winfast 6100K8MB
        027e  C51 Memory Controller 2
+               103c 2a34  Pavilion a1677c
                103c 30b7  Presario V6133CL
                1043 81cd  A8N-VM CSM Mainboard
                1458 5000  GA-M55plus-S3G
                1462 7207  K8NGM2 series
        027f  C51 Memory Controller 3
+               103c 2a34  Pavilion a1677c
                103c 30b7  Presario V6133CL
                1043 81cd  A8N-VM CSM Mainboard
                1458 5000  GA-M55plus-S3G
        02e4  G71 [GeForce 7950 GT]
                1682 2271  PV-T71A-YDF7 (512MB)
        02f0  C51 Host Bridge
+               103c 2a34  Pavilion a1677c
                103c 30b7  Presario V6133CL
                1043 81cd  A8N-VM CSM Mainboard
                1462 7207  K8NGM2 series
        02f6  C51 Host Bridge
        02f7  C51 Host Bridge
        02f8  C51 Memory Controller 5
+               103c 2a34  Pavilion a1677c
                103c 30b7  Presario V6133CL
                1043 81cd  A8N-VM CSM Mainboard
                1458 5000  GA-M55plus-S3G
                1462 7207  K8NGM2 series
        02f9  C51 Memory Controller 4
+               103c 2a34  Pavilion a1677c
                103c 30b7  Presario V6133CL
                1043 81cd  A8N-VM CSM Mainboard
                1458 5000  GA-M55plus-S3G
                1462 7207  K8NGM2 series
        02fa  C51 Memory Controller 0
+               103c 2a34  Pavilion a1677c
                103c 30b7  Presario V6133CL
                1043 81cd  A8N-VM CSM Mainboard
                1458 5000  GA-M55plus-S3G
        02fd  C51 PCI Express Bridge
                103c 30b7  Presario V6133CL
        02fe  C51 Memory Controller 1
+               103c 2a34  Pavilion a1677c
                103c 30b7  Presario V6133CL
                1043 81cd  A8N-VM CSM Mainboard
                1458 5000  GA-M55plus-S3G
                1462 7207  K8NGM2 series
        02ff  C51 Host Bridge
+               103c 2a34  Pavilion a1677c
                103c 30b7  Presario V6133CL
                1043 81cd  A8N-VM CSM Mainboard
                1458 5000  GA-M55plus-S3G
                1849 0562  ALiveNF7G-HDready
        0563  MCP67 PCI Express Bridge
        0568  MCP78S [GeForce 8200] Memory Controller
+               103c 2a9e  Pavilion p6310f
                1043 82e8  M3N72-D
                1462 7508  K9N2GM-FIH
                1849 0568  K10N78FullHD-hSLI R3.0 Memory Controller
        0569  MCP78S [GeForce 8200] PCI Express Bridge
+               103c 2a9e  Pavilion p6310f
                1043 82e8  M3N72-D
                1462 7508  K9N2GM-FIH
                1849 0569  K10N78FullHD-hSLI R3.0 PCI Express Bridge
        06fd  G98 [Quadro NVS 295]
        06ff  G98 [HICx16 + Graphics]
        0751  MCP78S [GeForce 8200] Memory Controller
+               103c 2a9e  Pavilion p6310f
                1043 82e8  M3N72-D
                1462 7508  K9N2GM-FIH
                1849 0751  K10N78FullHD-hSLI R3.0 Memory Controller
        0752  MCP78S [GeForce 8200] SMBus
+               103c 2a9e  Pavilion p6310f
                1043 82e8  M3N72-D
                1462 7508  K9N2GM-FIH
                1849 0752  K10N78FullHD-hSLI R3.0 SMBus
        0753  MCP78S [GeForce 8200] Co-Processor
+               103c 2a9e  Pavilion p6310f
                1043 82e8  M3N72-D
                1462 7508  K9N2GM-FIH
                1849 0753  K10N78FullHD-hSLI R3.0 Co-Processor
        0754  MCP78S [GeForce 8200] Memory Controller
+               103c 2a9e  Pavilion p6310f
                1043 82e8  M3N72-D
                1462 7508  K9N2GM-FIH
                1849 0754  K10N78FullHD-hSLI R3.0 Memory Controller
                1462 7508  K9N2GM-FIH
                1849 0759  K10N78FullHD-hSLI R3.0 IDE
        075a  MCP78S [GeForce 8200] PCI Bridge
+               103c 2a9e  Pavilion p6310f
                1043 82e8  M3N72-D
                1849 075a  K10N78FullHD-hSLI R3.0 PCI Bridge
        075b  MCP78S [GeForce 8200] PCI Express Bridge
+               103c 2a9e  Pavilion p6310f
                1043 82e8  M3N72-D
                1462 7508  K9N2GM-FIH
                1849 075b  K10N78FullHD-hSLI R3.0 PCI Express Bridge
        075c  MCP78S [GeForce 8200] LPC Bridge
+               103c 2a9e  Pavilion p6310f
                1462 7508  K9N2GM-FIH
                1849 075c  K10N78FullHD-hSLI R3.0 LPC Bridge
        075d  MCP78S [GeForce 8200] LPC Bridge
                1043 82e8  M3N72-D
        0760  MCP77 Ethernet
+               103c 2a9e  Pavilion p6310f
                1043 82e8  M3N72-D
                1462 7508  K9N2GM-FIH
                1849 0760  K10N78FullHD-hSLI R3.0 Ethernet
        0762  MCP77 Ethernet
        0763  MCP77 Ethernet
        0774  MCP72XE/MCP72P/MCP78U/MCP78S High Definition Audio
+               103c 2a9e  Pavilion p6310f
 # has a Realtek ALC1200 HDAudio Codec
                1043 82fe  M3N72-D
                1462 7508  K9N2GM-FIH
                1849 3662  K10N78FullHD-hSLI R3.0 High Definition Audio
        0778  MCP78S [GeForce 8200] PCI Express Bridge
+               103c 2a9e  Pavilion p6310f
                1043 82e8  M3N72-D
                1462 7508  K9N2GM-FIH
                1849 0778  K10N78FullHD-hSLI R3.0 PCI Express Bridge
        077a  MCP78S [GeForce 8200] PCI Bridge
+               103c 2a9e  Pavilion p6310f
                1043 82e8  M3N72-D
                1462 7508  K9N2GM-FIH
                1849 077a  K10N78FullHD-hSLI R3.0 PCI Bridge
        077b  MCP78S [GeForce 8200] OHCI USB 1.1 Controller
+               103c 2a9e  Pavilion p6310f
                1043 82e8  M3N72-D
                1462 7508  K9N2GM-FIH
                1849 077b  K10N78FullHD-hSLI R3.0 OHCI USB 1.1 Controller
        077c  MCP78S [GeForce 8200] EHCI USB 2.0 Controller
+               103c 2a9e  Pavilion p6310f
                1043 82e8  M3N72-D
                1462 7508  K9N2GM-FIH
                1849 077c  K10N78FullHD-hSLI R3.0 EHCI USB 2.0 Controller
        077d  MCP78S [GeForce 8200] OHCI USB 1.1 Controller
+               103c 2a9e  Pavilion p6310f
                1043 82e8  M3N72-D
                1462 7508  K9N2GM-FIH
                1849 077d  K10N78FullHD-hSLI R3.0 OHCI USB 1.1 Controller
        077e  MCP78S [GeForce 8200] EHCI USB 2.0 Controller
+               103c 2a9e  Pavilion p6310f
                1043 82e8  M3N72-D
                1462 7508  K9N2GM-FIH
                1849 077e  K10N78FullHD-hSLI R3.0 EHCI USB 2.0 Controller
        0845  C77 [GeForce 8200M G]
        0846  C77 [GeForce 9200]
        0847  C78 [GeForce 9100]
+               103c 2a9e  Pavilion p6310f
        0848  C77 [GeForce 8300]
        0849  C77 [GeForce 8200]
                1462 7508  K9N2GM-FIH
        0865  C79 [GeForce 9300]
        0866  C79 [GeForce 9400M G]
        0867  C79 [GeForce 9400]
+               106b 00ad  iMac 9,1
        0868  C79 [nForce 760i SLI]
        086a  C79 [GeForce 9400]
        086c  C79 [GeForce 9300 / nForce 730i]
        0a65  GT218 [GeForce 210]
                1043 8334  EN210 SILENT
        0a66  GT218 [GeForce 310]
+# taken from nv_disp.inf
+       0a67  GT218 [GeForce 315]
        0a68  G98M [GeForce G105M]
        0a69  G98M [GeForce G105M]
        0a6a  GT218 [NVS 2100M]
        0a87  MCP79 Host Bridge
        0a88  MCP79 Memory Controller
        0a89  MCP79 Memory Controller
+       0a98  MCP79 Memory Controller
+               10de cb79  iMac 9,1
        0aa0  MCP79 PCI Express Bridge
+               10de cb79  Apple iMac 9,1
        0aa2  MCP79 SMBus
+               10de cb79  Apple iMac 9,1
                19da a123  IONITX-F-E
        0aa3  MCP79 Co-processor
+               10de cb79  Apple iMac 9,1
                19da a123  IONITX-F-E
        0aa4  MCP79 Memory Controller
                19da a123  IONITX-F-E
        0aa5  MCP79 OHCI USB 1.1 Controller
+               10de cb79  Apple iMac 9,1
                19da a123  IONITX-F-E
        0aa6  MCP79 EHCI USB 2.0 Controller
+               10de cb79  Apple iMac 9,1
                19da a123  IONITX-F-E
        0aa7  MCP79 OHCI USB 1.1 Controller
+               10de cb79  Apple iMac 9,1
                19da a123  IONITX-F-E
        0aa8  MCP79 OHCI USB 1.1 Controller
        0aa9  MCP79 EHCI USB 2.0 Controller
+               10de cb79  Apple iMac 9,1
                19da a123  IONITX-F-E
        0aaa  MCP79 EHCI USB 2.0 Controller
        0aab  MCP79 PCI Bridge
+               10de cb79  Apple iMac 9,1
        0aac  MCP79 LPC Bridge
        0aad  MCP79 LPC Bridge
                19da a123  IONITX-F-E
        0aae  MCP79 LPC Bridge
+               10de cb79  Apple iMac 9,1
        0aaf  MCP79 LPC Bridge
        0ab0  MCP79 Ethernet
+               10de cb79  Apple iMac 9,1
                19da a123  IONITX-F-E
        0ab1  MCP79 Ethernet
        0ab2  MCP79 Ethernet
        0ab7  MCP79 SATA Controller
        0ab8  MCP79 AHCI Controller
        0ab9  MCP79 AHCI Controller
+               10de cb79  Apple iMac 9,1
        0aba  MCP79 AHCI Controller
        0abb  MCP79 AHCI Controller
        0abc  MCP79 RAID Controller
        0abe  MCP79 RAID Controller
        0abf  MCP79 RAID Controller
        0ac0  MCP79 High Definition Audio
+               10de cb79  Apple iMac 9,1
        0ac1  MCP79 High Definition Audio
        0ac2  MCP79 High Definition Audio
        0ac3  MCP79 High Definition Audio
        0ac4  MCP79 PCI Express Bridge
+               10de cb79  Apple iMac 9,1
        0ac5  MCP79 PCI Express Bridge
        0ac6  MCP79 PCI Express Bridge
+               10de cb79  Apple iMac 9,1
        0ac7  MCP79 PCI Express Bridge
+               10de cb79  Apple iMac 9,1
        0ac8  MCP79 PCI Express Bridge
        0ad0  MCP78S [GeForce 8200] SATA Controller (non-AHCI mode)
                1462 7508  K9N2GM-FIH
                1849 0ad0  K10N78FullHD-hSLI R3.0 IDE
        0ad4  MCP78S [GeForce 8200] AHCI Controller
+               103c 2a9e  Pavilion p6310f
                1043 82e8  M3N72-D
                1849 0ad4  K10N78FullHD-hSLI R3.0 AHCI Controller
        0ad8  MCP78S [GeForce 8200] SATA Controller (RAID mode)
        0ca2  GT215 [GeForce GT 320]
        0ca3  GT215 [GeForce GT 240]
        0ca4  GT215 [GeForce GT 340]
+# taken from nv_disp.inf
+       0ca5  GT215 [GeForce GT 220]
        0ca7  GT215 [GeForce GT 330]
        0ca8  GT215 [GeForce GTS 260M]
        0ca9  GT215 [GeForce GTS 250M]
+# GT215, not GT216 per http://www.techpowerup.com/gpuz/594cm/
+       0cac  GT215 [GeForce GT 220]
        0caf  GT215 [GeForce GT 335M]
        0cb0  GT215 [GeForce GTS 350M]
        0cb1  GT215 [GeForce GTS 360M]
        0d94  MCP89 High Definition Audio
        0d9c  MCP89 OHCI USB 1.1 Controller
        0d9d  MCP89 EHCI USB 2.0 Controller
+# taken from nv_disp.inf
+       0dc0  GF108 [GeForce GT 440]
        0dc4  GF106 [GeForce GTS 450]
+# taken from nv_disp.inf
+       0dc5  GF106 [GeForce GTS 450]
+# taken from nv_disp.inf
+       0dc6  GF106 [GeForce GTS 450]
        0dcd  GF106 [GeForce GT 555M]
        0dce  GF106 [GeForce GT 555M]
 # rev a1
                1558 8687  CLEVO/KAPOK W860CU
        0dd2  GF106 [GeForce GT 445M]
        0dd8  GF106GL [Quadro 2000]
-       0dda  GF106 [Quadro 2000M]
+# NVIDIA calls it GF106GML
+       0dda  GF106GLM [Quadro 2000M]
        0de0  GF108 [GeForce GT 440]
        0de1  GF108 [GeForce GT 430]
                3842 1430  GeForce GT 430
        0de2  GF108 [GeForce GT 420]
-       0de9  GeForce GT 630M
+# taken from nv_disp.inf
+       0de4  GF108 [GeForce GT 520]
+# taken from nv_disp.inf
+       0de5  GF108 [GeForce GT 530]
+       0de9  GF108 [GeForce GT 630M]
 # Not fully sure that it's GF108, might also be GF106.
        0deb  GF108 [GeForce GT 555M]
        0dee  GF108 [GeForce GT 415M]
        0def  GF108 [Quadro NVS 5400M]
        0df0  GF108 [GeForce GT 425M]
+       0df1  GF108 [GeForce GT 420M]
        0df2  GF108 [GeForce GT 435M]
        0df4  GF108 [GeForce GT 540M]
        0df5  GF108 [GeForce GT 540M]
        0df7  GF108 [GeForce GT 520M]
-       0df8  GF108 [Quadro 600]
-       0df9  GF108 [Quadro 500M]
-       0dfa  GF108 [Quadro 1000M]
+# NVIDIA calls it GL
+       0df8  GF108GL [Quadro 600]
+# NVIDIA calls it GLM
+       0df9  GF108GLM [Quadro 500M]
+# NVIDIA calls it GLM
+       0dfa  GF108GLM [Quadro 1000M]
        0e08  GF119 HDMI Audio Controller
        0e09  GF110 High Definition Audio Controller
        0e0a  GK104 HDMI Audio Controller
        0e0c  GF114 HDMI Audio Controller
+       0e1b  GK107 HDMI Audio Controller
+               1043 8428  GTX650-DC-1GD5
        0e22  GF104 [GeForce GTX 460]
                1462 2322  N460GTX Cyclone 1GD5/OC
+# taken from nv_disp.inf
+       0e23  GF104 [GeForce GTX 460 SE]
+# taken from nv_disp.inf
+       0e24  GF104 [GeForce GTX 460]
        0e3a  GF104 [Quadro 3000M]
        0e3b  GF104 [Quadro 4000M]
+       0f00  GK107 [GeForce GT 630]
+# Probably GF108
+       0f01  GeForce GT 620
+# taken from nv_disp.inf
+       0fc0  GK107 [GeForce GT 640]
+# taken from nv_disp.inf
+       0fc1  GK107 [GeForce GT 640]
+       0fc6  GK107 [GeForce GTX 650]
+               1043 8428  GTX650-DC-1GD5
        0fd1  GK107 [GeForce GT 650M]
+               1043 2103  N56VZ
        0fd2  GK107 [GeForce GT 640M]
+       0ff2  GK107 [VGX K1]
+       0ffa  GK107 [Quadro K600]
        0ffb  GK107 [Quadro K2000M]
        0ffc  GK107 [Quadro K1000M]
+       0ffe  GK107 [Quadro K2000]
+       0fff  GK107 [Quadro 410]
        1040  GF119 [GeForce GT 520]
+# taken from nv_disp.inf
+       1042  GF119 [GeForce 510]
+# taken from nv_disp.inf
+       1048  GF119 [GeForce 605]
+# taken from nv_disp.inf
+       1049  GF119 [GeForce GT 620]
+# taken from nv_disp.inf
+       104a  GF119 [GeForce GT 610]
        1050  GF119 [GeForce GT 520M]
        1051  GF119 [GeForce GT 520MX]
+       1055  GF119 [GeForce 410M]
        1056  GF119 [Quadro NVS 4200M]
        1057  GF119 [Quadro NVS 4200M]
        105a  GF119 [GeForce 610M]
+       107d  GF119 [Quadro NVS 310]
        1080  GF110 [GeForce GTX 580]
        1081  GF110 [GeForce GTX 570]
                10de 087e  Leadtek WinFast GTX 570
        1082  GF110 [GeForce GTX 560 Ti]
+# taken from nv_disp.inf
+       1084  GF110 [GeForce GTX 560]
        1086  GF110 [GeForce GTX 570 HD]
        1087  GF110 [GeForce GTX 560 Ti 448 Cores]
+# taken from nv_disp.inf
+       1088  GF110 [GeForce GTX 590]
+# taken from nv_disp.inf
+       1089  GF110 [GeForce GTX 580]
+# taken from nv_disp.inf
+       108b  GF110 [GeForce GTX 580]
        1091  Tesla M2090
        1094  Tesla M2075 Dual-Slot Computing Processor Module
        1096  Tesla C2075
        1183  GK104 [GeForce GTX 660 Ti]
        1188  GK104 [GeForce GTX 690]
        1189  GK104 [GeForce GTX 670]
+       11ba  GK104 [Quadro K5000]
        11bc  GK104 [Quadro K5000M]
        11bd  GK104 [Quadro K4000M]
        11be  GK104 [Quadro K3000M]
+       11bf  GK104GL [VGX K2]
+       11fa  GK104 [Quadro K4000]
        1200  GF114 [GeForce GTX 560 Ti]
        1201  GF114 [GeForce GTX 560]
        1205  GF114 [GeForce GTX 460 v2]
+# taken from nv_disp.inf
+       1206  GF114 [GeForce GTX 555]
+# taken from nv_disp.inf
+       1207  GF114 [GeForce GTX 645]
+# taken from nv_disp.inf
+       1208  GF114 [GeForce GTX 560 SE]
+       1210  GF114 [GeForce GTX 570M]
+# GT, not GTX
+       1241  GF116 [GeForce GT 545]
+# GT, not GTX
+       1243  GF116 [GeForce GT 545]
        1244  GF116 [GeForce GTX 550 Ti]
        1245  GF116 [GeForce GTS 450]
-       1247  GF106 [GeForce GT 555M]
+       1247  GF116 [GeForce GT 555M]
+# taken from nv_disp.inf
+       1249  GF116 [GeForce GTS 450]
+# taken from nv_disp.inf
+       124b  GF116 [GeForce GT 640]
 10df  Emulex Corporation
        0720  OneConnect NIC (Skyhawk)
        0722  OneConnect iSCSI Initiator (Skyhawk)
        0885  Realtek 885 High Definition Audio
        0888  Realtek 888 High Definition Audio
                1028 020d  Inspiron 530
+       0892  Realtek 892 High Definition Audio
        5209  RTS5209 PCI Express Card Reader
        5229  RTS5229 PCI Express Card Reader
        5288  Barossa PCI Express Card Reader
        0009  [SB X-Fi Xtreme Audio] CA0110-IBG
                1102 0010  [SB X-Fi Xtreme Audio] CA0110-IBG
                1102 0018  SB1040
-       000b  X-Fi Titanium series [EMU20k2]
-               1102 0041  SB X-Fi Titanium PCI-e [SB0880]
+       000b  EMU20k2 [X-Fi Titanium Series]
+               1102 0041  SB0880 [SoundBlaster X-Fi Titanium PCI-e]
        4001  SB Audigy FireWire Port
                1102 0010  SB Audigy FireWire Port
        7002  SB Live! Game Port
                0010 0001  IEEE 1394 4port DCST 1394-3+1B
                1025 005a  TravelMate 290
                103c 2a20  Pavilion t3030.de Desktop PC
+               103c 2a3b  Media Center PC m7590n
                1043 808a  A8V/A8N/P4P800 series motherboard
                1043 81fe  M4A series motherboard
                1458 1000  GA-7VT600-1394 Motherboard
        3409  VX855/VX875 DRAM Bus Control
        3410  VX900 DRAM Bus Control
                19da a179  ZBOX nano VD01
+       3432  VL80x xHCI USB 3.0 Controller
        4149  VIA VT6420 (ATA133) Controller
        4204  K8M800 Host Bridge
        4208  PT890 Host Bridge
        5410  VX900 APIC and Central Traffic Control
        6100  VT85C100A [Rhine II]
        6287  SATA RAID Controller
+       6290  K8M890CE Host Bridge
        6327  P4M890 Security Device
        6353  VX800/VX820 Scratch Registers
        6364  CN896/VN896/P4M900 Security Device
        4000  DL2000-based Gigabit Ethernet
        4001  DGE-550SX PCI-X Gigabit Ethernet Adapter
        4300  DGE-528T Gigabit Ethernet Adapter
+# rev. B1; RealTek RTL8168E.
+               1186 4b10  DGE-560T PCI Express (x1) Gigabit Ethernet Adapter
        4302  DGE-530T Gigabit Ethernet Adapter (rev.C1) [Realtek RTL8169]
 # There are at least 3 revisions of this adapter; 4800 is board revision A1 as far as I can tell, revision B1 is 4c00.
        4800  DGE-530T Gigabit Ethernet Adapter (rev 11)
        4353  88E8039 PCI-E Fast Ethernet Controller
                104d 902d  VAIO VGN-NR120E
        4354  88E8040 PCI-E Fast Ethernet Controller
+               144d c072  Notebook N150P
        4355  88E8040T PCI-E Fast Ethernet Controller
                1179 ff50  Satellite P305D-S8995E
        4356  88EC033 PCI-E Fast Ethernet Controller
        5802  USS-312 USB Controller
        5803  USS-344S USB Controller
        5811  FW322/323 [TrueFire] 1394a Controller
-               1043 8294  IEEE 1394a Firewire Controller
+               103c 2a34  Pavilion a1677c
+               103c 2a9e  Pavilion p6310f
+               1043 8294  LSI FW322/323 IEEE 1394a FireWire Controller
                8086 524c  D865PERL mainboard
                dead 0800  FireWire Host Bus Adapter
        5901  FW643 [TrueFire] PCIe 1394b Controller
        0805  RocketPort UPCI 8 port w/octa cable
        080c  RocketModem III 8 port
        080d  RocketModem III 4 port
+       0810  RocketPort UPCI Plus 4 port RS232
        0811  RocketPort UPCI Plus 8 port RS232
        0812  RocketPort UPCI Plus 8 port RS422
        0903  RocketPort Compact PCI 16 port w/external I/F
        5201  PCI-2000
 1257  Vertex Networks, Inc.
 1258  Gilbarco, Inc.
-1259  Allied Telesyn International
+# nee Allied Telesyn International
+1259  Allied Telesis
        2560  AT-2560 Fast Ethernet Adapter (i82557B)
        2801  AT-2801FX (RTL-8139)
        a117  RTL81xx Fast Ethernet
                125d 1989  ESS Modem
        1998  ES1983S Maestro-3i PCI Audio Accelerator
                1028 00b1  Latitude C600
+               1028 00e5  Latitude C810
                1028 00e6  ES1983S Maestro-3i (Dell Inspiron 8100)
        1999  ES1983S Maestro-3i PCI Modem Accelerator
        199a  ES1983S Maestro-3i PCI Audio Accelerator
 12d7  Biotronic SRL
 12d8  Pericom Semiconductor
        01a7  PI7C21P100 PCI to PCI Bridge
+       400a  PI7C9X442SL PCI Express Bridge Port
+       400e  PI7C9X442SL USB OHCI Controller
+       400f  PI7C9X442SL USB EHCI Controller
        71e2  PI7C7300A/PI7C7300D PCI-to-PCI Bridge
        71e3  PI7C7300A/PI7C7300D PCI-to-PCI Bridge (Secondary Bus 2)
        8140  PI7C8140A PCI-to-PCI Bridge
        0067  PCI-DAS6070
        0068  PCI-DAS6071
        006f  PCI-DAS6036
+       0070  PCI-DAC6702
        0078  PCI-DAS6013
        0079  PCI-DAS6014
        0115  PCIe-DAS1602/16
 134f  Algo System Co Ltd
 1350  Systec Co. Ltd
 1351  Sonix Inc
-1353  Thales Idatys
+# nee Thales Idatys
+1353  Vierling Communication SAS
        0002  Proserver
        0003  PCI-FUT
        0004  PCI-S0
                13f6 ffff  CMI8338/C3DX PCI Audio Device
        0101  CM8338B
                13f6 0101  CMI8338-031 PCI Audio Device
-       0111  CM8738
+       0111  CMI8738/CMI8768 PCI Audio
                1019 0970  P6STP-FL motherboard
                1043 8035  CUSI-FX motherboard
                1043 8077  CMI8738 6-channel audio controller
                584d 3771  X-Mystique 7.1 LP Value
                7284 8384  Striker 7.1
        0211  CM8738
+       5011  CM8888 [Oxygen Express]
+               13f6 5011  HDA Controller
        8788  CMI8788 [Oxygen HD Audio]
                1043 8269  Virtuoso 200 (Xonar D2)
                1043 8275  Virtuoso 100 (Xonar DX)
                7284 9761  CLARO
                7284 9781  CLARO halo
                7284 9783  eCLARO
-       8828  CM8828 [Oxygen Express]
-       8888  CM8888 [Oxygen Express]
-               1043 84d5  ROG Xonar Phoebus
+               7284 9787  CLARO II
        9880  CM9880
 13f7  Wildfire Communications
 13f8  Ad Lib Multimedia Inc
                153b 1151  PHASE88
                16ce 1040  Edirol DA-2496
        1724  VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller
+               10b0 0200  Hollywood@Home 7.1
                1412 1724  Albatron PX865PE 7.1
                1412 3630  M-Audio Revolution 7.1
                1412 3631  M-Audio Revolution 5.1
        9521  OX16PCI952 (Dual 16950 UART)
        9523  OX16PCI952 Integrated Parallel Port
        c158  OXPCIe952 Dual 16C950 UART
+               e4bf c504  CP4-SCAT Wireless Technologies Carrier Board
+               e4bf d551  DU1-MUSTANG Dual-Port RS-485 Interface
        c308  EX-44016 16-port serial
 1416  Multiwave Innovation pte Ltd
 1417  Convergenet Technologies Inc
        4008  T420-CX Unified Wire Ethernet Controller
        4009  T420-BT Unified Wire Ethernet Controller
        400a  T404-BT Unified Wire Ethernet Controller
+       400b  B420-SR Unified Wire Ethernet Controller
+       400c  B404-BT Unified Wire Ethernet Controller
        400d  T480 Unified Wire Ethernet Controller
        400e  T440-LP-CR Unified Wire Ethernet Controller
        4401  T420-CR Unified Wire Ethernet Controller
        4408  T420-CX Unified Wire Ethernet Controller
        4409  T420-BT Unified Wire Ethernet Controller
        440a  T404-BT Unified Wire Ethernet Controller
+       440b  B420-SR Unified Wire Ethernet Controller
+       440c  B404-BT Unified Wire Ethernet Controller
        440d  T480 Unified Wire Ethernet Controller
        440e  T440-LP-CR Unified Wire Ethernet Controller
        4501  T420-CR Unified Wire Storage Controller
        4508  T420-CX Unified Wire Storage Controller
        4509  T420-BT Unified Wire Storage Controller
        450a  T404-BT Unified Wire Storage Controller
+       450b  B420-SR Unified Wire Ethernet Controller
+       450c  B404-BT Unified Wire Ethernet Controller
        450d  T480 Unified Wire Storage Controller
        450e  T440-LP-CR Unified Wire Storage Controller
        4601  T420-CR Unified Wire Storage Controller
        4608  T420-CX Unified Wire Storage Controller
        4609  T420-BT Unified Wire Storage Controller
        460a  T404-BT Unified Wire Storage Controller
+       460b  B420-SR Unified Wire Ethernet Controller
+       460c  B404-BT Unified Wire Ethernet Controller
        460d  T480 Unified Wire Storage Controller
        460e  T440-LP-CR Unified Wire Storage Controller
        4701  T420-CR Unified Wire Ethernet Controller
        4708  T420-CX Unified Wire Ethernet Controller
        4709  T420-BT Unified Wire Ethernet Controller
        470a  T404-BT Unified Wire Ethernet Controller
+       470b  B420-SR Unified Wire Ethernet Controller
+       470c  B404-BT Unified Wire Ethernet Controller
        470d  T480 Unified Wire Ethernet Controller
        470e  T440-LP-CR Unified Wire Ethernet Controller
        4801  T420-CR Unified Wire Ethernet Controller
        4808  T420-CX Unified Wire Ethernet Controller
        4809  T420-BT Unified Wire Ethernet Controller
        480a  T404-BT Unified Wire Ethernet Controller
+       480b  B420-SR Unified Wire Ethernet Controller
+       480c  B404-BT Unified Wire Ethernet Controller
        480d  T480 Unified Wire Ethernet Controller
        480e  T440-LP-CR Unified Wire Ethernet Controller
        a000  PE10K Unified Wire Ethernet Controller
                14c1 0008  10G-PCIE-8A
                14c1 0009  10G-PCIE-8A (MSI-X firmware)
                14c1 000a  10G-PCIE-8B
-               14c1 000b  10G-PCIE-8B2
-               14c1 000c  10G-PCIE2-8B2
        8043  Myrinet 2000 Scalable Cluster Interconnect
                103c 1240  Myrinet M2L-PCI64/2-3.0 LANai 7.4 (HP OEM)
 14c2  DTK Computer
                1028 01c2  Latitude D620
                103c 3015  PCIe LAN on Motherboard
                107b 5048  E4500 Onboard
+               1259 2705  AT-2711FX
        1601  NetXtreme BCM5752M Gigabit Ethernet PCI Express
        1612  BCM70012 Video Decoder [Crystal HD]
        1615  BCM70015 Video Decoder [Crystal HD]
        163d  NetXtreme II BCM57811 10-Gigabit Ethernet
        163e  NetXtreme II BCM57811 10 Gigabit Ethernet Multi Function
        163f  NetXtreme II BCM57811 10-Gigabit Ethernet Virtual Function
+       1641  NetXtreme BCM57787 Gigabit Ethernet PCIe
+       1642  NetXtreme BCM57764 Gigabit Ethernet PCIe
+       1643  NetXtreme BCM5725 Gigabit Ethernet PCIe
        1644  NetXtreme BCM5700 Gigabit Ethernet
                1014 0277  Broadcom Vigil B5700 1000Base-T
                1028 00d1  Broadcom BCM5700
        165f  NetXtreme BCM5720 Gigabit Ethernet PCIe
        1662  NetXtreme II BCM57712 10 Gigabit Ethernet
        1663  NetXtreme II BCM57712 10 Gigabit Ethernet Multi Function
+       1665  NetXtreme BCM5717 Gigabit Ethernet PCIe
        1668  NetXtreme BCM5714 Gigabit Ethernet
                103c 7039  NC324i PCIe Dual Port Gigabit Server Adapter
        1669  NetXtreme 5714S Gigabit Ethernet
        1680  NetXtreme BCM5761e Gigabit Ethernet PCIe
        1681  NetXtreme BCM5761 Gigabit Ethernet PCIe
        1682  NetXtreme BCM57762 Gigabit Ethernet PCIe
+       1683  NetXtreme BCM57767 Gigabit Ethernet PCIe
        1684  NetXtreme BCM5764M Gigabit Ethernet PCIe
        1685  NetXtreme II BCM57500S Gigabit Ethernet
        1686  NetXtreme BCM57766 Gigabit Ethernet PCIe
+       1687  NetXtreme BCM5762 Gigabit Ethernet PCIe
+       1688  NetXtreme BCM5761 10/100/1000BASE-T Ethernet
+               1259 2708  AT-2712 FX
 # The Broadcom 57800 device has two 1Gig ports and two 10Gig ports. The subsystem information can be used to differentiate.
        168a  NetXtreme II BCM57800 1/10 Gigabit Ethernet
                1028 1f5c  BCM57800 10-Gigabit Ethernet
                1028 1f68  BCM57800 1-Gigabit Ethernet
        168d  NetXtreme II BCM57840 10/20 Gigabit Ethernet
        168e  NetXtreme II BCM57810 10 Gigabit Ethernet
+               103c 1798  Flex-10 10Gb 2-port 530FLB Adapter [Meru]
        1690  NetXtreme BCM57760 Gigabit Ethernet PCIe
        1691  NetLink BCM57788 Gigabit Ethernet PCIe
                1028 04aa  XPS 8300
        432d  BCM4322 802.11an Wireless Network Controller
        4331  BCM4331 802.11a/b/g/n
                106b 00d6  AirPort Extreme
+       4333  Serial (EDGE/GPRS modem part of Option GT Combo Edge)
        4344  EDGE/GPRS data and 802.11b/g combo cardbus [GC89]
        4353  BCM43224 802.11a/b/g/n
                1028 000e  Wireless 1520 Half-size Mini PCIe Card
        4359  BCM43228 802.11a/b/g/n
                1028 0011  Wireless 1530 Half-size Mini PCIe Card
                103c 182c  BCM943228HM4L 802.11a/b/g/n 2x2 Wi-Fi Adapter
+       4365  BCM43142 802.11b/g/n
+               1028 0016  Wireless 1704 802.11n + BT 4.0
        4401  BCM4401 100Base-T
                1025 0035  TravelMate 660
                103c 08b0  tc1100 tablet
        8852  CX23885 PCI Video and Audio Decoder
                0070 8010  Hauppauge WinTV HVR-1400 ExpressCard
                1461 c039  AVerTV Hybrid Express (A577)
+               153b 117e  Cinergy T PCIe Dual
                18ac db78  FusionHDTV DVB-T Dual Express
        8880  CX23887/8 PCIe Broadcast Audio and Video Decoder with 3D Comb
                0070 c108  WinTV-HVR-4400-HD model 1278
        07c0  PVSCSI SCSI Controller
        0801  Virtual Machine Interface
                15ad 0800  Hypervisor ROM Interface
+       1977  HD Audio Controller
 15ae  Amersham Pharmacia Biotech
 15b0  Zoltrix International Ltd
 15b1  Source Technology Inc
 15b3  Mellanox Technologies
        0191  MT25408 [ConnectX IB Flash Recovery]
        01f6  MT27500 Family [ConnectX-3 Flash Recovery]
+       01ff  MT27600 Family [Connect-IB Flash Recovery]
        1002  MT25400 Family [ConnectX-2 Virtual Function]
        1003  MT27500 Family [ConnectX-3]
        1004  MT27500 Family [ConnectX-3 Virtual Function]
        100e  MT27551 Family
        100f  MT27560 Family
        1010  MT27561 Family
+       1011  MT27600 [Connect-IB]
+       1012  MT27600 Family [Connect-IB Virtual Function]
+       1013  MT27620 Family
+       1014  MT27621 Family
+       1015  MT27630 Family
+       1016  MT27631 Family
        5274  MT21108 InfiniBridge
        5a44  MT23108 InfiniHost
        5a45  MT23108 [Infinihost HCA Flash Recovery]
        002d  AR9227 Wireless Network Adapter
        002e  AR9287 Wireless Network Adapter (PCI-Express)
        0030  AR9300 Wireless LAN adaptor
-               103c 1627  HB112AGN 802.11abgn 3x3 Wi-Fi Adapter
+               103c 1627  AR9380/HB112 802.11abgn 3×3 Wi-Fi Adapter
                1a56 2000  Killer Wireless-N 1102 Half-size Mini PCIe Card [AR9382]
                1a56 2001  Killer Wireless-N 1103 Half-size Mini PCIe Card [AR9380]
        0032  AR9485 Wireless Network Adapter
+               103c 1838  AR9485/HB125 802.11bgn 1×1 Wi-Fi Adapter
        0033  AR9580 Wireless Network Adapter
        0034  AR9462 Wireless Network Adapter
+       0036  AR9565 Wireless Network Adapter
        0207  AR5210 Wireless Network Adapter [AR5000 802.11a]
        1014  AR5212 802.11abg NIC
                1014 058a  ThinkPad 11a/b/g Wireless LAN Mini Express Adapter (AR5BXB6)
        5807  XMC-SLX150: Reconfigurable Spartan-6 FPGA with plug-in I/O
        5808  XMC-SLX150-1M: Reconfigurable Spartan-6 FPGA with plug-in I/O
        5901  APCe8650 PCI Express IndustryPack Carrier Card
+       6301  XMC Module with user-configurable Virtex-6 FPGA, 240k logic cells, SFP front I/O
+       6302  XMC Module with user-configurable Virtex-6 FPGA, 365k logic cells, SFP front I/O
+       6303  XMC Module with user-configurable Virtex-6 FPGA, 240k logic cells, no front I/O
+       6304  XMC Module with user-configurable Virtex-6 FPGA, 365k logic cells, no front I/O
 16da  Advantech Co., Ltd.
        0011  INES GPIB-PCI
 16df  PIKA Technologies Inc.
                1799 700e  F5D7000 v6000 Wireless G Desktop Card
                1799 701e  F5D7010 v6000 Wireless G Notebook Card
                17f9 0012  AWLC3026T 802.11g Wireless CardBus Adapter
-               1814 2561  EW-7108PCg
+               1814 2561  EW-7108PCg/EW-7128g
        0302  RT2561/RT61 rev B 802.11g
                1186 3a71  DWA-510 Wireless G Desktop Adapter
                1186 3c08  AirPlus G DWL-G630 Wireless Cardbus Adapter (rev.E2)
                13bd 1057  GN-WS32L-RH Half-size Mini PCIe Card
        3091  RT3091 Wireless 802.11n 1T/2R PCIe
        3092  RT3092 Wireless 802.11n 2T/2R PCIe
-       3592  RT3592 Wireless 802.11an 2T/2R PCIe
+       3290  RT3290 Wireless 802.11n 1T/1R PCIe
+       3298  RT3290 Bluetooth
+       3592  RT3592 Wireless 802.11abgn 2T/2R PCIe
        5360  RT5360 Wireless 802.11n 1T/1R
                1186 3c05  DWA-525 Wireless N 150 Desktop Adapter (rev.A2)
                20f4 703a  TEW-703PI N150 Wireless PCI Adapter
 18ca  XGI Technology Inc. (eXtreme Graphics Innovation)
        0020  Z7/Z9 (XG20 core)
        0021  Z9s/Z9m (XG21 core)
-# duh! Device name, not my name :)
        0027  Z11/Z11M
        0040  Volari V3XT/V5/V8
        0047  Volari 8300 (chip: XP10, codename: XG47)
 18f1  Spectrum GmbH
 18f4  Napatech A/S
        0031  NT20X Network Adapter
-       0051  NT20-X Capture Card
+       0051  NT20X Capture Card
        0061  NT20E Capture Card
        0064  NT20E Inline Card
        0071  NT4E Capture Card
        0091  NT20X Capture Card [New Rev]
        00a1  NT4E-STD Capture Card
        00a4  NT4E-STD Inline Card
+# 8 x 1 Gbps / 10 Gbps PCIe Optical Bypass Adapter
+       00b1  NTBPE Optical Bypass Adapter
        00c5  NT20E2 Network Adapter 2x10Gb
        00d5  NT40E2-4 Network Adapter 4x10Gb
        00e5  NT40E2-1 Network Adapter 1x40Gb
+# 4-Port Adapter for 1 GbE In-Line Bypass Applications
+       00f5  NT4E2-4T-BP Network Adapter 4x1Gb with Electrical Bypass
 18f6  NextIO
        1000  [Nexsis] Switch Virtual P2P PCIe Bridge
        1050  [Nexsis] Switch Virtual P2P PCI Bridge
        2000  [Nexsis] Switch Integrated Mgmt. Endpoint
 18f7  Commtech, Inc.
-       0001  Fastcom ESCC-PCI-335
-       0002  Fastcom 422/4-PCI-335
-       0003  Fastcom 232/4-1M-PCI
-       0004  Fastcom 422/2-PCI-335
-       0005  Fastcom IGESCC-PCI-ISO/1
-       000a  Fastcom 232/4-PCI-335
-       000b  Fastcom 232/8-PCI-335 Async 8-Port RS-232 Serial PCI Adapter
-       000f  Fastcom FSCC
-       0010  Fastcom GSCC
-# Dual Serocco
-       0011  Fastcom QSSB
-       0014  SuperFSCC
-       0015  SuperFSCC-104
-       0016  Fastcom FSCC-232 Sync/Async 2-Port RS-232 Serial PCI Adapter (F-Core)
-       0017  SuperFSCC-104-NOUART
-       0018  Fastcom SuperFSCC/4 Sync/Async 4-Port RS-422 Serial PCI Adapter with DMA (F-Core)
-       0019  SuperFSCC with soft UARTs
-       001a  Fastcom SuperFSCC-104-LVDS Sync/Async 2-Port RS-644 Serial PC/104+ Adapter with DMA (F-Core)
-       001b  Fastcom FSCC/4 Sync/Async 4-Port RS-422 Serial PCI Adapter (F-Core)
-       001c  Fastcom SuperFSCC/4-LVDSSync/Async 4-Port RS-644 Serial PCI Adapter with DMA (F-Core)
+       0001  ESCC-PCI-335 Serial PCI Adapter [Fastcom]
+       0002  422/4-PCI-335 Serial PCI Adapter [Fastcom]
+       0003  232/4-1M-PCI Serial PCI Adapter [Fastcom]
+       0004  422/2-PCI-335 Serial PCI Adapter [Fastcom]
+       0005  IGESCC-PCI-ISO/1 Serial PCI Adapter [Fastcom]
+       000a  232/4-PCI-335 Serial PCI Adapter [Fastcom]
+       000b  232/8-PCI-335 Serial PCI Adapter [Fastcom]
+       000f  FSCC Serial PCI Adapter [Fastcom]
+       0010  GSCC Serial PCI Adapter [Fastcom]
+       0011  QSSB Serial PCI Adapter [Fastcom]
+       0014  SuperFSCC Serial PCI Adapter [Fastcom]
+       0015  SuperFSCC-104 Serial PCI/104+ Adapter [Fastcom]
+       0016  FSCC-232 RS-232 Serial PCI Adapter [Fastcom]
+# Synchronous Only
+       0017  SuperFSCC-104-NOUART Serial PCI/104+ Adapter [Fastcom]
+       0018  SuperFSCC/4 Serial PCI Adapter [Fastcom]
+       0019  SuperFSCC Serial PCI Adapter [Fastcom]
+# RS-644 Only
+       001a  SuperFSCC-104-LVDS Serial PC/104+ Adapter [Fastcom]
+       001b  FSCC/4 Serial PCI Adapter [Fastcom]
+# RS-644 Only
+       001c  SuperFSCC/4-LVDS Serial PCI Adapter [Fastcom]
+       0020  422/4-PCIe Serial PCIe Adapter [Fastcom]
+       0021  422/8-PCIe Serial PCIe Adapter [Fastcom]
 18fb  Resilience Corporation
 1904  Hangzhou Silan Microelectronics Co., Ltd.
        2031  SC92031 PCI Fast Ethernet Adapter
        0011  SH7757 PCIe End-Point [PBI]
        0012  SH7757 PCIe-PCI Bridge [PPB]
        0013  SH7757 PCIe Switch [PS]
+       0014  uPD720201 USB 3.0 Host Controller
 1919  Soltek Computer Inc.
 1923  Sangoma Technologies Corp.
        0040  A200/Remora FXO/FXS Analog AFT card
                1924 5201  SFN4112F-R1
                1924 5202  SFN4112F-R2
        0803  SFC9020 [Solarstorm]
+               1924 1201  SFA6902F-R1 SFP+ AOE Adapter
                1924 6200  SFN5122F-R0
                1924 6201  SFN5122F-R1
                1924 6202  SFN5122F-R2
                1924 6501  SFN5802K-R1
                1924 6511  SFN5814H-R1
                1924 6521  SFN5812H-R1
+               1924 6562  SFN6832F-R2 SFP+ Mezzanine Adapter
                1924 6a05  SFN5112F-R5
                1924 6a06  SFN5112F-R6
                1924 7206  SFN5162F-R6
                1924 0304  SFE4003-A4
                1924 0500  SFE4005-A0
        c101  EF1-21022T [EtherFabric]
+192a  BiTMICRO Networks Inc.
 192e  TransDimension
 1931  Option N.V.
        000c  Qualcomm MSM6275 UMTS chip
        1062  AR8132 Fast Ethernet
        1063  AR8131 Gigabit Ethernet
                1458 e000  GA-G31M-ES2L Motherboard
-       1066  L2c Gigabit Ethernet
-       1067  L1c Gigabit Ethernet
+       1066  Attansic L2c Gigabit Ethernet
+       1067  Attansic L1c Gigabit Ethernet
        1073  AR8151 v1.0 Gigabit Ethernet
        1083  AR8151 v2.0 Gigabit Ethernet
        1090  AR8162 Fast Ethernet
        1091  AR8161 Gigabit Ethernet
-       2048  L2 Fast Ethernet
+               1043 1477  N56VZ
+       2048  Attansic L2 Fast Ethernet
        2060  AR8152 v1.1 Fast Ethernet
        2062  AR8152 v2.0 Fast Ethernet
 196a  Sensory Networks Inc.
        0200  TILE-Gx36 processor
 1a4a  SLAC National Accelerator Lab PPA-REG
        1000  MCOR Power Supply Controller
+       1010  AMC EVR - Stockholm Timing Board
        2000  PGPCard - 4 Lane
        2010  PCI-Express EVR
 1a51  Hectronic AB
+1a55  Rohde & Schwarz DVS GmbH
+       0010  SDStationOEM
+       0011  SDStationOEM II
+       0020  Centaurus
+       0021  Centaurus II
+       0022  Centaurus II LT
+       0030  CLIPSTER-VPU 1.x (Hugo)
+       0040  Hydra Cinema (JPEG)
+       0050  CLIPSTER-VPU 2.x (DigiLab)
+       0060  CLIPSTER-DCI 2.x (HydraX)
+       0061  Atomix
+       0062  Atomix LT
+       0063  Atomix HDMI
+       0064  Atomix STAN
+       0065  Atomix HDMI STAN
+       0070  RED Rocket
+       0090  CinePlay
 1a56  Bigfoot Networks, Inc.
 1a57  Highly Reliable Systems
 1a58  Razer USA Ltd.
                1a78 0037  FlashMAX PCIe SSD [rev 3D]
                1a78 0038  FlashMAX PCIe SSD [rev 4]
                1a78 0039  FlashMAX PCIe SSD [rev 4D]
-       0040  Virident FlashMAX Drive V2
-               1a78 0040  PCIe SSD [LP Z1]
+       0040  FlashMAX II
 1a84  Commex Technologies
        0001  Vulcan SP HT6210 10-Gigabit Ethernet (rev 02)
 1a88  MEN Mikro Elektronik
        9192  88SE9172 SATA III 6Gb/s RAID Controller
        91a0  88SE91A0 SATA 6Gb/s Controller
        91a4  88SE9128 IDE Controller
+       9230  88SE9230 PCIe SATA 6Gb/s Controller
        9480  88SE9480 SAS/SATA 6Gb/s RAID controller
 1b55  NetUP Inc.
        2a2c  Dual DVB-S2-CI card
        f1c4  Dual ASI-RX/TX-CI card
 1b6f  Etron Technology, Inc.
        7023  EJ168 USB 3.0 Host Controller
+       7052  EJ188/EJ198 USB 3.0 Host Controller
 1b73  Fresco Logic
        1000  FL1000G USB 3.0 Host Controller
                1d5c 1000  Anker USB 3.0 Express Card
+       1009  FL1009 USB 3.0 Host Controller
 1b74  OpenVox Communication Co. Ltd.
        0115  D115P/D115E Single-port E1/T1 card
        d130  D130P/D130E Single-port E1/T1 card (3rd GEN)
 1b96  Western Digital
 1b9a  XAVi Technologies Corp.
 1bad  ReFLEX CES
+1bb0  SimpliVity Corporation
+       0002  OmniCube Accelerator OA-3000
 1bb3  Bluecherry
        4304  BC-04120A MPEG4 4 port video encoder / decoder
        4309  BC-08240A MPEG4 4 port video encoder / decoder
 1bb5  Quantenna Communications, Inc.
 1bbf  Maxeler Technologies Ltd.
        0003  MAX3
+       0004  MAX4
 1bf4  VTI Instruments Corporation
 1c1c  Symphony
        0001  82C101
        8000  8000 Storage IO Controller
 1c7f  Elektrobit Austria GmbH
        5100  EB5100
+1c8a  TSF5 Corporation
 1d44  DPT
        a400  PM2x24/PM3224
 1d5c  Fantasia Trading LLC
        004b  Core Processor Secondary PCI Express Root Port
        0050  Core Processor Thermal Management Controller
        0069  Core Processor DRAM Controller
-       0082  Centrino Advanced-N 6205
+       0082  Centrino Advanced-N 6205 [Taylor Peak]
                8086 1301  Centrino Advanced-N 6205 AGN
                8086 1306  Centrino Advanced-N 6205 ABG
                8086 1307  Centrino Advanced-N 6205 BG
                8086 1321  Centrino Advanced-N 6205 AGN
                8086 1326  Centrino Advanced-N 6205 ABG
-       0083  Centrino Wireless-N 1000
+       0083  Centrino Wireless-N 1000 [Condor Peak]
                8086 1205  Centrino Wireless-N 1000 BGN
                8086 1206  Centrino Wireless-N 1000 BG
                8086 1225  Centrino Wireless-N 1000 BGN
                8086 1306  Centrino Wireless-N 1000 BG
                8086 1325  Centrino Wireless-N 1000 BGN
                8086 1326  Centrino Wireless-N 1000 BG
-       0084  Centrino Wireless-N 1000
+       0084  Centrino Wireless-N 1000 [Condor Peak]
                8086 1215  Centrino Wireless-N 1000 BGN
                8086 1216  Centrino Wireless-N 1000 BG
                8086 1315  Centrino Wireless-N 1000 BGN
                8086 1316  Centrino Wireless-N 1000 BG
-       0085  Centrino Advanced-N 6205
+       0085  Centrino Advanced-N 6205 [Taylor Peak]
                8086 1311  Centrino Advanced-N 6205 AGN
                8086 1316  Centrino Advanced-N 6205 ABG
-       0087  Centrino Advanced-N + WiMAX 6250
+       0087  Centrino Advanced-N + WiMAX 6250 [Kilmer Peak]
                8086 1301  Centrino Advanced-N + WiMAX 6250 2x2 AGN
                8086 1306  Centrino Advanced-N + WiMAX 6250 2x2 ABG
                8086 1321  Centrino Advanced-N + WiMAX 6250 2x2 AGN
                8086 1326  Centrino Advanced-N + WiMAX 6250 2x2 ABG
-       0089  Centrino Advanced-N + WiMAX 6250
+       0089  Centrino Advanced-N + WiMAX 6250 [Kilmer Peak]
                8086 1311  Centrino Advanced-N + WiMAX 6250 2x2 AGN
                8086 1316  Centrino Advanced-N + WiMAX 6250 2x2 ABG
-       008a  Centrino Wireless-N 1030
+       008a  Centrino Wireless-N 1030 [Rainbow Peak]
                8086 5305  Centrino Wireless-N 1030 BGN
                8086 5307  Centrino Wireless-N 1030 BG
                8086 5325  Centrino Wireless-N 1030 BGN
                8086 5327  Centrino Wireless-N 1030 BG
-       008b  Centrino Wireless-N 1030
+       008b  Centrino Wireless-N 1030 [Rainbow Peak]
                8086 5315  Centrino Wireless-N 1030 BGN
                8086 5317  Centrino Wireless-N 1030 BG
-       0090  Centrino Advanced-N 6230
+       0090  Centrino Advanced-N 6230 [Rainbow Peak]
                8086 5211  Centrino Advanced-N 6230 AGN
                8086 5215  Centrino Advanced-N 6230 BGN
                8086 5216  Centrino Advanced-N 6230 ABG
-       0091  Centrino Advanced-N 6230
+       0091  Centrino Advanced-N 6230 [Rainbow Peak]
                8086 5201  Centrino Advanced-N 6230 AGN
                8086 5205  Centrino Advanced-N 6230 BGN
                8086 5206  Centrino Advanced-N 6230 ABG
                1028 04cc  Vostro 3350
        0150  Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller
        0151  Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port
+               1043 1477  N56VZ
        0152  Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller
+       0153  3rd Gen Core Processor Thermal Subsystem
+               1043 1517  Zenbook Prime UX31A
        0154  3rd Gen Core processor DRAM Controller
+               1043 1477  N56VZ
+               1043 1517  Zenbook Prime UX31A
        0155  Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port
        0156  3rd Gen Core processor Graphics Controller
        0158  Xeon E3-1200 v2/Ivy Bridge DRAM Controller
        015e  Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller
        0162  Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller
        0166  3rd Gen Core processor Graphics Controller
+               1043 1517  Zenbook Prime UX31A
+               1043 2103  N56VZ
        016a  Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller
        0172  Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller
        0176  3rd Gen Core processor Graphics Controller
        0309  80303 I/O Processor PCI-to-PCI Bridge
        030d  80312 I/O Companion Chip PCI-to-PCI Bridge
        0326  6700/6702PXH I/OxAPIC Interrupt Controller A
+               103c 3208  ProLiant DL140 G2
                1775 1100  CR11/VR11 Single Board Computer
        0327  6700PXH I/OxAPIC Interrupt Controller B
+               103c 3208  ProLiant DL140 G2
                1775 1100  CR11/VR11 Single Board Computer
        0329  6700PXH PCI Express-to-PCI Bridge A
        032a  6700PXH PCI Express-to-PCI Bridge B
        0412  Haswell Integrated Graphics Controller
        0416  Haswell Integrated Graphics Controller
        041a  Haswell Integrated Graphics Controller
-       0436  DH89xxCC Gigabit SGMII Connection
+       0436  DH8900CC Null Device
        0438  DH8900CC Series Gigabit Network Connection
        043a  DH8900CC Series Gigabit Fiber Network Connection
        043c  DH8900CC Series Gigabit Backplane Network Connection
        0960  80960RP (i960RP) Microprocessor/Bridge
        0962  80960RM (i960RM) Bridge
        0964  80960RP (i960RP) Microprocessor/Bridge
+       0a04  Haswell-ULT DRAM Controller
+       0a06  Haswell-ULT Integrated Graphics Controller
+       0a16  Haswell-ULT Integrated Graphics Controller
+       0a22  Haswell-ULT Integrated Graphics Controller
+       0a26  Haswell-ULT Integrated Graphics Controller
+       0a2a  Haswell-ULT Integrated Graphics Controller
        0be0  Atom Processor D2xxx/N2xxx Integrated Graphics Controller
        0be1  Atom Processor D2xxx/N2xxx Integrated Graphics Controller
        0be2  Atom Processor D2xxx/N2xxx Integrated Graphics Controller
        0c7d  Centerton Internal Fabric
        0c7e  Centerton Internal Fabric
        0c7f  Centerton Internal Fabric
+       0d00  Crystal Well DRAM Controller
+       0d01  Crystal Well PCI Express x16 Controller
+       0d04  Crystal Well DRAM Controller
+       0d05  Crystal Well PCI Express x8 Controller
+       0d09  Crystal Well PCI Express x4 Controller
+       0d0c  Crystal Well HD Audio Controller
+       0d16  Crystal Well Integrated Graphics Controller
+       0d26  Crystal Well Integrated Graphics Controller
+       0d36  Crystal Well Integrated Graphics Controller
        0e00  Ivytown DMI2
        0e01  Ivytown PCI Express Root Port in DMI2 Mode
+       0e02  Ivytown PCI Express Root Port 1a
+       0e03  Ivytown PCI Express Root Port 1b
        0e04  Ivytown PCI Express Root Port 2a
        0e05  Ivytown PCI Express Root Port 2b
        0e06  Ivytown PCI Express Root Port 2c
        0efb  Ivytown DDRIO
        0efc  Ivytown DDRIO
        0efd  Ivytown DDRIO
+       0f00  ValleyView SSA-CUnit
+       0f01  ValleyView SSA-CUnit
+       0f02  ValleyView SSA-CUnit
+       0f03  ValleyView SSA-CUnit
+       0f04  ValleyView High Definition Audio Controller
+       0f05  ValleyView High Definition Audio Controller
+       0f06  ValleyView LPIO1 DMA Controller
+       0f07  ValleyView LPIO1 DMA Controller
+       0f08  ValleyView LPIO1 PWM Controller
+       0f09  ValleyView LPIO1 PWM Controller
+       0f0a  ValleyView LPIO1 HSUART Controller #1
+       0f0b  ValleyView LPIO1 HSUART Controller #1
+       0f0c  ValleyView LPIO1 HSUART Controller #2
+       0f0d  ValleyView LPIO1 HSUART Controller #2
+       0f0e  ValleyView LPIO1 SPI Controller
+       0f0f  ValleyView LPIO1 SPI Controller
+       0f10  ValleyView LPIO1 Controller
+       0f11  ValleyView LPIO1 Controller
+       0f12  ValleyView SMBus Controller
+       0f13  ValleyView SMBus Controller
+       0f14  ValleyView SDIO Controller
+       0f15  ValleyView SDIO Controller
+       0f16  ValleyView SDIO Controller
+       0f17  ValleyView SDIO Controller
+       0f18  ValleyView SEC
+       0f19  ValleyView SEC
+       0f1a  ValleyView SEC
+       0f1b  ValleyView SEC
+       0f1c  ValleyView Power Control Unit
+       0f1d  ValleyView Power Control Unit
+       0f1e  ValleyView Power Control Unit
+       0f1f  ValleyView Power Control Unit
+       0f20  ValleyView 4-Port SATA Storage Controller
+       0f21  ValleyView 4-Port SATA Storage Controller
+       0f22  ValleyView 6-Port SATA AHCI Controller
+       0f23  ValleyView 6-Port SATA AHCI Controller
+       0f24  ValleyView SATA RAID Storage Controller
+       0f25  ValleyView SATA RAID Storage Controller
+       0f26  ValleyView 2-Port SATA Storage Controller
+       0f27  ValleyView 2-Port SATA Storage Controller
+       0f28  ValleyView LPE Audio Controller
+       0f29  ValleyView LPE Audio Controller
+       0f2a  ValleyView LPE Audio Controller
+       0f2b  ValleyView LPE Audio Controller
+       0f2e  ValleyView SATA RAID Storage Controller
+       0f2f  ValleyView SATA RAID Storage Controller
+       0f30  ValleyView Gen7
+       0f31  ValleyView Gen7
+       0f32  ValleyView Gen7
+       0f33  ValleyView Gen7
+       0f34  ValleyView USB Enhanced Host Controller
+       0f35  ValleyView USB xHCI Host Controller
+       0f36  ValleyView USB xHCI Host Controller
+       0f37  ValleyView OTG
+       0f38  ValleyView ISP
+       0f39  ValleyView ISP
+       0f3a  ValleyView ISP
+       0f3b  ValleyView ISP
+       0f3c  ValleyView ISP
+       0f3d  ValleyView ISP
+       0f3e  ValleyView ISP
+       0f3f  ValleyView ISP
+       0f40  ValleyView LPIO2 DMA Controller
+       0f41  ValleyView LPIO2 I2C Controller #1
+       0f42  ValleyView LPIO2 I2C Controller #2
+       0f43  ValleyView LPIO2 I2C Controller #3
+       0f44  ValleyView LPIO2 I2C Controller #4
+       0f45  ValleyView LPIO2 I2C Controller #5
+       0f46  ValleyView LPIO2 I2C Controller #6
+       0f47  ValleyView LPIO2 I2C Controller #7
+       0f48  ValleyView PCI Express Root Port
+       0f49  ValleyView PCI Express Root Port
+       0f4a  ValleyView PCI Express Root Port
+       0f4b  ValleyView PCI Express Root Port
+       0f4c  ValleyView PCI Express Root Port
+       0f4d  ValleyView PCI Express Root Port
+       0f4e  ValleyView PCI Express Root Port
+       0f4f  ValleyView PCI Express Root Port
+       0f50  ValleyView MIPI-HSI Controller
        1000  82542 Gigabit Ethernet Controller (Fiber)
                0e11 b0df  NC6132 Gigabit Ethernet Adapter (1000-SX)
                0e11 b0e0  NC6133 Gigabit Ethernet Adapter (1000-LX)
                8086 a02b  Gigabit ET Quad Port Server Adapter
                8086 a02c  Gigabit ET Quad Port Server Adapter
        10ea  82577LM Gigabit Network Connection
+               1028 040a  Latitude E6410
                1028 040b  Latitude E6510
                e4bf 50c1  PC1-GROOVE
        10eb  82577LC Gigabit Network Connection
                8086 000c  Ethernet X520 10GbE Dual Port KX4-KR Mezz
        10f9  82599EB 10 Gigabit CX4 Dual Port Network Connection
        10fb  82599EB 10-Gigabit SFI/SFP+ Network Connection
+               1028 1f72  Ethernet 10G 4P X520/I350 rNDC
                103c 17d0  Ethernet 10Gb 2-port 560FLR-SFP+ Adapter
                103c 17d2  Ethernet 10Gb 2-port 560M Adapter
                103c 17d3  Ethernet 10Gb 2-port 560SFP+ Adapter
                1028 1f62  Intel GbE 2P I350crNDC
                103c 337f  Ethernet 1Gb 2-port 361i Adapter
                103c 3380  Ethernet 1Gb 4-port 366i Adapter
-               103c 339e  Ethernet 1Gb 2-port 361T Adapter [Wharton Stony Lake]
+               103c 339e  Ethernet 1Gb 2-port 361T Adapter
                108e 7b16  Quad Port GbE PCIe 2.0 ExpressModule, UTP
                108e 7b18  Quad Port GbE PCIe 2.0 Low Profile Adapter, UTP
                10a9 802a  UV2-BaseIO dual-port GbE
                8086 00a3  Ethernet Server Adapter I350-F4
                8086 00a4  Ethernet Server Adapter I350-F2
        1523  I350 Gigabit Backplane Connection
-               103c 1784  Ethernet 1Gb 2-port 361FLB Adapter [Badger Flat]
+               103c 1784  Ethernet 1Gb 2-port 361FLB Adapter
                103c 18d1  Ethernet 1Gb 2-port 361FLB Adapter
-               103c 339f  Ethernet 1Gb 4-port 366M Adapter [Vaca Key]
+               103c 339f  Ethernet 1Gb 4-port 366M Adapter
                8086 1f52  1GbE 4P I350 Mezz
        1524  I350 Gigabit Connection
        1525  82567V-4 Gigabit Network Connection
                8086 0001  Ethernet Server Adapter I340-F4
                8086 0002  Ethernet Server Adapter I340-F4
        1528  Ethernet Controller 10-Gigabit X540-AT2
+               1028 1f61  Ethernet 10G 4P X540/I350 rNDC
+               103c 192d  561FLR-T 2-port 10Gb Ethernet Adapter
                108e 7b14  Sun Dual Port 10 GbE PCIe 2.0 ExpressModule, Base-T
                108e 7b15  Sun Dual Port 10 GbE PCIe 2.0 Low Profile Adapter, Base-T
                1137 00bf  Ethernet Converged Network Adapter X540-T2
                8086 5003  Ethernet 10G 2P X540-t Adapter
        1529  82599 10 Gigabit Dual Port Backplane Connection with FCoE
        152a  82599 10 Gigabit Dual port Network Connection with FCoE
+       1533  I210 Gigabit Network Connection
+               103c 0003  Ethernet Server Adapter I210-T1
+               8086 0001  Ethernet Server Adapter I210-T1
+               8086 0002  Ethernet Server Adapter I210-T1
+       1534  I210 Gigabit Network Connection
+       1536  I210 Gigabit Fiber Network Connection
+       1537  I210 Gigabit Backplane Connection
+       1538  I210 Gigabit Network Connection
+       1539  I211 Gigabit Network Connection
+       153a  Ethernet Connection I217-LM
+       153b  Ethernet Connection I217-V
+       1547  DSL3510 Thunderbolt Port [Cactus Ridge]
+       1549  DSL3510 Thunderbolt Controller [Cactus Ridge]
        154a  Ethernet Server Adapter X520-4
                8086 011a  Ethernet Converged Network Adapter X520-4
                8086 011b  Ethernet Converged Network Adapter X520-4
                8086 011c  Ethernet Converged Network Adapter X520-4
        154d  82599EB 10-Gigabit SFP+ Network Connection
                8086 7b11  10GbE 2P X520 Adapter
+       1557  82599 10 Gigabit Network Connection
+       1559  Ethernet Connection I218-V
+       155a  Ethernet Connection I218-LM
+       1560  Ethernet Controller X540-AT1
        1960  80960RP (i960RP) Microprocessor
                101e 0431  MegaRAID 431 RAID Controller
                101e 0438  MegaRAID 438 Ultra2 LVD RAID Controller
                1028 04b2  Vostro 3350
                1028 04da  Vostro 3750
                1043 8418  P8P67 Deluxe Motherboard
+# Realtek ALC888 audio codec
+               8086 2008  DQ67SW board
                8086 7270  Apple MacBookPro8,2 [Core i7, 15", 2011]
        1c22  6 Series/C200 Series Chipset Family SMBus Controller
                1028 04aa  XPS 8300
        1e01  7 Series Chipset Family 4-port SATA Controller [IDE mode]
        1e02  7 Series/C210 Series Chipset Family 6-port SATA Controller [AHCI mode]
        1e03  7 Series Chipset Family 6-port SATA Controller [AHCI mode]
+               1043 1477  N56VZ
+               1043 1517  Zenbook Prime UX31A
        1e04  7 Series/C210 Series Chipset Family SATA Controller [RAID mode]
        1e05  7 Series Chipset SATA Controller [RAID mode]
        1e06  7 Series/C210 Series Chipset Family SATA Controller [RAID mode]
        1e09  7 Series Chipset Family 2-port SATA Controller [IDE mode]
        1e0e  7 Series/C210 Series Chipset Family SATA Controller [RAID mode]
        1e10  7 Series/C210 Series Chipset Family PCI Express Root Port 1
+               1043 1477  N56VZ
+               1043 1517  Zenbook Prime UX31A
        1e12  7 Series/C210 Series Chipset Family PCI Express Root Port 2
+               1043 1477  N56VZ
+               1043 1517  Zenbook Prime UX31A
        1e14  7 Series/C210 Series Chipset Family PCI Express Root Port 3
        1e16  7 Series/C210 Series Chipset Family PCI Express Root Port 4
+               1043 1477  N56VZ
        1e18  7 Series/C210 Series Chipset Family PCI Express Root Port 5
        1e1a  7 Series/C210 Series Chipset Family PCI Express Root Port 6
        1e1c  7 Series/C210 Series Chipset Family PCI Express Root Port 7
        1e1e  7 Series/C210 Series Chipset Family PCI Express Root Port 8
        1e20  7 Series/C210 Series Chipset Family High Definition Audio Controller
+               1043 1477  N56VZ
+               1043 1517  Zenbook Prime UX31A
        1e22  7 Series/C210 Series Chipset Family SMBus Controller
+               1043 1477  N56VZ
+               1043 1517  Zenbook Prime UX31A
        1e24  7 Series/C210 Series Chipset Family Thermal Management Controller
+               1043 1517  Zenbook Prime UX31A
        1e25  7 Series/C210 Series Chipset Family DMI to PCI Bridge
        1e26  7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1
+               1043 1477  N56VZ
+               1043 1517  Zenbook Prime UX31A
        1e2d  7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2
+               1043 1477  N56VZ
+               1043 1517  Zenbook Prime UX31A
        1e31  7 Series/C210 Series Chipset Family USB xHCI Host Controller
+               1043 1477  N56VZ
+               1043 1517  Zenbook Prime UX31A
        1e33  7 Series/C210 Series Chipset Family LAN Controller
        1e3a  7 Series/C210 Series Chipset Family MEI Controller #1
+               1043 1477  N56VZ
+               1043 1517  Zenbook Prime UX31A
        1e3b  7 Series/C210 Series Chipset Family MEI Controller #2
        1e3c  7 Series/C210 Series Chipset Family IDE-r Controller
        1e3d  7 Series/C210 Series Chipset Family KT Controller
        1e57  HM77 Express Chipset LPC Controller
        1e58  UM77 Express Chipset LPC Controller
        1e59  HM76 Express Chipset LPC Controller
+               1043 1477  N56VZ
+               1043 1517  Zenbook Prime UX31A
        1e5a  7 Series Chipset Family LPC Controller
        1e5b  UM77 Express Chipset LPC Controller
        1e5c  7 Series Chipset Family LPC Controller
                104d 80df  Vaio PCG-FX403
        2448  82801 Mobile PCI Bridge
                1028 040b  Latitude E6510
-# (rev d3) (prog-if (rev d3) (prog-if 01 [Subtractive decode])
                103c 0934  HP Compaq nw8240 Mobile Workstation
                103c 099c  NX6110/NC6120
                103c 309f  Compaq nx9420 Notebook
                103c 30c1  Compaq 6910p
                104d 902d  VAIO VGN-NR120E
                144d c00c  P30 notebook
+               144d c072  Notebook N150P
                1734 1055  Amilo M1420
                17aa 20ae  ThinkPad T61
                e4bf cc47  CCG-RUMBA
                1028 0211  Optiplex 755
                1028 02da  OptiPlex 980
                103c 2a3b  Pavilion A1512X
+               103c 31fe  ProLiant DL140 G3
                103c 330b  ProLiant ML150 G6 Server
                1458 5000  GA-EP45-DS5 Motherboard
                1775 11cc  CC11/CL11
                1028 0169  Precision 470
                1028 019a  PowerEdge SC1425
                103c 12bc  d530 CMT (DG746A)
+               103c 3208  ProLiant DL140 G2
                1043 80a6  P4P800 series motherboard
                1458 24d1  GA-8IPE1000 Pro2 motherboard (865PE)
                1462 7280  865PE Neo2 (MS-6728)
                1028 019a  PowerEdge SC1425
                103c 006a  NX9500
                103c 12bc  d530 CMT (DG746A)
+               103c 3208  ProLiant DL140 G2
                1043 80a6  P4P800/P5P800 series motherboard
                1458 24d2  GA-8IPE1000/8KNXP motherboard
                1462 7280  865PE Neo2 (MS-6728)
                1028 0156  Precision 360
                1028 0169  Precision 470
                103c 12bc  d330 uT
+               103c 3208  ProLiant DL140 G2
                1043 80a6  P4P800/P5P800 series motherboard
                1458 24d2  GA-8IPE1000 Pro2 motherboard (865PE)
                1462 7280  865PE Neo2 (MS-6728)
                1028 019a  PowerEdge SC1425
                103c 006a  NX9500
                103c 12bc  d530 CMT (DG746A)
+               103c 3208  ProLiant DL140 G2
                1043 80a6  P4P800/P5P800 series motherboard
                1458 24d2  GA-8IPE1000 Pro2 motherboard (865PE)
                1462 7280  865PE Neo2 (MS-6728)
                1028 019a  PowerEdge SC1425
                103c 006a  NX9500
                103c 12bc  d530 CMT (DG746A)
+               103c 3208  ProLiant DL140 G2
                1043 80a6  P4P800/P5P800 series motherboard
                1458 5006  GA-8IPE1000 Pro2 motherboard (865PE)
                1462 7280  865PE Neo2 (MS-6728)
        25e7  5000 Series Chipset PCI Express x4 Port 7
        25f0  5000 Series Chipset FSB Registers
                1028 01bb  PowerEdge 1955 FSB Registers
+               103c 31fd  ProLiant DL140 G3
                15d9 8680  X7DVL-E-O motherboard
                8086 3476  Intel S5000PSLSATA Server Board
        25f1  5000 Series Chipset Reserved Registers
+               103c 31fd  ProLiant DL140 G3
                15d9 8680  X7DVL-E-O motherboard
                8086 3476  Intel S5000PSLSATA Server Board
        25f3  5000 Series Chipset Reserved Registers
+               103c 31fd  ProLiant DL140 G3
                15d9 8680  X7DVL-E-O motherboard
                8086 3476  Intel S5000PSLSATA Server Board
        25f5  5000 Series Chipset FBD Registers
+               103c 31fd  ProLiant DL140 G3
                15d9 8680  X7DVL-E-O motherboard
                8086 3476  Intel S5000PSLSATA Server Board
        25f6  5000 Series Chipset FBD Registers
+               103c 31fd  ProLiant DL140 G3
                15d9 8680  X7DVL-E-O motherboard
                8086 3476  Intel S5000PSLSATA Server Board
        25f7  5000 Series Chipset PCI Express x8 Port 2-3
                e4bf 0cd3  CD3-JIVE
                e4bf 58b1  XB1
        2670  631xESB/632xESB/3100 Chipset LPC Interface Controller
+               103c 31fe  ProLiant DL140 G3
                15d9 8680  X7DVL-E-O motherboard
                8086 3476  Intel S5000PSLSATA Server Board
        2680  631xESB/632xESB/3100 Chipset SATA IDE Controller
        2681  631xESB/632xESB SATA AHCI Controller
+               103c 31fe  ProLiant DL140 G3
                15d9 8680  X7DVL-E-O motherboard
                8086 3476  Intel S5000PSLSATA Server Board
        2682  631xESB/632xESB SATA RAID Controller
        2688  631xESB/632xESB/3100 Chipset UHCI USB Controller #1
                1028 01bb  PowerEdge 1955 onboard USB
                1028 01f0  PowerEdge R900 onboard USB
+               103c 31fe  ProLiant DL140 G3
                15d9 8680  X7DVL-E-O motherboard
                8086 3476  Intel S5000PSLSATA Server Board
        2689  631xESB/632xESB/3100 Chipset UHCI USB Controller #2
                1028 01bb  PowerEdge 1955 onboard USB
                1028 01f0  PowerEdge R900 onboard USB
+               103c 31fe  ProLiant DL140 G3
                15d9 8680  X7DVL-E-O motherboard
                8086 3476  Intel S5000PSLSATA Server Board
        268a  631xESB/632xESB/3100 Chipset UHCI USB Controller #3
                1028 01f0  PowerEdge R900 onboard USB
+               103c 31fe  ProLiant DL140 G3
                15d9 8680  X7DVL-E-O motherboard
                8086 3476  Intel S5000PSLSATA Server Board
        268b  631xESB/632xESB/3100 Chipset UHCI USB Controller #4
        268c  631xESB/632xESB/3100 Chipset EHCI USB2 Controller
                1028 01bb  PowerEdge 1955 onboard USB
                1028 01f0  PowerEdge R900 onboard USB
+               103c 31fe  ProLiant DL140 G3
                15d9 8680  X7DVL-E-O motherboard
                8086 3476  Intel S5000PSLSATA Server Board
        2690  631xESB/632xESB/3100 Chipset PCI Express Root Port 1
+               103c 31fe  ProLiant DL140 G3
        2692  631xESB/632xESB/3100 Chipset PCI Express Root Port 2
+               103c 31fe  ProLiant DL140 G3
        2694  631xESB/632xESB/3100 Chipset PCI Express Root Port 3
        2696  631xESB/632xESB/3100 Chipset PCI Express Root Port 4
        2698  631xESB/632xESB AC '97 Audio Controller
        2699  631xESB/632xESB AC '97 Modem Controller
        269a  631xESB/632xESB High Definition Audio Controller
        269b  631xESB/632xESB/3100 Chipset SMBus Controller
+               103c 31fe  ProLiant DL140 G3
                15d9 8680  X7DVL-E-O motherboard
                8086 3476  Intel S5000PSLSATA Server Board
        269e  631xESB/632xESB IDE Controller
+               103c 31fe  ProLiant DL140 G3
                15d9 8680  X7DVL-E-O motherboard
        2770  82945G/GZ/P/PL Memory Controller Hub
                1028 01ad  OptiPlex GX620
                10f7 8338  Panasonic CF-Y5 laptop
                17aa 2009  ThinkPad T60/R60 series
        27bc  NM10 Family LPC Controller
+               144d c072  Notebook N150P
                8086 4f4d  DeskTop Board D510MO
        27bd  82801GHM (ICH7-M DH) LPC Interface Bridge
                1025 006c  9814 WKMI
-       27c0  N10/ICH7 Family SATA Controller [IDE mode]
+       27c0  NM10/ICH7 Family SATA Controller [IDE mode]
                1028 01ad  OptiPlex GX620
                1028 01df  PowerEdge SC440
                1028 01e6  PowerEdge 860
                1462 7236  945P Neo3-F Rev. 2.2 motherboard
                1775 11cc  CC11/CL11
                8086 544e  DeskTop Board D945GTP
-       27c1  N10/ICH7 Family SATA Controller [AHCI mode]
+       27c1  NM10/ICH7 Family SATA Controller [AHCI mode]
                1028 01df  PowerEdge SC440
                103c 2a3b  Pavilion A1512X
+               144d c072  Notebook N150P
                1775 11cc  CC11/CL11
                8086 4f4d  DeskTop Board D510MO
                8086 5842  DeskTop Board D975XBX
                103c 30a3  Compaq nw8440
                17aa 200d  ThinkPad T60/R60 series
        27c6  82801GHM (ICH7-M DH) SATA Controller [RAID mode]
-       27c8  N10/ICH 7 Family USB UHCI Controller #1
+       27c8  NM10/ICH7 Family USB UHCI Controller #1
                1025 006c  9814 WKMI
                1028 01ad  OptiPlex GX620
                1028 01d7  XPS M1210
                1043 1237  A6J-Q008
                1043 8179  P5KPL-VM,P5LD2-VM Mainboard
                107b 5048  E4500
+               144d c072  Notebook N150P
                1775 11cc  CC11/CL11
                17aa 200a  ThinkPad T60/R60 series
                8086 4f4d  DeskTop Board D510MO
                8086 544e  DeskTop Board D945GTP
-       27c9  N10/ICH 7 Family USB UHCI Controller #2
+       27c9  NM10/ICH7 Family USB UHCI Controller #2
                1025 006c  9814 WKMI
                1028 01ad  OptiPlex GX620
                1028 01d7  XPS M1210
                1043 1237  A6J-Q008
                1043 8179  P5KPL-VM,P5LD2-VM Mainboard
                107b 5048  E4500
+               144d c072  Notebook N150P
                1775 11cc  CC11/CL11
                17aa 200a  ThinkPad T60/R60 series
                8086 4f4d  DeskTop Board D510MO
                8086 544e  DeskTop Board D945GTP
-       27ca  N10/ICH 7 Family USB UHCI Controller #3
+       27ca  NM10/ICH7 Family USB UHCI Controller #3
                1025 006c  9814 WKMI
                1028 01ad  OptiPlex GX620
                1028 01d7  XPS M1210
                1043 1237  A6J-Q008
                1043 8179  P5KPL-VM,P5LD2-VM Mainboard
                107b 5048  E4500
+               144d c072  Notebook N150P
                1775 11cc  CC11/CL11
                17aa 200a  ThinkPad T60/R60 series
                8086 4f4d  DeskTop Board D510MO
                8086 544e  DeskTop Board D945GTP
-       27cb  N10/ICH 7 Family USB UHCI Controller #4
+       27cb  NM10/ICH7 Family USB UHCI Controller #4
                1025 006c  9814 WKMI
                1028 01ad  OptiPlex GX620
                1028 01d7  XPS M1210
                1043 1237  A6J-Q008
                1043 8179  P5KPL-VM,P5LD2-VM Mainboard
                107b 5048  E4500
+               144d c072  Notebook N150P
                1775 11cc  CC11/CL11
                17aa 200a  ThinkPad T60/R60 series
                8086 4f4d  DeskTop Board D510MO
                8086 544e  DeskTop Board D945GTP
-       27cc  N10/ICH 7 Family USB2 EHCI Controller
+       27cc  NM10/ICH7 Family USB2 EHCI Controller
                1025 006c  9814 WKMI
                1028 01ad  OptiPlex GX620
                1028 01d7  XPS M1210
                103c 30a3  Compaq nw8440
                1043 1237  A6J-Q008
                1043 8179  P5KPL-VM,P5LD2-VM Mainboard
+               144d c072  Notebook N150P
                1775 11cc  CC11/CL11
                17aa 200b  ThinkPad T60/R60 series
                8086 4f4d  DeskTop Board D510MO
                8086 544e  DeskTop Board D945GTP
-       27d0  N10/ICH 7 Family PCI Express Port 1
+       27d0  NM10/ICH7 Family PCI Express Port 1
                103c 309f  Compaq nx9420 Notebook
                103c 30a3  Compaq nw8440
+               144d c072  Notebook N150P
                1775 11cc  CC11/CL11
-       27d2  N10/ICH 7 Family PCI Express Port 2
+       27d2  NM10/ICH7 Family PCI Express Port 2
                103c 309f  Compaq nx9420 Notebook
                103c 30a3  Compaq nw8440
+               144d c072  Notebook N150P
                1775 11cc  CC11/CL11
-       27d4  N10/ICH 7 Family PCI Express Port 3
+       27d4  NM10/ICH7 Family PCI Express Port 3
+               144d c072  Notebook N150P
                1775 11cc  CC11/CL11
-       27d6  N10/ICH 7 Family PCI Express Port 4
+       27d6  NM10/ICH7 Family PCI Express Port 4
                103c 30a3  Compaq nw8440
+               144d c072  Notebook N150P
                1775 11cc  CC11/CL11
-       27d8  N10/ICH 7 Family High Definition Audio Controller
+       27d8  NM10/ICH7 Family High Definition Audio Controller
                1025 006c  9814 WKMI
                1028 01d7  XPS M1210
                103c 2a3b  Pavilion A1512X
                1179 ff10  Toshiba Satellite A100-796 audio (Realtek ALC861)
                1179 ff31  AC97 Data Fax SoftModem with SmartCP
                1447 1043  Asus A8JP (Analog Devices AD1986A)
+               144d c072  Notebook N150P
                1458 a102  GA-8I945PG-RH Mainboard
                152d 0753  Softmodem
                1734 10ad  Conexant softmodem SmartCP
                8086 27d8  DeskTop Board D945GTP
                8086 d618  DeskTop Board D510MO
                8384 7680  STAC9221 HD Audio Codec
-       27da  N10/ICH 7 Family SMBus Controller
+       27da  NM10/ICH7 Family SMBus Controller
                1025 006c  9814 WKMI
                1028 01ad  OptiPlex GX620
                1028 01d7  XPS M1210
                103c 2a3b  Pavilion A1512X
                1043 8179  P5KPL-VM Motherboard
                10f7 8338  Panasonic CF-Y5 laptop
+               144d c072  Notebook N150P
                1458 5001  GA-8I945PG-RH Mainboard
                1775 11cc  CC11/CL11
                17aa 200f  ThinkPad T60/R60 series
                8086 4f4d  DeskTop Board D510MO
                8086 544e  DeskTop Board D945GTP
                8086 5842  DeskTop Board D975XBX
-       27dc  N10/ICH 7 Family LAN Controller
+       27dc  NM10/ICH7 Family LAN Controller
                103c 2a3b  Pavilion A1512X
                8086 308d  DeskTop Board D945GTP
        27dd  82801G (ICH7 Family) AC'97 Modem Controller
        2821  82801HR/HO/HH (ICH8R/DO/DH) 6 port SATA Controller [AHCI mode]
        2822  82801 SATA Controller [RAID mode]
                1028 020d  Inspiron 530
+       2823  Wellsburg sSATA RAID Controller
        2824  82801HB (ICH8) 4 port SATA Controller [AHCI mode]
                1043 81ec  P5B
        2825  82801HR/HO/HH (ICH8R/DO/DH) 2 port SATA Controller [IDE mode]
                1028 01da  OptiPlex 745
                1462 7235  P965 Neo MS-7235 mainboard
        2826  C600/X79 series chipset SATA RAID Controller
+       2827  Wellsburg sSATA RAID Controller
        2828  82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [IDE mode]
                1028 01f3  Inspiron 1420
                103c 30c0  Compaq 6710b
                1028 01da  OptiPlex 745
                1028 01f3  Inspiron 1420
                103c 30c0  Compaq 6710b
-# Name mistyped on previous submission
                103c 30c1  Compaq 6910p
                103c 30cc  Pavilion dv6700
                103c 30d9  Presario C700
        2e16  4 Series Chipset PT IDER Controller
        2e17  4 Series Chipset Serial KT Controller
        2e20  4 Series Chipset DRAM Controller
+               1043 82d3  P5Q Deluxe Motherboard
                1458 5000  GA-EP45-DS5/GA-EG45M-DS2H Motherboard
        2e21  4 Series Chipset PCI Express Root Port
+               1043 82d3  P5Q Deluxe Motherboard
                1458 5000  GA-EP45-DS5 Motherboard
        2e22  4 Series Chipset Integrated Graphics Controller
                1458 d000  GA-EG45M-DS2H Mainboard
        340e  5520/5500/X58 I/O Hub PCI Express Root Port 7
                103c 330b  ProLiant ML150 G6 Server
        340f  5520/5500/X58 I/O Hub PCI Express Root Port 8
-       3410  5520/5500/X58 I/O Hub PCI Express Root Port 9
-       3411  5520/5500/X58 I/O Hub PCI Express Root Port 10
-       3418  5520/5500/X58 Physical Layer Port 0
-       3419  5520/5500 Physical Layer Port 1
-       3420  5500 Non-Legacy I/O Hub PCI Express Root Port 0
-       3421  5520 Non-Legacy I/O Hub PCI Express Root Port 0
-       3422  5520/5500/X58 I/O Hub GPIO and Scratch Pad Registers
+       3410  7500/5520/5500/X58 I/O Hub PCI Express Root Port 9
+       3411  7500/5520/5500/X58 I/O Hub PCI Express Root Port 10
+       3418  7500/5520/5500/X58 Physical Layer Port 0
+       3419  7500/5520/5500 Physical Layer Port 1
+       3420  7500/5520/5500/X58 I/O Hub PCI Express Root Port 0
+       3421  7500/5520/5500/X58 I/O Hub PCI Express Root Port 0
+       3422  7500/5520/5500/X58 I/O Hub GPIO and Scratch Pad Registers
                103c 330b  ProLiant G6 series
-       3423  5520/5500/X58 I/O Hub Control Status and RAS Registers
+       3423  7500/5520/5500/X58 I/O Hub Control Status and RAS Registers
                103c 330b  ProLiant G6 series
-       3425  5520/5500/X58 Physical and Link Layer Registers Port 0
-       3426  5520/5500/X58 Routing and Protocol Layer Registers Port 0
-       3427  5520/5500 Physical and Link Layer Registers Port 1
-       3428  5520/5500 Routing & Protocol Layer Register Port 1
+       3425  7500/5520/5500/X58 Physical and Link Layer Registers Port 0
+       3426  7500/5520/5500/X58 Routing and Protocol Layer Registers Port 0
+       3427  7500/5520/5500 Physical and Link Layer Registers Port 1
+       3428  7500/5520/5500 Routing & Protocol Layer Register Port 1
        3429  5520/5500/X58 Chipset QuickData Technology Device
        342a  5520/5500/X58 Chipset QuickData Technology Device
        342b  5520/5500/X58 Chipset QuickData Technology Device
        342c  5520/5500/X58 Chipset QuickData Technology Device
-       342d  5520/5500/X58 I/O Hub I/OxAPIC Interrupt Controller
-       342e  5520/5500/X58 I/O Hub System Management Registers
+       342d  7500/5520/5500/X58 I/O Hub I/OxAPIC Interrupt Controller
+       342e  7500/5520/5500/X58 I/O Hub System Management Registers
                103c 330b  ProLiant G6 series
-       342f  5520/5500/X58 Trusted Execution Technology Registers
+       342f  7500/5520/5500/X58 Trusted Execution Technology Registers
        3430  5520/5500/X58 Chipset QuickData Technology Device
        3431  5520/5500/X58 Chipset QuickData Technology Device
        3432  5520/5500/X58 Chipset QuickData Technology Device
        3433  5520/5500/X58 Chipset QuickData Technology Device
-       3438  5520/5500/X58 I/O Hub Throttle Registers
+       3438  7500/5520/5500/X58 I/O Hub Throttle Registers
        3500  6311ESB/6321ESB PCI Express Upstream Port
+               103c 31fe  ProLiant DL140 G3
        3501  6310ESB PCI Express Upstream Port
        3504  6311ESB/6321ESB I/OxAPIC Interrupt Controller
        3505  6310ESB I/OxAPIC Interrupt Controller
        350c  6311ESB/6321ESB PCI Express to PCI-X Bridge
+               103c 31fe  ProLiant DL140 G3
        350d  6310ESB PCI Express to PCI-X Bridge
        3510  6311ESB/6321ESB PCI Express Downstream Port E1
+               103c 31fe  ProLiant DL140 G3
        3511  6310ESB PCI Express Downstream Port E1
        3514  6311ESB/6321ESB PCI Express Downstream Port E2
        3515  6310ESB PCI Express Downstream Port E2
        3591  E7525/E7520 Error Reporting Registers
                1014 02dd  eServer xSeries server mainboard
                1028 0169  Precision 470
+               103c 3208  ProLiant DL140 G2
                4c53 10d0  Telum ASLP10 Processor AMC
        3592  E7320 Memory Controller Hub
        3593  E7320 Error Reporting Registers
                1028 028c  PowerEdge R410 LPC Interface Controller
                1028 028d  PowerEdge T410 LPC Interface Controller
                103c 330b  ProLiant G6 series
+               1043 82d4  P5Q Deluxe Motherboard
                1458 5001  GA-EP45-DS5 Motherboard
        3a18  82801JIB (ICH10) LPC Interface Controller
        3a1a  82801JD (ICH10D) LPC Interface Controller
                1028 028c  PowerEdge R410 SATA IDE Controller
                1028 028d  PowerEdge T410 SATA IDE Controller
        3a30  82801JI (ICH10 Family) SMBus Controller
+               1043 82d4  P5Q Deluxe Motherboard
                1458 5001  GA-EP45-DS5/GA-EG45M-DS2H Motherboard
        3a32  82801JI (ICH10 Family) Thermal Subsystem
        3a34  82801JI (ICH10 Family) USB UHCI Controller #1
                1028 028c  PowerEdge R410 USB UHCI Controller
                1028 028d  PowerEdge T410 USB UHCI Controller
                103c 330b  ProLiant G6 series
+               1043 82d4  P5Q Deluxe Motherboard
                1458 5004  GA-EP45-DS5 Motherboard
        3a35  82801JI (ICH10 Family) USB UHCI Controller #2
                1028 028c  PowerEdge R410 USB UHCI Controller
                1028 028d  PowerEdge T410 USB UHCI Controller
                103c 330b  ProLiant G6 series
+               1043 82d4  P5Q Deluxe Motherboard
                1458 5004  GA-EP45-DS5 Motherboard
        3a36  82801JI (ICH10 Family) USB UHCI Controller #3
                1028 028c  PowerEdge R410 USB UHCI Controller
                1028 028d  PowerEdge T410 USB UHCI Controller
                103c 330b  ProLiant G6 series
+               1043 82d4  P5Q Deluxe Motherboard
                1458 5004  GA-EP45-DS5 Motherboard
        3a37  82801JI (ICH10 Family) USB UHCI Controller #4
                1028 028c  PowerEdge R410 USB UHCI Controller
                1028 028d  PowerEdge T410 USB UHCI Controller
                103c 330b  ProLiant G6 series
+               1043 82d4  P5Q Deluxe Motherboard
                1458 5004  GA-EP45-DS5/GA-EG45M-DS2H Motherboard
        3a38  82801JI (ICH10 Family) USB UHCI Controller #5
                1028 028c  PowerEdge R410 USB UHCI Controller
                1028 028d  PowerEdge T410 USB UHCI Controller
                103c 330b  ProLiant ML150 G6 Server
+               1043 82d4  P5Q Deluxe Motherboard
                1458 5004  GA-EP45-DS5/GA-EG45M-DS2H Motherboard
        3a39  82801JI (ICH10 Family) USB UHCI Controller #6
                1028 028c  PowerEdge R410 USB UHCI Controller
                1028 028d  PowerEdge T410 USB UHCI Controller
                103c 330b  ProLiant ML150 G6 Server
+               1043 82d4  P5Q Deluxe Motherboard
                1458 5004  GA-EP45-DS5/GA-EG45M-DS2H Motherboard
        3a3a  82801JI (ICH10 Family) USB2 EHCI Controller #1
                1028 028c  PowerEdge R410 USB EHCI Controller
                1028 028d  PowerEdge T410 USB EHCI Controller
                103c 330b  ProLiant G6 series
+               1043 82d4  P5Q Deluxe Motherboard
                1458 5006  GA-EP45-DS5 Motherboard
        3a3c  82801JI (ICH10 Family) USB2 EHCI Controller #2
                1028 028c  PowerEdge R410 USB EHCI Controller
                1028 028d  PowerEdge T410 USB EHCI Controller
                103c 330b  ProLiant G6 series
+               1043 82d4  P5Q Deluxe Motherboard
                1458 5006  GA-EP45-DS5 Motherboard
        3a3e  82801JI (ICH10 Family) HD Audio Controller
+               1043 8311  P5Q Deluxe Motherboard
                1458 a002  GA-EP45-UD3R Motherboard
                1458 a102  GA-EP45-DS5/GA-EG45M-DS2H Motherboard
        3a40  82801JI (ICH10 Family) PCI Express Root Port 1
                1028 028c  PowerEdge R410 PCI Express Port 1
                1028 028d  PowerEdge T410 PCI Express Port 1
                103c 330b  ProLiant ML150 G6 Server
+               1043 82d4  P5Q Deluxe Motherboard
                1043 82ea  P6T DeLuxe Motherboard
                1458 5001  GA-EP45-DS5/GA-EG45M-DS2H Motherboard
        3a42  82801JI (ICH10 Family) PCI Express Port 2
                1458 5001  GA-EP45-DS5 Motherboard
        3a4a  82801JI (ICH10 Family) PCI Express Root Port 6
                103c 330b  ProLiant ML150 G6 Server
+               1043 82d4  P5Q Deluxe Motherboard
                1043 82ea  P6T DeLuxe Motherboard
                1458 5001  GA-EP45-DS5/GA-EG45M-DS2H Motherboard
        3a4c  82801JI (ICH10 Family) Gigabit Ethernet Controller
        8184  Atom Processor E6xx PCI Express Port 1
        8185  Atom Processor E6xx PCI Express Port 2
        8186  Atom Processor E6xx LPC Bridge
+       821c  Wellsburg PCI Express Root Port #7
+       821d  Wellsburg PCI Express Root Port #7
        84c4  450KX/GX [Orion] - 82454KX/GX PCI bridge
        84c5  450KX/GX [Orion] - 82453KX/GX Memory controller
        84ca  450NX - 82451NX Memory & I/O Controller
        8817  Platform Controller Hub EG20T I2C Controller
        8818  Platform Controller Hub EG20T Controller Area Network (CAN) Controller
        8819  Platform Controller Hub EG20T IEEE 1588 Hardware Assist
-       8c00  Lynx Point 4-Port SATA IDE Controller
-       8c01  Lynx Point 4-Port SATA IDE Controller
-       8c02  Lynx Point 6-Port SATA AHCI Controller
-       8c03  Lynx Point 6-Port SATA AHCI Controller
-       8c04  Lynx Point SATA RAID Controller
-       8c05  Lynx Point SATA RAID Controller
-       8c06  Lynx Point SATA RAID Controller
-       8c07  Lynx Point SATA RAID Controller
-       8c08  Lynx Point 2-Port SATA IDE Controller
-       8c09  Lynx Point 2-Port SATA IDE Controller
-       8c0e  Lynx Point SATA RAID Controller
-       8c0f  Lynx Point SATA RAID Controller
-       8c10  Lynx Point PCI Express Root Port 1
-       8c11  Lynx Point PCI Express Root Port 1
-       8c12  Lynx Point PCI Express Root Port 2
-       8c13  Lynx Point PCI Express Root Port 2
-       8c14  Lynx Point PCI Express Root Port 3
-       8c15  Lynx Point PCI Express Root Port 3
-       8c16  Lynx Point PCI Express Root Port 4
-       8c17  Lynx Point PCI Express Root Port 4
-       8c18  Lynx Point PCI Express Root Port 5
-       8c19  Lynx Point PCI Express Root Port 5
-       8c1a  Lynx Point PCI Express Root Port 6
-       8c1b  Lynx Point PCI Express Root Port 6
-       8c1c  Lynx Point PCI Express Root Port 7
-       8c1d  Lynx Point PCI Express Root Port 7
-       8c1e  Lynx Point PCI Express Root Port 8
-       8c1f  Lynx Point PCI Express Root Port 8
-       8c20  Lynx Point HD Audio Controller
-       8c21  Lynx Point HD Audio Controller
+       8c00  Lynx Point 4-port SATA Controller 1 [IDE mode]
+       8c01  Lynx Point 4-port SATA Controller 1 [IDE mode]
+       8c02  Lynx Point 6-port SATA Controller 1 [AHCI mode]
+       8c03  Lynx Point 6-port SATA Controller 1 [AHCI mode]
+       8c04  Lynx Point SATA Controller 1 [RAID mode]
+       8c05  Lynx Point SATA Controller 1 [RAID mode]
+       8c06  Lynx Point SATA Controller 1 [RAID mode]
+       8c07  Lynx Point SATA Controller 1 [RAID mode]
+       8c08  Lynx Point 2-port SATA Controller 2 [IDE mode]
+       8c09  Lynx Point 2-port SATA Controller 2 [IDE mode]
+       8c0e  Lynx Point SATA Controller 1 [RAID mode]
+       8c0f  Lynx Point SATA Controller 1 [RAID mode]
+       8c10  Lynx Point PCI Express Root Port #1
+       8c11  Lynx Point PCI Express Root Port #1
+       8c12  Lynx Point PCI Express Root Port #2
+       8c13  Lynx Point PCI Express Root Port #2
+       8c14  Lynx Point PCI Express Root Port #3
+       8c15  Lynx Point PCI Express Root Port #3
+       8c16  Lynx Point PCI Express Root Port #4
+       8c17  Lynx Point PCI Express Root Port #4
+       8c18  Lynx Point PCI Express Root Port #5
+       8c19  Lynx Point PCI Express Root Port #5
+       8c1a  Lynx Point PCI Express Root Port #6
+       8c1b  Lynx Point PCI Express Root Port #6
+       8c1c  Lynx Point PCI Express Root Port #7
+       8c1d  Lynx Point PCI Express Root Port #7
+       8c1e  Lynx Point PCI Express Root Port #8
+       8c1f  Lynx Point PCI Express Root Port #8
+       8c20  Lynx Point High Definition Audio Controller
+       8c21  Lynx Point High Definition Audio Controller
        8c22  Lynx Point SMBus Controller
-       8c23  Lynx Point CHAP Counter
+       8c23  Lynx Point CHAP Counters
        8c24  Lynx Point Thermal Management Controller
        8c26  Lynx Point USB Enhanced Host Controller #1
        8c2d  Lynx Point USB Enhanced Host Controller #2
        8c5d  Lynx Point LPC Controller
        8c5e  Lynx Point LPC Controller
        8c5f  Lynx Point LPC Controller
+       8d00  Wellsburg 4-port SATA Controller [IDE mode]
+       8d02  Wellsburg 6-Port SATA Controller [AHCI mode]
+       8d04  Wellsburg SATA Controller [RAID mode]
+       8d06  Wellsburg SATA Controller [RAID mode]
+       8d08  Wellsburg 2-port SATA Controller [IDE mode]
+       8d0e  Wellsburg SATA Controller [RAID mode]
+       8d10  Wellsburg PCI Express Root Port #1
+       8d11  Wellsburg PCI Express Root Port #1
+       8d12  Wellsburg PCI Express Root Port #2
+       8d13  Wellsburg PCI Express Root Port #2
+       8d14  Wellsburg PCI Express Root Port #3
+       8d15  Wellsburg PCI Express Root Port #3
+       8d16  Wellsburg PCI Express Root Port #4
+       8d17  Wellsburg PCI Express Root Port #4
+       8d18  Wellsburg PCI Express Root Port #5
+       8d19  Wellsburg PCI Express Root Port #5
+       8d1a  Wellsburg PCI Express Root Port #6
+       8d1e  Wellsburg PCI Express Root Port #8
+       8d1f  Wellsburg PCI Express Root Port #8
+       8d20  Wellsburg HD Audio Controller
+       8d21  Wellsburg HD Audio Controller
+       8d22  Wellsburg SMBus Controller
+       8d24  Wellsburg Thermal Subsystem
+       8d26  Wellsburg USB Enhanced Host Controller #1
+       8d2d  Wellsburg USB Enhanced Host Controller #2
+       8d31  Wellsburg USB xHCI Host Controller
+       8d33  Wellsburg LAN Controller
+       8d34  Wellsburg NAND Controller
+       8d3a  Wellsburg MEI Controller #1
+       8d3b  Wellsburg MEI Controller #2
+       8d3c  Wellsburg IDE-r Controller
+       8d3d  Wellsburg KT Controller
+       8d40  Wellsburg LPC Controller
+       8d41  Wellsburg LPC Controller
+       8d42  Wellsburg LPC Controller
+       8d43  Wellsburg LPC Controller
+       8d44  Wellsburg LPC Controller
+       8d45  Wellsburg LPC Controller
+       8d46  Wellsburg LPC Controller
+       8d47  Wellsburg LPC Controller
+       8d48  Wellsburg LPC Controller
+       8d49  Wellsburg LPC Controller
+       8d4a  Wellsburg LPC Controller
+       8d4b  Wellsburg LPC Controller
+       8d4c  Wellsburg LPC Controller
+       8d4d  Wellsburg LPC Controller
+       8d4e  Wellsburg LPC Controller
+       8d4f  Wellsburg LPC Controller
+       8d60  Wellsburg sSATA Controller [IDE mode]
+       8d62  Wellsburg sSATA Controller [AHCI mode]
+       8d64  Wellsburg sSATA Controller [RAID mode]
+       8d66  Wellsburg sSATA Controller [RAID mode]
+       8d68  Wellsburg sSATA Controller [IDE mode]
+       8d6e  Wellsburg sSATA Controller [RAID mode]
+       8d7c  Wellsburg SPSR
+       8d7d  Wellsburg MS SMBus 0
+       8d7e  Wellsburg MS SMBus 1
+       8d7f  Wellsburg MS SMBus 2
        9000  IXP2000 Family Network Processor
        9001  IXP2400 Network Processor
        9002  IXP2300 Network Processor
        9622  Integrated RAID
        9641  Integrated RAID
        96a1  Integrated RAID
+       9c00  Lynx Point-LP SATA Controller 1 [IDE mode]
+       9c01  Lynx Point-LP SATA Controller 1 [IDE mode]
+       9c02  Lynx Point-LP SATA Controller 1 [AHCI mode]
+       9c03  Lynx Point-LP SATA Controller 1 [AHCI mode]
+       9c04  Lynx Point-LP SATA Controller 1 [RAID mode]
+       9c05  Lynx Point-LP SATA Controller 1 [RAID mode]
+       9c06  Lynx Point-LP SATA Controller 1 [RAID mode]
+       9c07  Lynx Point-LP SATA Controller 1 [RAID mode]
+       9c08  Lynx Point-LP SATA Controller 2 [IDE mode]
+       9c09  Lynx Point-LP SATA Controller 2 [IDE mode]
+       9c0a  LynxPoint-LP SATA Controller [Reserved]
+       9c0b  LynxPoint-LP SATA Controller [Reserved]
+       9c0c  LynxPoint-LP SATA Controller [Reserved]
+       9c0d  LynxPoint-LP SATA Controller [Reserved]
+       9c0e  Lynx Point-LP SATA Controller 1 [RAID mode]
+       9c0f  Lynx Point-LP SATA Controller 1 [RAID mode]
+       9c10  Lynx Point-LP PCI Express Root Port 1
+       9c11  Lynx Point-LP PCI Express Root Port 1
+       9c12  Lynx Point-LP PCI Express Root Port 2
+       9c13  Lynx Point-LP PCI Express Root Port 2
+       9c14  Lynx Point-LP PCI Express Root Port 3
+       9c15  Lynx Point-LP PCI Express Root Port 3
+       9c16  Lynx Point-LP PCI Express Root Port 4
+       9c17  Lynx Point-LP PCI Express Root Port 4
+       9c18  Lynx Point-LP PCI Express Root Port 5
+       9c19  Lynx Point-LP PCI Express Root Port 5
+       9c1a  Lynx Point-LP PCI Express Root Port 6
+       9c1b  Lynx Point-LP PCI Express Root Port 6
+       9c20  Lynx Point-LP HD Audio Controller
+       9c21  Lynx Point-LP HD Audio Controller
+       9c22  Lynx Point-LP SMBus Controller
+       9c23  Lynx Point-LP CHAP Counters
+       9c24  Lynx Point-LP Thermal
+       9c26  Lynx Point-LP USB EHCI #1
+       9c31  Lynx Point-LP USB xHCI HC
+       9c35  Lynx Point-LP SDIO Controller
+       9c36  Lynx Point-LP Audio DSP Controller
+       9c3a  Lynx Point-LP HECI #0
+       9c3b  Lynx Point-LP HECI #1
+       9c3c  Lynx Point-LP HECI IDER
+       9c3d  Lynx Point-LP HECI KT
+       9c40  Lynx Point-LP LPC Controller
+       9c41  Lynx Point-LP LPC Controller
+       9c42  Lynx Point-LP LPC Controller
+       9c43  Lynx Point-LP LPC Controller
+       9c44  Lynx Point-LP LPC Controller
+       9c45  Lynx Point-LP LPC Controller
+       9c46  Lynx Point-LP LPC Controller
+       9c47  Lynx Point-LP LPC Controller
+       9c60  Lynx Point-LP Low Power Sub-System DMA
+       9c61  Lynx Point-LP I2C Controller #0
+       9c62  Lynx Point-LP I2C Controller #1
+       9c63  Lynx Point-LP UART Controller #0
+       9c64  Lynx Point-LP UART Controller #1
+       9c65  Lynx Point-LP SPI Controller #0
+       9c66  Lynx Point-LP SPI Controller #1
        a000  Atom Processor D4xx/D5xx/N4xx/N5xx DMI Bridge
                8086 4f4d  DeskTop Board D510MO
        a001  Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller
        a002  Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller
        a003  Atom Processor D4xx/D5xx/N4xx/N5xx CHAPS counter
        a010  Atom Processor D4xx/D5xx/N4xx/N5xx DMI Bridge
+               144d c072  Notebook N150P
        a011  Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller
+               144d c072  Notebook N150P
        a012  Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller
+               144d c072  Notebook N150P
        a013  Atom Processor D4xx/D5xx/N4xx/N5xx CHAPS counter
        a620  6400/6402 Advanced Memory Buffer (AMB)
        b152  21152 PCI-to-PCI Bridge
@@ -20767,6 +21390,8 @@ b1d9  ATCOM Technology co., LTD.
 # Pinnacle should be 11bd, but they got it wrong several times --mj
 bd11  Pinnacle Systems, Inc. (Wrong ID)
 bdbd  Blackmagic Design
+# HD/SDI input and output card for PCI Express 1x
+       a11b  DeckLink SDI
 c001  TSI Telsys
 c0a9  Micron/Crucial Technology
 c0de  Motorola
@@ -20818,6 +21443,10 @@ dada  Datapath Limited
 db10  Diablo Technologies
 dcba  Dynamic Engineering
        0046  PCIeAlteraCycloneIV
+# VPX format Receiver Controller Board
+       0047  VPX-RCB
+# PMC Format FPGA design with 8 high speed UART channels
+       0048  PMC-Biserial-III-BAE9
 dd01  Digital Devices GmbH
        0003  Octopus LE DVB adapter
 dead  Indigita Corporation
index 1b256c5cd5fd273805735d5b4ff1c458f79f19fa..5a58d8c5c0ed01204b64598f8bab065fa7986d42 100644 (file)
@@ -26,8 +26,10 @@ REQUIRES_CFLAGS = libio-vbus libio-io
 PRIVATE_INCDIR += $(SRC_DIR)
 
 
+ifneq ($(filter regen_files,$(MAKECMDGOALS)),)
+
 ifneq ($(SRC_DIR),)
-all:: $(SRC_DIR)/lua_glue.swg.h $(SRC_DIR)/lua_glue.swg.cc
+regen_files:: $(SRC_DIR)/lua_glue.swg.h $(SRC_DIR)/lua_glue.swg.cc
 endif
 
 SWIG_RM_EXT_C ?= $(L4DIR)/tool/bin/swig-rm-extern-c.pl
@@ -50,7 +52,7 @@ $(SRC_DIR)/%.swg.c_cc: $(SRC_DIR)/%.swg $(SRC_DIR)/Makefile
        $(VERBOSE)$(SWIG) $(SWIG_INCDIR) -c++ -small -lua -o $@ $<
 
 $(SRC_DIR)/%.swg.c_h:
-       pwd
        @$(GEN_MESSAGE)
        $(VERBOSE)$(SWIG) $(SWIG_INCDIR) -c++ -lua -small -external-runtime $@
 
+endif
index fa6a95e3b346258519740579d7d050e00a60bc14..b42b079f3b256be2b44dcd358183da6c0313828d 100644 (file)
@@ -13,7 +13,7 @@ CC_YY  := $(SRC_YY:%.yy=%.tab.cc) $(SRC_YY:%.yy=%.tab.hh)
 # generate scanner in the source dir, to prevent a hard dependency to ragel
 CC_RL  := $(SRC_DIR)/cfg_scan.cc
 
-regen_files: $(CC_RL) $(CC_YY)
+regen_files:: $(CC_RL) $(CC_YY)
 
 $(CC_RL): %.cc: %.rl $(SRC_DIR)/Makefile
        @$(GEN_MESSAGE)
index 5cb81da25bd05f5ec07aaa9efa6d49c9525b2692..de81b28e115ab429a1e04ca21ba2ff993bb813f5 100644 (file)
@@ -23,8 +23,7 @@
  */
 #pragma once
 
-#include <l4/sys/ipc.h>
-#include <l4/sys/task.h>
+#include <l4/sys/types.h>
 
 /**
  * \defgroup l4_vm_svm_api VM API for SVM
index b39cf301bb7a6c1ad24a2e30c1938397de031d8f..fab684b136bbca86fd94d9a1dd56321d857cdb50 100644 (file)
@@ -20,7 +20,7 @@ PRIVATE_INCDIR_ARCH-x86/perform.s.o = ARCH-x86
 
 include $(L4DIR)/mk/lib.mk
 
-ARCH-x86/perform.o:    ARCH-x86/pmc_events.h
+ARCH-x86/perform.o ARCH-x86/perform.s.o: ARCH-x86/pmc_events.h
 ARCH-x86/pmc_events.h: pmc_events.in
        @$(GEN_MESSAGE)
        $(VERBOSE)sort < $^ > $(OBJ_DIR)/$(^F).sorted || rm $(OBJ_DIR)/$(^F).sorted
index c6d42784bc9beea3f10e193a0fa500b9b2c15882..2d7e93d7ea242c3688cbdffd3e2d711917876ff6 100644 (file)
@@ -232,6 +232,9 @@ int
 l4io_iterate_devices(l4io_device_handle_t *devhandle,
                      l4io_device_t *dev, l4io_resource_handle_t *reshandle)
 {
+  if (!vbus().is_valid())
+    return -L4_ENOENT;
+
   if (reshandle)
     *reshandle = 0;
 
index 6024f9c2c35e6baef533d7d19df9ff5bb4cbfcf1..a849b2c175f86d545fbb57f9e97708b8ec291520 100644 (file)
@@ -8,7 +8,7 @@ PKGNAME         = libstdc++-v3
 INCSRC_DIR      = $(STDCXX_CONTRIB_DIR)/include
 TARGET          = $(shell (cd $(INCSRC_DIR) && find . -type f -not -name 'Make*' -print))
 
-LIBSUPC_H            := exception new typeinfo
+LIBSUPC_H            := exception new typeinfo cxxabi.h
 LIBSUPC_H-4.6_PLUS-  := exception_defines.h cxxabi-forced.h
 LIBSUPC_H-4.6_PLUS-y := bits/exception_defines.h bits/cxxabi_forced.h bits/hash_bytes.h
 LIBSUPC_H-4.7_PLUS-y += bits/atomic_lockfree_defines.h
index 591e51c803226d29fb11671aa2b182118ca322ee..197e3088afa24cecf37ee0a4253e37f2e4798026 100644 (file)
@@ -147,17 +147,19 @@ public:
   { l4vcpu_irq_restore(this, s, utcb, do_event_work_cb, setup_ipc); }
 
   /**
-   * \brief Halt/block the vCPU.
+   * \brief Wait for event.
    *
    * \param utcb             The UTCB to use.
    * \param do_event_work_cb Call-back function that is called in case an
    *                         event (such as an interrupt) is pending.
    * \param setup_ipc        Call-back function that is called before an
    *                         IPC operation is called.
+   *
+   * Note that event delivery remains disabled after this function returns.
    */
-  void halt(l4_utcb_t *utcb, l4vcpu_event_hndl_t do_event_work_cb,
-            l4vcpu_setup_ipc_t setup_ipc) throw()
-  { l4vcpu_halt(this, utcb, do_event_work_cb, setup_ipc); }
+  void wait_for_event(l4_utcb_t *utcb, l4vcpu_event_hndl_t do_event_work_cb,
+                      l4vcpu_setup_ipc_t setup_ipc) throw()
+  { l4vcpu_wait_for_event(this, utcb, do_event_work_cb, setup_ipc); }
 
   /**
    * \brief Set the task of the vCPU.
index 4d78d955be0769ae61d388bedf04d8aedc3003b4..2311e860838bdedb558f061066dde66c4d81fac7 100644 (file)
@@ -141,7 +141,7 @@ l4vcpu_wait(l4_vcpu_state_t *vcpu, l4_utcb_t *utcb,
             l4vcpu_setup_ipc_t setup_ipc) L4_NOTHROW;
 
 /**
- * \brief Halt the vCPU (sleep).
+ * \brief Wait for event.
  * \ingroup api_libvcpu
  *
  * \param vcpu             Pointer to vCPU area.
@@ -150,12 +150,14 @@ l4vcpu_wait(l4_vcpu_state_t *vcpu, l4_utcb_t *utcb,
  *                         awakes and needs to handle an event/IRQ.
  * \param setup_ipc        Function call-back that is called right before
  *                         any IPC operation.
+ *
+ * Note that event delivery remains disabled after this function returns.
  */
 L4_CV L4_INLINE
 void
-l4vcpu_halt(l4_vcpu_state_t *vcpu, l4_utcb_t *utcb,
-            l4vcpu_event_hndl_t do_event_work_cb,
-            l4vcpu_setup_ipc_t setup_ipc) L4_NOTHROW;
+l4vcpu_wait_for_event(l4_vcpu_state_t *vcpu, l4_utcb_t *utcb,
+                      l4vcpu_event_hndl_t do_event_work_cb,
+                      l4vcpu_setup_ipc_t setup_ipc) L4_NOTHROW;
 
 
 /**
@@ -290,12 +292,11 @@ l4vcpu_irq_restore(l4_vcpu_state_t *vcpu, l4vcpu_irq_state_t s,
 
 L4_CV L4_INLINE
 void
-l4vcpu_halt(l4_vcpu_state_t *vcpu, l4_utcb_t *utcb,
-            l4vcpu_event_hndl_t do_event_work_cb,
-            l4vcpu_setup_ipc_t setup_ipc) L4_NOTHROW
+l4vcpu_wait_for_event(l4_vcpu_state_t *vcpu, l4_utcb_t *utcb,
+                      l4vcpu_event_hndl_t do_event_work_cb,
+                      l4vcpu_setup_ipc_t setup_ipc) L4_NOTHROW
 {
   l4vcpu_wait(vcpu, utcb, L4_IPC_NEVER, do_event_work_cb, setup_ipc);
-  l4vcpu_irq_enable(vcpu, utcb, do_event_work_cb, setup_ipc);
 }
 
 __END_DECLS
index 4cc945bf2861c5d9b5208955f5505df0435ba19c..bf62efc99b0222c8b03fbb2a89a14e20abd8ca72 100644 (file)
 void l4vcpu_print_state_arch(l4_vcpu_state_t *vcpu,
                              const char *prefix) L4_NOTHROW
 {
-  printf("%svcpu=%p ip=%08lx sp=%08lx trapno=%08lx label=%lx\n",
-         prefix, vcpu, vcpu->r.ip, vcpu->r.sp, vcpu->r.trapno, vcpu->i.label);
+  printf("%sip=%08lx sp=%08lx trapno=%08lx\n",
+         prefix, vcpu->r.ip, vcpu->r.sp, vcpu->r.trapno);
   printf("%sax=%08lx dx=%08lx bx=%08lx cx=%08lx\n",
          prefix, vcpu->r.ax, vcpu->r.dx, vcpu->r.bx, vcpu->r.cx);
   printf("%ssi=%08lx di=%08lx bp=%08lx flags=%08lx\n",
          prefix, vcpu->r.si, vcpu->r.di, vcpu->r.bp, vcpu->r.flags);
 }
-
index cf808e9a6cda6a863a425b59d17b69841073c944..db2b99a0042514d1bf29796307dd3c4f8f62fd1a 100644 (file)
@@ -31,4 +31,3 @@ void l4vcpu_print_state_arch(l4_vcpu_state_t *vcpu,
   printf("%sds=%08lx es=%08lx gs=%08lx fs=%08lx\n",
          prefix, vcpu->r.ds, vcpu->r.es, vcpu->r.gs, vcpu->r.fs);
 }
-
index 51bbe1be167a6e597162588deb9e11a1838f0524..abe6b44c8878282c49bfea13030fcf964a89f628 100644 (file)
@@ -27,8 +27,9 @@ l4vcpu_print_state(l4_vcpu_state_t *vcpu,
 {
   printf("%svcpu=%p state=%x savedstate=%x label=%lx\n",
          prefix, vcpu, vcpu->state, vcpu->saved_state, vcpu->i.label);
-  printf("%ssticky=%x user_task=%lx\n",
-         prefix, vcpu->sticky_flags, vcpu->user_task << L4_CAP_SHIFT);
+  printf("%ssticky=%x user_task=%lx  pfa=%lx\n",
+         prefix, vcpu->sticky_flags, vcpu->user_task << L4_CAP_SHIFT,
+         vcpu->r.pfa);
   printf("%sentry_sp=%lx entry_ip=%lx\n",
          prefix, vcpu->entry_sp, vcpu->entry_ip);
   l4vcpu_print_state_arch(vcpu, prefix);
index 0d131b6cb617b9bc1c8adf5239e84a0df807616e..960bfbe24b890ebda48a9b98cc05b97c3702e13c 100644 (file)
@@ -617,6 +617,7 @@ typedef Color_traits<Color_def<Pixel_traits<2>, 11,5,5,6,0,5> >      Rgb16;
 typedef Color_traits<Color_def<Pixel_traits<2>, 0,5,5,6,11,5> >      Bgr16;
 typedef Color_traits<Color_def<Pixel_traits<3>, 16,8,8,8,0,8> >      Rgb24;
 typedef Color_traits<Color_def<Pixel_traits<4>, 16,8,8,8,0,8> >      Rgb32;
+typedef Color_traits<Color_def<Pixel_traits<4>, 0,8,8,8,16,8> >      Bgr32;
 typedef Color_traits<Color_def<Pixel_traits<4>, 16,8,8,8,0,8,24,8> > Rgba32;
 
 }
index ee569d63186024207aabc70682985b33e23e8899..3c531f88b1f6dfa98b9510747f6ae4f035b82a2c 100644 (file)
@@ -44,6 +44,7 @@ static Csf<Rgb16>  _csf_rgb16;
 static Csf<Bgr16>  _csf_bgr16;
 static Csf<Rgb24>  _csf_rgb24;
 static Csf<Rgb32>  _csf_rgb32;
+static Csf<Bgr32>  _csf_bgr32;
 static Csf<Rgba32>  _csf_rgba32;
 
 }
index 7a3a279dce1658f028996f6630d239fe6f472850..7d206fe265252d65a8b00921c041b87408117495 100644 (file)
@@ -264,14 +264,14 @@ Allocator::disp_factory(l4_umword_t r, L4::Ipc::Iostream &ios)
          if (!size.is_of_int())
            return -L4_EINVAL;
 
-         //L4::cout << "MEM: alloc ... " << size << "; " << flags << "\n";
+         // L4::cout << "MEM: alloc ... " << size.value<l4_umword_t>() << "; " << flags.value<l4_umword_t>() << "\n";
          cxx::Auto_ptr<Moe::Dataspace> mo(alloc(size.value<l4_umword_t>(),
                flags.is_of_int() ? flags.value<l4_umword_t>() : 0));
 
          // L4::cout << "MO=" << mo.get() << "\n";
          ko = object_pool.cap_alloc()->alloc(mo.get());
          ko->dec_refcnt(1);
-         //L4::cout << "MO_CAP=" << mo->obj_cap() << "\n";
+         // L4::cout << "MO_CAP=" << mo->obj_cap() << "\n";
          ios << ko;
          mo.release();
          return L4_EOK;
index cde2c3f82817b1d185974decefa198d491ed41a1..08d0324e999b3a5184a5d83dcbb7a9ec003777b9 100644 (file)
@@ -40,11 +40,18 @@ public:
   explicit Quota(size_t limit) : _limit(limit), _used(0) {}
   bool alloc(size_t s)
   {
-    if (_limit && (s > _limit || _used > _limit - s))
+    if (_limit && (s > _limit))
       return false;
 
+    if (_limit && (_used > _limit - s))
+      {
+        GC_gcollect_and_unmap();
+        if (_used > _limit - s)
+          return false;
+      }
+
     _used += s;
-    // printf("Q: alloc(%zx) -> %zx\n", s, _used);
+    //printf("Q: alloc(%zx) -> %zx\n", s, _used);
     return true;
   }
 
index 7f668332e28f829183036178bc4319f6cdeca217..838800cdd3b8c782928333e087f8f6b32de997bd 100644 (file)
@@ -1,4 +1,4 @@
 requires: libudis86 stdlibs libiniparser cxx_io libio-vbus libstdc++ 
-           libvcpu libloader liblwip_netif_ankh
-provides: romain
+           libvcpu libloader liblwip_netif_ankh zlib
+provides: romain libpthread_rep libuu libevbuf_c
 maintainer: doebel@os.inf.tu-dresden.de
index 4c40488c0de3ceb717b85b2de4b5bd01c5f99c63..0c402eb601ecd48bea667901adcd71826ff4079b 100644 (file)
@@ -10,6 +10,6 @@ SYSTEMS = x86-l4f
 
 TARGET = include server lib ex
 
-ex : server lib
+ex : lib server
 
 include $(L4DIR)/mk/subdir.mk
index 65e69f99c20eaf1fdc795bb0a0344cb4d241a983..a115f2adb672085339ba07970d04fbc94c8735d6 100644 (file)
@@ -13,7 +13,7 @@ ldr:start(
                  { caps = { },
                    log = {"romain", "c"},
                  },
---                 "rom/romain rom/hello"
+                   "rom/romain rom/hello"
 --                 "rom/romain rom/pthread_hello"
-                   "rom/romain rom/pthread_mutex"
+--                 "rom/romain rom/pthread_mutex"
                    );
index 54cf554a402603e6089828b35677b794e38fdb1b..47a17ba6930bf82e7cef08c85cbf69b4dfd58f82 100755 (executable)
@@ -1,18 +1,35 @@
 #!/bin/bash
 
+echo "# generated for '$1'"
 echo "[general]"
-#echo "  print_vcpu_state    = y"
 echo "  page_fault_handling = rw"
-echo "  log                 = all"
 echo "  threads             = yes"
-echo "  redundancy          = none"
-#echo "  debug               = simple"
+echo "#  redundancy          = none"
+echo "#  redundancy          = dual"
+echo "#  redundancy          = triple"
+echo "  logbuf = 12"
+echo "  logrdtsc = true"
+echo "  logreplica = true"
+echo ""
+echo "#  print_vcpu_state    = y"
+echo "#  log                 = all"
+
 echo ""
 
 echo "[threads]"
 
-function_list="__pthread_lock __pthread_unlock pthread_mutex_init pthread_mutex_lock pthread_mutex_unlock"
+function_list="__pthread_lock __pthread_unlock pthread_mutex_lock pthread_mutex_unlock"
 
 for f in $function_list; do
        nm $1 | grep -E "\ $f" | sed -re "s/([0-9a-f]+) [TW] ($f(_rep)?)/  \2 = 0x\1/" | sed -re "s/[_]*pthread_//g"
 done
+
+
+kiptime=""
+for line in `objdump -lSCd $1 | grep ff0a0 | cut -d: -f 1`; do
+       kiptime+="0x$line "
+done
+kiptime=`echo $kiptime | sed -re 's/\w$//' | sed -re 's/ 0x/,0x/g'`
+echo ""
+echo "[kip-time]"
+echo "target = $kiptime"
index 907abdde8dde1fe328f54a2f3b96a042abfc4aa7..58db32b0f01df7d44e325f732f954cdcf476b81c 100644 (file)
@@ -1,6 +1,10 @@
 PKGDIR ?= ..
 L4DIR  ?= $(PKGDIR)/../..
 
-TARGET = serial_client trap+emulate dataspaces pthread_hello pthread_mutex
+TARGET = serial_client \
+         trap+emulate \
+         pthread_hello \
+         pthread_mutex \
+         eventbuf
 
 include $(L4DIR)/mk/subdir.mk
diff --git a/l4/pkg/plr/ex/eventbuf/Makefile b/l4/pkg/plr/ex/eventbuf/Makefile
new file mode 100644 (file)
index 0000000..d8c0a95
--- /dev/null
@@ -0,0 +1,20 @@
+PKGDIR      ?= ../..
+L4DIR       ?= $(PKGDIR)/../..
+
+TARGET      = romain_eventbuf
+
+SYSTEMS     = x86-l4f
+
+# list your .c or .cc files here
+SRC_C       =
+SRC_CC      = main.cc
+
+CXXFLAGS += -I$(SRC_DIR)/../../server/src/
+CXXFLAGS += $(call checkcxx,-std=c++11)
+
+vpath %.cc $(SRC_DIR)/../../server/src/
+
+# list requirements of your program here
+REQUIRES_LIBS = libstdc++ libvcpu libudis86 zlib libuu
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/plr/ex/eventbuf/main.cc b/l4/pkg/plr/ex/eventbuf/main.cc
new file mode 100644 (file)
index 0000000..a5baebe
--- /dev/null
@@ -0,0 +1,61 @@
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+
+#include <l4/util/rdtsc.h>
+#include <l4/util/util.h>
+
+#include <l4/plr/uu.h>
+#include <l4/plr/measurements.h>
+
+Measurements::EventBuf eb;
+
+unsigned char buffer[1024 * 1024];
+
+int main()
+{
+       printf("EB\n");
+       eb.set_buffer(buffer, sizeof(buffer));
+       printf("EB.buf = %p, size %d, index %d\n",
+              eb.buffer, eb.size, eb.index);
+
+       printf("Generating 200 events...\n");
+       for (unsigned i = 0; i < 100; ++i) {
+
+               Measurements::GenericEvent* ev = eb.next();
+               ev->header.tsc   = l4_rdtsc();
+               ev->header.vcpu  = 0x1234;
+               ev->header.type  = Measurements::Foo;
+               ev->data.foo.start = 1;
+               printf("%d %llx\n", ev->header.type, ev->header.tsc);
+               
+               l4_sleep(random() % 100);
+               
+               ev = eb.next();
+               ev->header.tsc   = l4_rdtsc();
+               ev->header.vcpu  = 0x1234;
+               ev->header.type  = Measurements::Foo;
+               ev->data.foo.start = 0;
+       }
+
+       printf("EB.buf = %p, size %d, index %d\n",
+              eb.buffer, eb.size, eb.index);
+       printf("EB.oldest = %d\n", eb.oldest());
+
+       char const *filename = "sampledump.txt";
+
+       unsigned oldest = eb.oldest();
+       unsigned dump_start, dump_size;
+
+       if (oldest == 0) { // half-full -> dump from 0 to index
+               dump_start = 0;
+               dump_size  = eb.index * sizeof(Measurements::GenericEvent);
+       } else { // buffer completely full -> dump full size starting from oldest entry
+               dump_start = oldest * sizeof(Measurements::GenericEvent);
+               dump_size  = eb.size * sizeof(Measurements::GenericEvent);
+       }
+
+       uu_dumpz_ringbuffer(filename, eb.buffer, eb.size * sizeof(Measurements::GenericEvent),
+                           dump_start, dump_size);
+       return 0;
+}
diff --git a/l4/pkg/plr/ex/hello/Makefile b/l4/pkg/plr/ex/hello/Makefile
new file mode 100644 (file)
index 0000000..1ed3478
--- /dev/null
@@ -0,0 +1,15 @@
+PKGDIR ?=      ../../..
+L4DIR ?=       $(PKGDIR)/..
+
+TARGET                = romain_hello romain_hello_c
+SRC_CC_romain_hello = main.cc
+SRC_C_romain_hello_c = cmain.c
+
+PRIVATE_INCDIR = $(SRC_DIR)/../../server/src/
+
+CXXFLAGS += $(call checkcxx,-std=c++11)
+REQUIRES_LIBS = libstdc++ libevbuf_c
+
+SYSTEMS = x86-l4f
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/plr/ex/hello/cmain.c b/l4/pkg/plr/ex/hello/cmain.c
new file mode 100644 (file)
index 0000000..e85b3fb
--- /dev/null
@@ -0,0 +1,27 @@
+#include <stdio.h>
+
+#include <l4/util/util.h>
+#include <l4/util/rdtsc.h>
+
+#include <l4/plr/measurements.h>
+
+int main()
+{
+       printf("starting Hello (C version)\n");
+
+       void *ebuf = (void*)0xB0000000;
+       
+       unsigned i = 0;
+       for ( ; i < 5; ++i) {
+
+               struct GenericEvent *ev = evbuf_next(ebuf);
+               ev->header.tsc = evbuf_get_time(ebuf, 1);
+               ev->header.vcpu = 0x1234;
+               ev->header.type = 4;
+
+               printf("HELLO..\n");
+
+               l4_sleep(1000);
+       }
+       return 0;
+}
diff --git a/l4/pkg/plr/ex/hello/main.cc b/l4/pkg/plr/ex/hello/main.cc
new file mode 100644 (file)
index 0000000..afa990f
--- /dev/null
@@ -0,0 +1,37 @@
+#include <iostream>
+
+#include <l4/util/util.h>
+#include <l4/util/rdtsc.h>
+
+#include "constants.h"
+#include <l4/plr/measurements.h>
+
+int main()
+{
+       std::cout << "starting Hello (C++ version)" << std::endl;
+
+       Measurements::EventBuf *eb = reinterpret_cast<Measurements::EventBuf*>(Romain::REPLICA_LOG_ADDRESS);
+       std::cout << "evbuf @ " << std::hex << eb << " " << eb->index << " " << eb->size << std::endl;
+       
+       for (unsigned i = 0; i < 5; ++i) {
+               std::cout << "creating event ... " << &eb->index << std::endl;
+               Measurements::GenericEvent* ev = eb->next();
+               std::cout << "  next @ " << std::hex << ev << std::endl;
+               ev->header.tsc  = l4_rdtsc();
+               ev->header.vcpu = 0x1234;
+               ev->header.type = Measurements::Foo;
+               ev->data.foo.start = true;
+               
+               std::cout << "HELLO" << std::endl;
+
+               ev = eb->next();
+               ev->header.tsc  = l4_rdtsc();
+               ev->header.vcpu = 0x1234;
+               ev->header.type = Measurements::Foo;
+               ev->data.foo.start = false;
+
+               l4_sleep(1000);
+       }
+
+       return 0;
+}
index 5ffcb89c4aafb40994232c998d314dc3e309193e..32bf58983e8480ead3d499e0017ec3489fdb2a5e 100644 (file)
@@ -24,6 +24,7 @@ int main(int argc, char **argv)
        (void)argc; (void)argv;
 
        pthread_t pt;
+       printf("\033[32mhello from main thread\033[0m\n");
 
        int res = pthread_create(&pt, NULL, thread, NULL);
        assert(res == 0);
index c469cd8e0d5bbae1de9deff36e400318ea543e52..6508bba12b7ae852455742d7809b964cbe9bce8a 100644 (file)
@@ -5,6 +5,7 @@ SYSTEMS = x86-l4f
 
 TARGET                = pthread_mutex
 SRC_C = main.c
+#REQUIRES_LIBS += libpthread
 
 include $(L4DIR)/mk/prog.mk
 
index be33cfd0adaea1637d2f4583e645f44fbd58a775..bac8c3b1218fe16cee0ef23a47dae2b9d272e139 100644 (file)
@@ -1,5 +1,6 @@
 #include <stdio.h>
 #include <assert.h>
+#include <sys/time.h>
 
 #include <pthread.h>
 #include <pthread-l4.h>
 static int globalcounter;
 pthread_mutex_t mtx;
 
+static const unsigned print_iterations = 100;
+static const unsigned inc_iterations   = 10000;
+
 static
 void *thread(void *data)
 {
        (void)data;
+#if 0
        while (1) {
-               for (unsigned i = 0; i < 10000; ++i) {
+#else
+       for (unsigned cnt = 0; cnt < print_iterations; ++cnt) {
+#endif
+               for (unsigned i = 0; i < inc_iterations; ++i) {
                        pthread_mutex_lock(&mtx);
                        globalcounter++;
                        pthread_mutex_unlock(&mtx);
                }
+
+               pthread_mutex_lock(&mtx);
                printf("\033[31mThread: %d\n", globalcounter);
+               pthread_mutex_unlock(&mtx);
        }
        return NULL;
 }
 
+
+static int diff_ms(struct timeval *t1, struct timeval *t2)
+{
+       return (((t1->tv_sec - t2->tv_sec) * 1000000) + 
+               (t1->tv_usec - t2->tv_usec))/1000;
+}
+
+
 int main(int argc, char **argv)
 {
        (void)argc; (void)argv;
 
        pthread_t pt;
+
+       struct timeval start, stop;
+
+       gettimeofday(&start, NULL);
+
        pthread_mutex_init(&mtx, 0);
 
        int res = pthread_create(&pt, NULL, thread, NULL);
        assert(res == 0);
 
+#if 0
        while (1) {
-               for (unsigned i = 0; i < 10000; ++i) {
+#else
+       for (unsigned cnt = 0; cnt < print_iterations; ++cnt) {
+#endif
+               for (unsigned i = 0; i < inc_iterations; ++i) {
                        pthread_mutex_lock(&mtx);
                        globalcounter++;
                        pthread_mutex_unlock(&mtx);
                }
+
+               pthread_mutex_lock(&mtx);
                printf("\033[32mMain: %d\n", globalcounter);
+               pthread_mutex_unlock(&mtx);
        }
 
        pthread_join(pt, NULL);
 
-       enter_kdebug("before return");
+       gettimeofday(&stop, NULL);
+
+       unsigned long ms = diff_ms(&stop, &start);
+       printf("Start %ld.%ld --- Stop %ld.%ld --- Diff %ld.%03ld\n",
+              start.tv_sec, start.tv_usec, stop.tv_sec, stop.tv_usec,
+              ms / 1000, ms % 1000);
+
+       //enter_kdebug("before return");
 
        return 0;
 }
diff --git a/l4/pkg/plr/include/measurements.h b/l4/pkg/plr/include/measurements.h
new file mode 100644 (file)
index 0000000..66e4a5b
--- /dev/null
@@ -0,0 +1,225 @@
+#pragma once
+
+/*
+ * measurements.h --
+ *
+ *     Event logging infrastructure
+ *
+ * (c) 2012-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ *     economic rights: Technische Universität Dresden (Germany)
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+
+#include <cassert>
+#include <climits>
+//#include <utility>
+
+#include <l4/util/atomic.h>
+#include <l4/util/rdtsc.h>
+#include <l4/sys/kdebug.h>
+
+/*
+ * Namespace containing classes regarding measurements and
+ * sensors etc.
+ *
+ * XXX: C compatibility! Don't use C++ features except inside __cplusplus parts -> I want to
+ *      use this header file from C files, too
+ */
+#ifdef __cplusplus
+namespace Measurements
+{
+#endif
+
+       enum EventTypes {
+               Invalid = 0,
+               Syscall = 1,
+               Pagefault = 2,
+               Swifi = 3,
+               Foo = 4,
+               Trap = 5,
+               Thread_start = 6,
+               Thread_stop  = 7,
+       };
+
+       struct __attribute__((packed))
+       SensorHead {
+               l4_uint64_t   tsc;   // TSC: stop
+               l4_uint32_t   vcpu;  // vcpu ptr
+               unsigned char type;  // event type
+       };
+
+
+       struct __attribute__((packed))
+       PagefaultEvent
+       {
+               char rw;
+               l4_addr_t address;
+               l4_addr_t localbase;
+               l4_addr_t remotebase;
+       };
+
+       struct __attribute__((packed))
+       TrapEvent
+       {
+               char        start;
+               l4_addr_t   trapaddr;
+               l4_uint32_t trapno;
+       };
+
+
+       struct __attribute__((packed))
+       SyscallEvent
+       {
+               l4_addr_t   eip;
+               l4_uint32_t label;
+       };
+
+
+       struct __attribute__((packed))
+       FooEvent
+       {
+               unsigned start;
+       };
+
+
+       struct __attribute__((packed))
+       GenericEvent
+       {
+               struct SensorHead header;
+               union {
+                       struct PagefaultEvent pf;
+                       struct SyscallEvent sys;
+                       struct FooEvent     foo;
+                       struct TrapEvent    trap;
+                       char         pad[19];
+               } data;
+       };
+
+
+       /*
+        * Event buffer
+        * 
+        * An event buffer holds events of the GenericEvent type. The class does not
+        * allocate memory. Instead the underlying buffer needs to be specified using
+        * the set_buffer() function.
+        * 
+        * Once the buffer is valid, users obtain an element using the next() method
+        * and fill it appropriately.
+        * 
+        * The buffer is managed as a ring buffer and may overflow, in which case the
+        * oldest elements get overwritten. The index variable is increased monotonically,
+        * so users may determine whether the buffer has already overflown by checking
+        * if index > size. If so, (index mod size) points to the oldest element.
+        *
+        * The whole buffer can be dumped using the dump() method. This will produce a UU-encoded
+        * version of the zipped buffer content.
+        */
+       struct __attribute__((packed))
+       EventBuf
+       {
+               struct GenericEvent*  buffer;
+               unsigned       index;
+               unsigned       size;
+               unsigned       sharedTSC;
+               l4_uint64_t   *timestamp;
+               char _end[];
+
+#ifdef __cplusplus
+
+               /**
+                * Create event buffer
+                *
+                * sharableTSC -> allow the TSC value to be located in a way that we can share
+                *                this value among different address spaces (e.g., have replicas
+                *                log events themselves using this TSC). This requires the timestamp
+                *                value to be placed on a dedicated page.
+                */
+               EventBuf(bool sharableTSC = false)
+                       : buffer(0), index(0), size(0), sharedTSC(sharableTSC ? 1 : 0)
+               {
+                 static_assert(sizeof(SensorHead) == 13, "Sensor head not 13 bytes large!");
+                 static_assert(sizeof(GenericEvent) == 32, "GenericEvent larger than 24 bytes!");
+                 //static_assert((l4_umword_t)((EventBuf const *)0)->_end < sizeof(GenericEvent), "head too large?");
+
+                 if (!sharableTSC) {
+                       timestamp = new l4_uint64_t();
+                 }
+
+                 static unsigned char dummyBuffer[32];
+                 set_buffer(dummyBuffer, 32);
+               }
+
+
+               ~EventBuf()
+               {
+                       enter_kdebug("~EventBuf");
+                       if (!sharedTSC) {
+                               delete timestamp;
+                       }
+               }
+
+
+               void set_buffer(unsigned char *buf, unsigned size_in_bytes)
+               {
+                       buffer = reinterpret_cast<GenericEvent*>(buf);
+                       size   = size_in_bytes / sizeof(GenericEvent);
+               }
+
+
+               void set_tsc_buffer(l4_uint64_t *buf)
+               {
+                       timestamp = buf;
+               }
+
+
+               static void launchTimerThread(l4_addr_t timerAddress, unsigned CPU);
+
+               l4_uint64_t getTime(bool local=false)
+               {
+                       if (local) {
+                               return l4_rdtsc();
+                       } else {
+                               return *timestamp;
+                       }
+               }
+
+               /*
+                * Get the next buffer entry.
+                *
+                * Safe against concurrent calls by using atomic increment on the
+                * counter.  Concurrent accesses may lead to events not being properly
+                * ordered, though.
+                */
+               GenericEvent* next()
+               {
+                       unsigned val = l4util_inc32_res(&index) - 1;
+                       val %= size;
+                       return &buffer[val];
+               }
+
+
+               unsigned oldest() const
+               {
+                       if (index < size) {
+                               return 0;
+                       }
+                       else {
+                               return index % size;
+                       }
+               }
+#endif /* C++ */
+       };
+
+#ifdef __cplusplus
+}
+
+extern "C"
+{
+#endif
+       l4_uint64_t evbuf_get_time(void *eb, unsigned local);
+       struct GenericEvent* evbuf_next(void *eb);
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
index 4fd590cf8ecd85af8874f9b340f87a9b32ee9eb6..8da18ddba4f274bf42892a7e58f4b11d28823235 100644 (file)
@@ -11,6 +11,7 @@ enum {
        pt_max_wrappers = 5,
 
        lock_entry_free = 0,
+       lock_unlocking  = 0xAAAAAAAA,
        lock_unowned    = 0xFFFFFFFF,
 
        NUM_TRAMPOLINES = 32,
@@ -22,12 +23,13 @@ enum {
 typedef struct {
   unsigned char trampolines[NUM_TRAMPOLINES * TRAMPOLINE_SIZE];
   struct {
-         l4_addr_t lockdesc;         // corresponding pthread_mutex_t ptr
-         l4_addr_t owner;            // lock owner
-         volatile l4_addr_t wait_count;  // count how many threads wait to acquire this lock
-         l4_addr_t acq_count;        // count how many threads acquired this lock
-         l4_addr_t wake_count;       // count how many threads should be unlocked
-         volatile l4_uint32_t lock;  // internal: lock for this row
+         volatile l4_addr_t lockdesc;            // corresponding pthread_mutex_t ptr
+         volatile l4_addr_t owner;               // lock owner
+         volatile l4_addr_t owner_epoch;         // lock holder's epoch
+         volatile l4_addr_t wait_count; // count how many threads wait to acquire this lock
+         volatile l4_addr_t acq_count;           // count how many threads acquired this lock
+         volatile l4_addr_t wake_count;          // count how many threads should be unlocked
+         volatile l4_uint32_t lock;     // internal: lock for this row
   } locks[NUM_LOCKS];
   volatile l4_umword_t replica_count; // number of replicas running a.t.m.
 } lock_info;
@@ -41,16 +43,19 @@ lock_info* get_lock_info(void) {
 }
 
 
-static inline void lock_li(lock_info *li, unsigned idx)
+static inline void lock_li(volatile lock_info *li, unsigned idx)
 {
-       while (l4util_cmpxchg32(&li->locks[idx].lock, 0, 1) == 0) {
-               asm volatile ("ud2" : : : "memory");
+       asm volatile ("" : : : "memory");
+       while (!l4util_cmpxchg32(&li->locks[idx].lock, 0, 1)) {
+               asm volatile ("ud2" : : : "eax", "memory");
        }
 }
 
-static inline void unlock_li(lock_info* li, unsigned idx)
+static inline void unlock_li(volatile lock_info* li, unsigned idx)
 {
+       asm volatile ("" : : : "eax", "memory");
        li->locks[idx].lock = 0;
+       asm volatile ("" ::: "memory");
 }
 
 
diff --git a/l4/pkg/plr/include/uu.h b/l4/pkg/plr/include/uu.h
new file mode 100644 (file)
index 0000000..6bf16ce
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+ * \file   ferret/examples/merge_mon/uu.h
+ * \brief  UUencoding functions, mostly from jdb
+ *
+ * \date   14/12/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_EXAMPLES_MERGE_MON_UU_H_
+#define __FERRET_EXAMPLES_MERGE_MON_UU_H_
+
+EXTERN_C_BEGIN
+
+#include <stddef.h>
+
+//void uu_dump(const char * filename, const buf_t *buf);
+void uu_dumpz(const char * filename, const unsigned char * s_buf, size_t len);
+void uu_dumpz_ringbuffer(const char * filename,
+                         const void * buffer, size_t buffer_len,
+                         unsigned start_offset, size_t transfer_size);
+
+EXTERN_C_END
+
+#endif
index 6b9562ef40425ea5c991d3f44a248b4fac573cc2..896578197152eadb9eefcf3cad99087beed65781 100644 (file)
@@ -1,6 +1,6 @@
 PKGDIR ?= ..
 L4DIR  ?= $(PKGDIR)/../..
 
-TARGET = libpthread_romain
+TARGET = libpthread_romain libuu libevbuf_c
 
 include $(L4DIR)/mk/subdir.mk
diff --git a/l4/pkg/plr/lib/libevbuf_c/Makefile b/l4/pkg/plr/lib/libevbuf_c/Makefile
new file mode 100644 (file)
index 0000000..41258ef
--- /dev/null
@@ -0,0 +1,15 @@
+PKGDIR?= ../..
+L4DIR ?= $(PKGDIR)/../..
+
+SYSTEMS = x86-l4f
+
+# the name of your library
+TARGET = libevbuf_c.a
+
+PC_FILENAME = libevbuf_c
+
+# list your .c or .cc files here
+SRC_C  =
+SRC_CC  = eb.cc
+
+include $(L4DIR)/mk/lib.mk
diff --git a/l4/pkg/plr/lib/libevbuf_c/eb.cc b/l4/pkg/plr/lib/libevbuf_c/eb.cc
new file mode 100644 (file)
index 0000000..6b6993d
--- /dev/null
@@ -0,0 +1,12 @@
+#include <l4/plr/measurements.h>
+
+extern "C" l4_uint64_t evbuf_get_time(void *eb, unsigned local)
+{
+       return reinterpret_cast<Measurements::EventBuf*>(eb)->getTime(local == 1);
+}
+
+
+extern "C" struct GenericEvent* evbuf_next(void *eb)
+{
+       return (GenericEvent*)reinterpret_cast<Measurements::EventBuf*>(eb)->next();
+}
index cbee2f35d043087109e3b9b93fcd0e370bbb5564..22e585f49aee5addd264507309759bb8c80a0d4c 100644 (file)
@@ -40,7 +40,7 @@ INCDIR-x86   = $(ORIGDIR)/sysdeps/i386/i686 $(ORIGDIR)/sysdeps/i386 \
 #INCDIR-ppc32 = $(ORIGDIR)/sysdeps/powerpc
 #INCDIR-sparc = $(ORIGDIR)/sysdeps/sparc
 
-PRIVATE_INCDIR = -I- $(ORIGDIR) $(SRC_DIR) $(INCDIR-$(ARCH)) $(CONTRIBDIR)/ldso/include
+PRIVATE_INCDIR = -I- $(SRC_DIR) $(ORIGDIR) $(INCDIR-$(ARCH)) $(CONTRIBDIR)/ldso/include
 
 DEFINES   := -DL4_THREAD_SAFE -D__USE_XOPEN2K -D_POSIX_C_SOURCE=200112L \
              -D_GNU_SOURCE=1 -D__NO_WEAK_PTHREAD_ALIASES=1 \
@@ -52,8 +52,8 @@ DEFINES_x86-l4f   := -DUSE___THREAD=1
 #DEFINES_ppc32-l4f := -DUSE___THREAD=1 
 #DEFINES_sparc-l4f := -DUSE___THREAD=1 
 
-CFLAGS    += -include $(CONTRIBDIR)/include/libc-symbols.h
-CXXFLAGS  += -include $(CONTRIBDIR)/include/libc-symbols.h
+CFLAGS    += -include $(CONTRIBDIR)/include/libc-symbols.h -include $(SRC_DIR)/descr.h
+CXXFLAGS  += -include $(CONTRIBDIR)/include/libc-symbols.h -include $(SRC_DIR)/descr.h
 CXXFLAGS  += -fno-exceptions
 
 include $(L4DIR)/mk/lib.mk
diff --git a/l4/pkg/plr/lib/libpthread_romain/src/descr.h b/l4/pkg/plr/lib/libpthread_romain/src/descr.h
new file mode 100644 (file)
index 0000000..d934396
--- /dev/null
@@ -0,0 +1,238 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program is free software; you can redistribute it and/or        */
+/* modify it under the terms of the GNU Library General Public License  */
+/* as published by the Free Software Foundation; either version 2       */
+/* of the License, or (at your option) any later version.               */
+/*                                                                      */
+/* This program is distributed in the hope that it will be useful,      */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of       */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        */
+/* GNU Library General Public License for more details.                 */
+
+#ifndef _DESCR_H
+#define _DESCR_H       1
+
+#define __need_res_state
+#include <resolv.h>
+#include <setjmp.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <tls.h>
+#include <l4/sys/utcb.h>
+
+/* Fast thread-specific data internal to libc.  */
+enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
+                       _LIBC_TSD_KEY_DL_ERROR,
+                       _LIBC_TSD_KEY_RPC_VARS,
+                       _LIBC_TSD_KEY_LOCALE,
+                       _LIBC_TSD_KEY_CTYPE_B,
+                       _LIBC_TSD_KEY_CTYPE_TOLOWER,
+                       _LIBC_TSD_KEY_CTYPE_TOUPPER,
+                       _LIBC_TSD_KEY_N };
+
+/* The type of thread descriptors */
+typedef struct _pthread_descr_struct *pthread_descr;
+
+
+/* Some more includes.  */
+#include <pt-machine.h>
+//#include <linuxthreads_db/thread_dbP.h>
+
+
+/* Arguments passed to thread creation routine */
+struct pthread_start_args {
+  void *(*start_routine)(void *); /* function to run */
+  void *arg;                      /* its argument */
+};
+
+
+/* Callback interface for removing the thread from waiting on an
+   object if it is cancelled while waiting or about to wait.
+   This hold a pointer to the object, and a pointer to a function
+   which ``extricates'' the thread from its enqueued state.
+   The function takes two arguments: pointer to the wait object,
+   and a pointer to the thread. It returns 1 if an extrication
+   actually occured, and hence the thread must also be signalled.
+   It returns 0 if the thread had already been extricated. */
+typedef struct _pthread_extricate_struct {
+    void *pu_object;
+    int (*pu_extricate_func)(void *, pthread_descr);
+} pthread_extricate_if;
+
+
+/* Atomic counter made possible by compare_and_swap */
+struct pthread_atomic {
+  long p_count;
+  int p_spinlock;
+};
+
+
+/* Context info for read write locks. The pthread_rwlock_info structure
+   is information about a lock that has been read-locked by the thread
+   in whose list this structure appears. The pthread_rwlock_context
+   is embedded in the thread context and contains a pointer to the
+   head of the list of lock info structures, as well as a count of
+   read locks that are untracked, because no info structure could be
+   allocated for them. */
+struct _pthread_rwlock_t;
+typedef struct _pthread_rwlock_info {
+  struct _pthread_rwlock_info *pr_next;
+  struct _pthread_rwlock_t *pr_lock;
+  int pr_lock_count;
+} pthread_readlock_info;
+
+
+/* We keep thread specific data in a special data structure, a two-level
+   array.  The top-level array contains pointers to dynamically allocated
+   arrays of a certain number of data pointers.  So we can implement a
+   sparse array.  Each dynamic second-level array has
+       PTHREAD_KEY_2NDLEVEL_SIZE
+   entries.  This value shouldn't be too large.  */
+#define PTHREAD_KEY_2NDLEVEL_SIZE      32
+
+/* We need to address PTHREAD_KEYS_MAX key with PTHREAD_KEY_2NDLEVEL_SIZE
+   keys in each subarray.  */
+#define PTHREAD_KEY_1STLEVEL_SIZE \
+  ((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1) \
+   / PTHREAD_KEY_2NDLEVEL_SIZE)
+
+
+union dtv;
+
+struct _pthread_descr_struct
+{
+#if !defined USE_TLS || !TLS_DTV_AT_TP || INCLUDE_TLS_PADDING
+  /* This overlaps tcbhead_t (see tls.h), as used for TLS without threads.  */
+  union
+  {
+    struct
+    {
+      void *tcb;               /* Pointer to the TCB.  This is not always
+                                  the address of this thread descriptor.  */
+      union dtv *dtvp;
+      pthread_descr self;      /* Pointer to this structure */
+      int multiple_threads;
+      uintptr_t sysinfo;
+    } data;
+    void *__padding[16];
+  } p_header;
+# define p_multiple_threads p_header.data.multiple_threads
+#elif defined TLS_MULTIPLE_THREADS_IN_TCB && TLS_MULTIPLE_THREADS_IN_TCB
+  int p_multiple_threads;
+#endif
+
+  pthread_descr p_nextlive, p_prevlive;
+                                /* Double chaining of active threads */
+  pthread_descr p_nextwaiting;  /* Next element in the queue holding the thr */
+  pthread_descr p_nextlock;    /* can be on a queue and waiting on a lock */
+  pthread_t p_tid;              /* Thread identifier */
+
+  int p_priority;               /* Thread priority (== 0 if not realtime) */
+  int p_sched_policy;
+
+
+  l4_cap_idx_t     p_thsem_cap;
+  l4_cap_idx_t     p_th_cap;
+  struct _pthread_fastlock * p_lock; /* Spinlock for synchronized accesses */
+  sigjmp_buf * p_cancel_jmp;    /* where to siglongjmp on a cancel or NULL */
+  char p_terminated;            /* true if terminated e.g. by pthread_exit */
+  char p_detached;              /* true if detached */
+  char p_exited;                /* true if the assoc. process terminated */
+  void * p_retval;              /* placeholder for return value */
+  int p_retcode;                /* placeholder for return code */
+  pthread_descr p_joining;      /* thread joining on that thread or NULL */
+  struct _pthread_cleanup_buffer * p_cleanup; /* cleanup functions */
+  char p_cancelstate;           /* cancellation state */
+  char p_canceltype;            /* cancellation type (deferred/async) */
+  char p_canceled;              /* cancellation request pending */
+  struct pthread_start_args p_start_args; /* arguments for thread creation */
+  void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE]; /* thread-specific data */
+#if !(USE_TLS && HAVE___THREAD)
+  void * p_libc_specific[_LIBC_TSD_KEY_N]; /* thread-specific data for libc */
+  int * p_errnop;               /* pointer to used errno variable */
+  int p_errno;                  /* error returned by last system call */
+  int * p_h_errnop;             /* pointer to used h_errno variable */
+  int p_h_errno;                /* error returned by last netdb function */
+  struct __res_state *p_resp;  /* Pointer to resolver state */
+#endif
+  struct __res_state p_res;    /* per-thread resolver state */
+  int p_userstack;             /* nonzero if the user provided the stack */
+  void *p_guardaddr;           /* address of guard area or NULL */
+  size_t p_guardsize;          /* size of guard area */
+  struct pthread_atomic p_resume_count; /* number of times restart() was
+                                          called on thread */
+  char p_woken_by_cancel;       /* cancellation performed wakeup */
+  char p_condvar_avail;                /* flag if conditional variable became avail */
+  char p_sem_avail;             /* flag if semaphore became available */
+  pthread_extricate_if *p_extricate; /* See above */
+  pthread_readlock_info *p_readlock_list;  /* List of readlock info structs */
+  pthread_readlock_info *p_readlock_free;  /* Free list of structs */
+  int p_untracked_readlock_count;      /* Readlocks not tracked by list */
+  int p_inheritsched;           /* copied from the thread attribute */
+#ifdef USE_TLS
+  char *p_stackaddr;           /* Stack address.  */
+#endif
+  size_t p_alloca_cutoff;      /* Maximum size which should be allocated
+                                  using alloca() instead of malloc().  */
+  unsigned p_epoch;
+  unsigned ebx, ecx, edx, esi, edi;
+  /* New elements must be added at the end.  */
+} __attribute__ ((aligned(32))); /* We need to align the structure so that
+                                   doubles are aligned properly.  This is 8
+                                   bytes on MIPS and 16 bytes on MIPS64.
+                                   32 bytes might give better cache
+                                   utilization.  */
+
+
+
+/* Limit between the stack of the initial thread (above) and the
+   stacks of other threads (below). Aligned on a STACK_SIZE boundary.
+   Initially 0, meaning that the current thread is (by definition)
+   the initial thread. */
+
+extern char *__pthread_initial_thread_bos;
+
+/* Descriptor of the initial thread */
+
+extern struct _pthread_descr_struct __pthread_initial_thread;
+
+/* Limits of the thread manager stack. */
+
+extern char *__pthread_manager_thread_bos;
+extern char *__pthread_manager_thread_tos;
+
+/* Descriptor of the manager thread */
+
+extern struct _pthread_descr_struct __pthread_manager_thread;
+extern pthread_descr __pthread_manager_threadp L4_HIDDEN;
+
+/* Indicate whether at least one thread has a user-defined stack (if 1),
+   or all threads have stacks supplied by LinuxThreads (if 0). */
+
+extern int __pthread_nonstandard_stacks;
+
+/* The max size of the thread stack segments.  If the default
+   THREAD_SELF implementation is used, this must be a power of two and
+   a multiple of PAGE_SIZE.  */
+#ifndef STACK_SIZE
+#define STACK_SIZE  (2 * 1024 * 1024)
+#endif
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#ifndef CURRENT_STACK_FRAME
+#define CURRENT_STACK_FRAME  ({ char __csf; &__csf; })
+#endif
+
+/* Recover thread descriptor for the current thread */
+
+extern pthread_descr __pthread_find_self (void) __attribute__ ((pure));
+
+static __inline__ pthread_descr thread_self (void) __attribute__ ((pure));
+static __inline__ pthread_descr thread_self (void)
+{ return (pthread_descr)(l4_utcb_tcr()->user[0]); }
+
+#endif /* descr.h */
index f3ef96b671544de416b7150681144535da783f55..42fcf9e0ede752637609f8be391ee52517c8f829 100644 (file)
@@ -14,6 +14,7 @@
 
 /* Mutexes */
 
+#include "descr.h"
 #include <bits/libc-lock.h>
 #include <errno.h>
 #ifdef NOT_FOR_L4
 #include <l4/plr/pthread_rep.h>
 
 
+int pthread_mutex_lock_rep(pthread_mutex_t * mutex);
+int pthread_mutex_unlock_rep(pthread_mutex_t * mutex);
+
+
+#define LOCKli(li, mtx) (li)->locks[(mtx)->__m_reserved]
+#define ACQ(li, mtx)    lock_li(  (li), (mtx)->__m_reserved)
+#define REL(li, mtx)    unlock_li((li), (mtx)->__m_reserved)
+
+#define YIELD()  yield() 
+#define BARRIER() asm volatile ("" : : : "memory");
+#define ASSERT42(cond, msg) do { /*if (cond) enter_kdebug42(msg);*/ } while (0)
+
+#define GO_TO_SLEEP 0
+
+/*
+ * The generated code uses registers to access and modify data in
+ * the lock info page. This page is shared between all replicas, but
+ * the counts written to it may differ between replicas, which in turn
+ * may lead to the master process detecting state deviation if the values
+ * remain in those registers.
+ *
+ * To fix that, we store the original values of EBX, ECX, and EDX in
+ * thread-private storage and restore them before we a) leave the function or
+ * b) perform a system call that would be observed by the master.
+ *
+ * XXX: This assumes that we will not cause a page fault or
+ *      any other exception during execution, because then we might end
+ *      up with differing register values as well.
+ */
+static inline void rep_function_save_regs(void)
+{
+  BARRIER();
+  asm volatile ("mov %%ebx, %0\t\n"
+                "mov %%ecx, %1\t\n"
+                "mov %%edx, %2\t\n"
+                /*
+                "mov %%esi, %3\t\n"
+                "mov %%edi, %4\t\n"*/
+                : "=m" (thread_self()->ebx),
+                  "=m" (thread_self()->ecx),
+                  "=m" (thread_self()->edx)/*,
+                  "=m" (thread_self()->esi),
+                  "=m" (thread_self()->edi)*/
+                :
+                : "memory"
+  );
+}
+
+
+static inline void rep_function_restore_regs(void)
+{
+  
+  BARRIER();
+  asm volatile ("mov %0, %%ebx\t\n"
+                "mov %1, %%ecx\t\n"
+                "mov %2, %%edx\t\n"
+                /*
+                "mov %3, %%esi\t\n"
+                "mov %4, %%edi\t\n"*/
+                :
+                : "m" (thread_self()->ebx),
+                  "m" (thread_self()->ecx),
+                  "m" (thread_self()->edx)/*,
+                  "m" (thread_self()->esi),
+                  "m" (thread_self()->edi)*/
+                : "memory"
+  );
+}
+
+static inline int yield()
+{
+       rep_function_restore_regs();
+       asm volatile ("ud2" : : : "edx", "ecx", "ebx", "memory");
+       rep_function_save_regs();
+}
+
+
+static inline void lock_rep_wait(pthread_mutex_t* mutex)
+{
+    /*
+     * Go to sleep. This is a system call and will be checked by the master. Therefore,
+     * we need to load the ECX and EDX values we pushed in the beginning, so that the
+     * master process sees a consistent state here.
+     */
+    rep_function_restore_regs();
+    asm volatile (
+                  "push %0\t\n"
+                  "mov $0xA020, %%eax\t\n"
+                  "call *%%eax\t\n"
+                  "pop %0\t\n"
+                  :
+                  : "r" (mutex)
+                  : "eax", "memory");
+    rep_function_save_regs();
+}
+
+
+
+static inline void lock_rep_post(pthread_mutex_t* mutex)
+{
+    /*
+     * Send the actual notification. This is a special case in the master,
+     * because here only one replica performs the system call while all
+     * others continue untouched.
+     */
+    BARRIER();
+    asm volatile ("push %0\t\n"
+                  "mov $0xA040, %%eax\t\n"
+                  "call *%%eax\t\n"
+                  "pop %0\t\n": : "r" (mutex) : "eax", "memory");
+}
+
+
 static void init_replica_mutex(pthread_mutex_t* mtx)
 {
   unsigned i = 0;
   lock_info* li = get_lock_info();
 
+  rep_function_save_regs();
+  
   /*
    * find either the respective lock (if it has been registered by another
    * replica yet) or a free slot to use
@@ -67,14 +183,16 @@ static void init_replica_mutex(pthread_mutex_t* mtx)
   if (i >= NUM_LOCKS) {
          enter_kdebug("out of locks");
   }
+  
+  rep_function_restore_regs();
 }
 
-
-int pthread_mutex_lock_rep(pthread_mutex_t * mutex);
 int
 attribute_hidden
 pthread_mutex_lock_rep(pthread_mutex_t * mutex)
 {
+    rep_function_save_regs();
+    
        /*
         * not initialized yet? -> happens for statically initialized
         * locks as those don't call mutex_init(). And as we need to
@@ -85,127 +203,84 @@ pthread_mutex_lock_rep(pthread_mutex_t * mutex)
          init_replica_mutex(mutex);
        }
 
-       lock_info* li      = get_lock_info();
-    pthread_descr self = thread_self();
-    if (!self) enter_kdebug("self == NULL");
-
-#define LOCKli(li, mtx) (li)->locks[(mtx)->__m_reserved]
-
-    /*
-     * The generated code uses ECX and EDX to access and modify data in
-     * the lock info page. This page is shared between all replicas, but
-     * the counts written to it may differ between replicas, which in turn
-     * may lead to the master process detecting state deviation if the values
-     * remain in those registers.
-     *
-     * To fix that, we store the original values of ECX and EDX to the stack
-     * and restore them before we a) leave the function or b) perform a system
-     * call that would be observed by the master.
-     * 
-     * XXX: Ben points out that this only works if all the code
-     *      below does not use any (%esp)-indirect addresses.
-     *      I validated this for now. A proper solution would be
-     *      to store these registers to some replica-private page.
-     *
-     * XXX: Furthermore, this assumes that we will not cause a page fault or
-     *      any other exception during execution, because then we might end
-     *      up with differing register values as well.
-     */
-       asm volatile ("push %ecx\t\n"
-                     "push %edx\t\n");
-
-retry:
-       lock_li(li, mutex->__m_reserved);
-       
-       if (LOCKli(li, mutex).owner == lock_unowned) {
-               /*
-                * Case 1: The lock was previously unlocked.
-                *   -> make ourselves the lock owner
-                *   -> set acq_count to number of replicas
-                *      (it is decremented in unlock())
-                */
-               LOCKli(li, mutex).owner     = (l4_addr_t)self;
-               LOCKli(li, mutex).acq_count = li->replica_count;
-        asm volatile ("" : : : "memory");
-       } else if (LOCKli(li, mutex).owner != (l4_addr_t)self) {
-               /*
-                * Case 2: someone else owns the lock
-                *   -> best we can do is go to sleep
-                *   -> XXX: maybe spinning with thread_yield
-                *      would help even more?
-                */
-               LOCKli(li, mutex).wait_count += 1;
-               unlock_li(li, mutex->__m_reserved);
-        
-               /*
-                * Go to sleep. This is a system call and will be checked by the master. Therefore,
-                * we need to load the ECX and EDX values we pushed in the beginning, so that the
-                * master process sees a consistent state here.
-                */
-        asm volatile ("pop %%edx\t\n"
-                      "pop %%ecx\t\n"
-                      "push %0\t\n"
-                      "mov $0xA020, %%eax\t\n"
-                      "call *%%eax\t\n"
-                      "pop %0\t\n"
-                      "push %%ecx\t\n"
-                      "push %%edx\t\n"
-                      : : "r" (mutex) : "eax", "memory");
-
-               /*
-                * If we return from the call above, the previous lock
-                * owner signalled us. The locking protocol makes sure that
-                * the lock is not marked as unlocked, but instead appears
-                * to still belong to the old owner.
-                *
-                * If we are the first replica to exit the call
-                * (wait_count == replica count), we adjust the lock owner
-                * to be ourselves.
-                */
-        lock_li(li, mutex->__m_reserved);
-
-        LOCKli(li, mutex).wait_count   -= 1;
-        
-        if (LOCKli(li, mutex).wake_count == li->replica_count) {
-               LOCKli(li, mutex).owner     = (l4_addr_t)self;
-                       LOCKli(li, mutex).acq_count = li->replica_count;
-               }
-
-        LOCKli(li, mutex).wake_count   -= 1;
-
-        asm volatile ("" : : : "memory");
-        unlock_li(li, mutex->__m_reserved);
-       } else if (LOCKli(li, mutex).owner == (l4_addr_t)self) {
-               /*
-                * Case 3: my thread group owns the lock,
-                *         but i'm not the first to acquire it
-                */
-
-               /* Not so good case: If the wake count is larger than 0, this means that
-                * the current thread previously had acquired the lock, then called unlock,
-                * but not all replicas reached the end of unlock() yet. In this case a
-                * fast replica might already try to grab the lock again and find out that
-                * it is already the lock owner. In this case, the thread must not grab the
-                * lock, but instead release the CPU and retry at a later point in time.
-                */
-               if (LOCKli(li, mutex).wake_count > 0) {
-                       unlock_li(li, mutex->__m_reserved);
-                       asm volatile ("ud2" : : : "memory");
-                       goto retry;
-               }
-       }
-
-       unlock_li(li, mutex->__m_reserved);
+    unsigned retry_counter   = 0;
+    lock_info* li            = get_lock_info();
+    thread_self()->p_epoch  += 1;
+    
+    /*outstring("lock() "); outhex32(thread_self()->p_epoch); outstring("\n");*/
+    while (1) {
+
+               ACQ(li, mutex);
+    
+        if (LOCKli(li, mutex).owner == lock_unowned)
+        {
+            ASSERT42(LOCKli(li, mutex).wait_count != 0, "wait count != 0");
+            ASSERT42(LOCKli(li, mutex).acq_count != 0,  "acq count  != 0");
+            ASSERT42(LOCKli(li, mutex).wake_count != 0, "wake count != 0");
+            
+            LOCKli(li, mutex).owner       = (l4_addr_t)thread_self();
+            LOCKli(li, mutex).owner_epoch = thread_self()->p_epoch;
+            LOCKli(li, mutex).acq_count   = li->replica_count;
+            break;
+        }
+        else if (LOCKli(li, mutex).owner == (l4_addr_t)thread_self())
+        {
+            if (LOCKli(li, mutex).owner_epoch != thread_self()->p_epoch) {
+                //outchar42('.'); outchar42(' '); outhex42(thread_self());
+                REL(li, mutex);
+                YIELD();
+                continue;
+                
+                // XXX allow multiple subsequent lock acquisitions */
+                /*
+                outhex42(LOCKli(li, mutex).owner_epoch); outchar42(' ');
+                outhex42(thread_self()->p_epoch); outchar42('\n');
+                enter_kdebug42("epoch mismatch");
+                */
+            }
+
+            break;
+            //enter_kdebug42("mtx owned by me");
+        }
+        else
+        {
+               /*
+                * XXX: Spin for a short while?
+                */
+#if GO_TO_SLEEP
+                       LOCKli(li, mutex).wait_count += 1;
+                       REL(li, mutex);
+                       
+                       lock_rep_wait(mutex);
+
+                       ACQ(li, mutex);
+
+                       LOCKli(li, mutex).wake_count -= 1;
+                       LOCKli(li, mutex).wait_count -= 1;
+
+                       if (LOCKli(li, mutex).wake_count == 0) {
+                               ASSERT42(LOCKli(li, mutex).acq_count != 0,  "acq count  != 0");
+                               LOCKli(li, mutex).owner       = (l4_addr_t)thread_self();
+                               LOCKli(li, mutex).owner_epoch = thread_self()->p_epoch;
+                               LOCKli(li, mutex).acq_count   = li->replica_count;
+                       }
+
+                       REL(li, mutex);
+                       break;
 
-#if 1
-       asm volatile ("pop %edx\t\n"
-                     "pop %ecx\t\n");
+#else
+            REL(li, mutex);
+            YIELD();
+            continue;
 #endif
+            //enter_kdebug42("mtx: other owner");
+        }
+    }
+    
+    REL(li, mutex);
 
-#undef LOCKli
-
-       //enter_kdebug("acquired lock");
-
+    rep_function_restore_regs();
        return 0;
 }
 
@@ -216,67 +291,40 @@ int
 attribute_hidden
 pthread_mutex_unlock_rep(pthread_mutex_t * mutex)
 {
-#define LOCKli(li, mtx) (li)->locks[(mtx)->__m_reserved]
-
-       lock_info* li      = get_lock_info();
-
-    /*
-     * See documentation at the beginning of pthread_mutex_lock_rep()
-     */
-       asm volatile ("push %ecx\t\n"
-                     "push %edx\t\n");
-
-       lock_li(li, mutex->__m_reserved);
-
-       LOCKli(li, mutex).acq_count -= 1;
-
-       /*
-        * All replicas are required to decrement the lock acquisition count. However,
-        * only the last replica to do so will actually wake up a sleeping thread.
-        */
-       if (LOCKli(li, mutex).acq_count == 0) {
-
-               // 1. send unlock notification if there are waiting threads
-        if (LOCKli(li, mutex).wait_count > 0) {
-
-                       /*
-                        * The wake count is used to figure out how many replicas will
-                        * exit their sleep() inside mutex_lock_rep(). See there.
-                        */             
+    rep_function_save_regs();
+    lock_info *li = get_lock_info();
+    
+retry2:
+    ACQ(li, mutex);
+    
+    ASSERT42(LOCKli(li, mutex).owner != (l4_addr_t)thread_self(), "unlock not by owner");
+    ASSERT42(LOCKli(li, mutex).acq_count == 0, "acq count == 0");
+    
+    LOCKli(li, mutex).acq_count -= 1;
+    if (LOCKli(li, mutex).acq_count == 0) {
+#if GO_TO_SLEEP
+        if (LOCKli(li, mutex).wait_count != 0) {
                LOCKli(li, mutex).wake_count = li->replica_count;
-
-                       /*
-                        * Send the actual notification. This is a special case in the master,
-                        * because here only one replica performs the system call while all
-                        * others continue untouched.
-                        */
-            asm volatile ("push %0\t\n"
-                          "mov $0xA040, %%eax\t\n"
-                          "call *%%eax\t\n"
-                          "pop %0\t\n": : "r" (mutex) : "eax");
-            /* Not resetting the owner here. We want to prevent other
-             * threads from grabbing the lock and instead leave the lock
-             * to the thread we just signalled. Therefore, this thread
-             * will need to set ownership directly.
-             */
+               lock_rep_post(mutex);
+               /* don't reset owner */
         } else {
-               // no waiters -> lock is free now
             LOCKli(li, mutex).owner = lock_unowned;
-        }
-
-        asm volatile ("" : : : "memory");
-       }
-
-       unlock_li(li, mutex->__m_reserved);
-
-       asm volatile ("pop %edx\t\n"
-                     "pop %ecx\t\n");
-
-#undef LOCKli
+               }
+#else
+        LOCKli(li, mutex).owner = lock_unowned;
+#endif
+    }
 
+    REL(li, mutex);
+    rep_function_restore_regs();
+    
+    //if (thread_self()->p_epoch % 10 == 0)
+    //    YIELD();
+    
        return 0;
 }
 
+#undef LOCKli
 
 int
 attribute_hidden
diff --git a/l4/pkg/plr/lib/libuu/Makefile b/l4/pkg/plr/lib/libuu/Makefile
new file mode 100644 (file)
index 0000000..2fd0f7c
--- /dev/null
@@ -0,0 +1,15 @@
+PKGDIR?= ../..
+L4DIR ?= $(PKGDIR)/../..
+
+# the name of your library
+TARGET = libuu.a
+
+PC_FILENAME = libuu
+
+# list your .c or .cc files here
+SRC_C  = uu.c 
+SRC_CC  =
+
+REQUIRES_LIBS = zlib
+
+include $(L4DIR)/mk/lib.mk
diff --git a/l4/pkg/plr/lib/libuu/uu.c b/l4/pkg/plr/lib/libuu/uu.c
new file mode 100644 (file)
index 0000000..17796d7
--- /dev/null
@@ -0,0 +1,271 @@
+/**
+ * \file   ferret/examples/merge_mon/uu.c
+ * \brief  UUencoding functions, mostly from jdb
+ *
+ * \date   14/12/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+
+/* ENC is the basic 1 character encoding function to make a char printing */
+#define        ENC(c) ((c) ? ((c) & 077) + ' ': '`')
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <zlib.h>
+
+#include <l4/plr/uu.h>
+
+#define MIN(a, b) ((a)<(b)?(a):(b))
+
+#define LINE_IN 45
+
+static z_stream strm;
+
+/* Init. zlib data structures, available input data and start address
+ */
+static void init_z(size_t len, const void *start)
+{
+    int ret;
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    ret = deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED, 15 + 16, 9,
+                       Z_DEFAULT_STRATEGY);
+    assert(ret == Z_OK);
+
+    strm.avail_in = len;
+    strm.next_in  = (void *)start;  // oh why ...
+}
+
+static int get_next_chunk(void *dest, ssize_t n, int flush)
+{
+    int ret;
+
+    strm.avail_out = n;
+    strm.next_out = dest;
+    ret = deflate(&strm, flush);
+    assert(ret != Z_STREAM_ERROR);
+    return n - strm.avail_out;
+}
+
+static void update_in_data(const unsigned char * buf, size_t * len)
+{
+    if (strm.avail_in == 0 && *len != 0)
+    {
+        strm.avail_in = *len;
+        strm.next_in  = (void *)buf;  // oh why ...
+        *len = 0;
+    }
+}
+
+void uu_dumpz(const char * filename, const unsigned char * s_buf, size_t len)
+{
+    unsigned int ch;
+    int n, ret;
+    const unsigned char *p_buf;
+    int out_i;
+    static unsigned char in[LINE_IN + 3];  // some spare zeros for uuencode
+    static unsigned char out[70];
+    int flush = Z_NO_FLUSH;
+
+    init_z(len, s_buf);
+
+    // uuencode header
+    printf("begin 644 %s.gz\n", filename);
+
+    while (1)
+    {
+        // get next line of data
+        n = get_next_chunk(in, LINE_IN, flush);
+        if (n < LINE_IN && flush == Z_NO_FLUSH)
+        {
+            flush = Z_FINISH;  // time to clean up now
+            n += get_next_chunk(in + n, LINE_IN - n, flush);
+        }
+        else if (n == 0 && flush == Z_FINISH)
+            break;  // no more data available, leave loop
+        memset(in + n, 0, sizeof(in) - n);
+
+        // fill output buffer
+        out_i = 0;
+        // line length prefix
+        ch = ENC(n);
+        out[out_i++] = ch;
+        for (p_buf = in; n > 0; n -= 3, p_buf += 3)
+       {
+            ch = *p_buf >> 2;
+            ch = ENC(ch);
+            out[out_i++] = ch;
+            ch = ((*p_buf << 4) & 060) | ((p_buf[1] >> 4) & 017);
+            ch = ENC(ch);
+            out[out_i++] = ch;
+            ch = ((p_buf[1] << 2) & 074) | ((p_buf[2] >> 6) & 03);
+            ch = ENC(ch);
+            out[out_i++] = ch;
+            ch = p_buf[2] & 077;
+            ch = ENC(ch);
+            out[out_i++] = ch;
+       }
+        // skip this newline for log output
+        //out[out_i++] = '\n';
+        out[out_i] = '\0';
+        puts((char const*)out);  // write it
+    }
+
+    ret = deflateEnd(&strm);
+    assert(ret == Z_OK);
+
+    // uuencode footer
+    printf("`\nend\n");
+}
+
+/* Also works in ring buffers with wrap-around
+ */
+void uu_dumpz_ringbuffer(const char * filename,
+                         const void * _buffer, size_t buffer_len,
+                         unsigned start_offset, size_t transfer_size)
+{
+    int ret;
+    unsigned char * buffer = (unsigned char *)_buffer;
+    static unsigned char in[LINE_IN + 3];  // some spare zeros for uuencode
+    static unsigned char out[70];
+    int flush = Z_NO_FLUSH;
+    size_t first_len = MIN(transfer_size, buffer_len - start_offset);
+
+    assert((unsigned)start_offset < buffer_len);
+    assert(transfer_size <= buffer_len);
+
+    // init. zlib stream for first chunk
+    init_z(first_len, buffer + start_offset);
+    transfer_size -= first_len;
+
+    // uuencode header
+    printf("begin 644 %s.gz\n", filename);
+
+    while (1)
+    {
+        int out_i, n;
+        unsigned int ch;
+        const unsigned char * p_buf;
+
+        // get next line of data
+        n = get_next_chunk(in, LINE_IN, flush);
+        update_in_data(buffer, &transfer_size);
+        if (n < LINE_IN && flush == Z_NO_FLUSH)
+        {
+            flush = Z_FINISH;  // time to clean up now
+            n += get_next_chunk(in + n, LINE_IN - n, flush);
+            update_in_data(buffer, &transfer_size);
+        }
+        else if (n == 0 && flush == Z_FINISH)
+            break;  // no more data available, leave loop
+        memset(in + n, 0, sizeof(in) - n);
+
+        // fill output buffer
+        out_i = 0;
+        // line length prefix
+        ch = ENC(n);
+        out[out_i++] = ch;
+        for (p_buf = in; n > 0; n -= 3, p_buf += 3)
+       {
+            ch = *p_buf >> 2;
+            ch = ENC(ch);
+            out[out_i++] = ch;
+            ch = ((*p_buf << 4) & 060) | ((p_buf[1] >> 4) & 017);
+            ch = ENC(ch);
+            out[out_i++] = ch;
+            ch = ((p_buf[1] << 2) & 074) | ((p_buf[2] >> 6) & 03);
+            ch = ENC(ch);
+            out[out_i++] = ch;
+            ch = p_buf[2] & 077;
+            ch = ENC(ch);
+            out[out_i++] = ch;
+       }
+        // skip this newline for log output
+        //out[out_i++] = '\n';
+        out[out_i] = '\0';
+        puts((char const *)out);  // write it
+    }
+
+    ret = deflateEnd(&strm);
+    assert(ret == Z_OK);
+
+    // uuencode footer
+    printf("`\nend\n");
+}
+
+#if 0
+void uu_dump(const char * filename, const buf_t * buf)
+{
+    unsigned int ch;
+    int n;
+    const unsigned char *p_buf;
+    unsigned char *s_buf = buf->start;
+    int out_i;
+    static unsigned char in[48];
+    static unsigned char out[70];
+    size_t len = buf->write_pos - buf->start;
+
+    // debug
+    //printf("%hhx %hhx %hhx %hhx\n", ENC(8), ENC(64), ENC(4), ENC(2));
+
+    // uuencode header
+    printf("begin 644 %s\n", filename);
+
+    while (len > 0)
+    {
+        // get next line of data
+        if (len >= LINE_IN)
+       {
+            n = LINE_IN;
+       }
+        else
+       {
+            n = len;
+       }
+        memcpy(in, s_buf, n);
+        memset(in + n, 0, sizeof(in) - n);
+        len -= n;
+        s_buf += n;
+
+        // fill output buffer
+        out_i = 0;
+        // line length prefix
+        ch = ENC(n);
+        out[out_i++] = ch;
+        for (p_buf = in; n > 0; n -= 3, p_buf += 3)
+       {
+            ch = *p_buf >> 2;
+            ch = ENC(ch);
+            out[out_i++] = ch;
+            ch = ((*p_buf << 4) & 060) | ((p_buf[1] >> 4) & 017);
+            ch = ENC(ch);
+            out[out_i++] = ch;
+            ch = ((p_buf[1] << 2) & 074) | ((p_buf[2] >> 6) & 03);
+            ch = ENC(ch);
+            out[out_i++] = ch;
+            ch = p_buf[2] & 077;
+            ch = ENC(ch);
+            out[out_i++] = ch;
+       }
+        // skip this newline for log output
+        //out[out_i++] = '\n';
+        out[out_i] = '\0';
+
+        // write it
+        puts(out);
+    }
+
+    // uuencode footer
+    printf("`\nend\n");
+}
+#endif
diff --git a/l4/pkg/plr/patches/fiasco_ud2yield.diff b/l4/pkg/plr/patches/fiasco_ud2yield.diff
new file mode 100644 (file)
index 0000000..8c03fa4
--- /dev/null
@@ -0,0 +1,69 @@
+diff --git a/src/kern/ia32/thread-ia32.cpp b/src/kern/ia32/thread-ia32.cpp
+index d6fb000..7be482b 100644
+--- a/src/kern/ia32/thread-ia32.cpp
++++ b/src/kern/ia32/thread-ia32.cpp
+@@ -30,6 +30,7 @@ EXTENSION class Thread
+ {
+ private:
+   static int  (*int3_handler)(Trap_state*);
++  static int  (*int42_handler)(Trap_state*);
+ };
+@@ -196,6 +197,26 @@ Thread::handle_slow_trap(Trap_state *ts)
+         ts->_err    = 0;
+         }
++      if (ts->_trapno == 6)
++        {
++        LOG_MSG_3VAL(current(), "UD2", dbg_id(), ts->ip(), 0);
++        ts->ip(ts->ip()+2);
++        //Sched_context::rq.current().invalidate_sched();
++        switch_sched(sched(), &Sched_context::rq.current());
++        schedule();
++        goto success;
++        }
++
++      if (ts->_trapno == 13 && ts->_err == 530 /* INT 0x42 */)
++        {
++        /*printf("Replica %lx bailout @ %lx\n", dbg_id(), ts->ip());*/
++        ts->_trapno = 3;
++        ts->ip(ts->ip()+2);
++        if (int42_handler && int42_handler(ts))
++          goto success;
++        goto generic_debug;
++        }
++
+       if (send_exception(ts))
+       goto success;
+     }
+@@ -517,6 +538,7 @@ IMPLEMENTATION[ia32 || amd64]:
+ #include "terminate.h"
+ int (*Thread::int3_handler)(Trap_state*);
++int (*Thread::int42_handler)(Trap_state*);
+ DEFINE_PER_CPU Per_cpu<Thread::Dbg_stack> Thread::dbg_stack;
+ STATIC_INITIALIZER_P (int3_handler_init, KDB_INIT_PRIO);
+@@ -526,6 +548,7 @@ void
+ int3_handler_init()
+ {
+   Thread::set_int3_handler(Thread::handle_int3);
++  Thread::set_int42_handler(Thread::handle_int3);
+ }
+ IMPLEMENT static inline NEEDS ["gdt.h"]
+@@ -575,6 +598,13 @@ Thread::set_int3_handler(int (*handler)(Trap_state *ts))
+   int3_handler = handler;
+ }
++
++PUBLIC static inline
++void
++Thread::set_int42_handler(int (*handler)(Trap_state *ts))
++{
++  int42_handler = handler;
++}
+ /**
+  * Default handle for int3 extensions if JDB is disabled. If the JDB is
+  * available, Jdb::handle_int3_threadctx is called instead.
diff --git a/l4/pkg/plr/patches/l4sys_kdebug0x42.diff b/l4/pkg/plr/patches/l4sys_kdebug0x42.diff
new file mode 100644 (file)
index 0000000..ca79de0
--- /dev/null
@@ -0,0 +1,72 @@
+Index: ../l4sys/include/ARCH-x86/kdebug.h
+===================================================================
+--- ../l4sys/include/ARCH-x86/kdebug.h
++++ ../l4sys/include/ARCH-x86/kdebug.h
+@@ -53,6 +53,13 @@
+     1:
+ #endif
++#define enter_kdebug42(text) \
++asm(\
++    "int      $0x42\n\t"\
++    "jmp      1f      \n\t"\
++    ".ascii   \"" text "\"\n\t"\
++    "1:                       \n\t"\
++    )
+ /**
+  * Enter L4 kernel debugger (plain assembler version)
+  * \ingroup l4_debugger_api
+@@ -111,6 +118,8 @@
+  */
+ L4_INLINE void
+ outchar(char c) L4_NOTHROW;
++L4_INLINE void
++outchar42(char c) L4_NOTHROW;
+ /**
+  * Print character string
+@@ -139,6 +148,8 @@
+  */
+ L4_INLINE void
+ outhex32(int number) L4_NOTHROW;
++L4_INLINE void
++outhex42(int number) L4_NOTHROW;
+ /**
+  * Print 20 bit number (hexadecimal)
+@@ -270,6 +281,17 @@
+       );
+ }
++L4_INLINE void
++outchar42(char c) L4_NOTHROW
++{
++  asm(
++      "int    $0x42\n\t"
++      "cmpb   $0,%%al \n\t"
++      : /* No output */
++      : "a" (c)
++      );
++}
++
+ /* actually outstring is outcstring */
+ L4_INLINE void
+ outstring(const char *text) L4_NOTHROW
+@@ -311,6 +333,17 @@
+ }
+ L4_INLINE void
++outhex42(int number) L4_NOTHROW
++{
++  asm(
++      "int    $0x42\n\t"
++      "cmpb   $5,%%al \n\t"
++      : /* No output */
++      : "a" (number)
++      );
++}
++
++L4_INLINE void
+ outhex20(int number) L4_NOTHROW
+ {
+   asm(
index 11d1862e0aca7b47d4013dd2c3942a0bc08f0d34..50986871632d2e5641a4eaceb73d725c9ae58042 100644 (file)
@@ -12,6 +12,7 @@ OBSERVERS = $(addprefix fault_handlers/, \
               observer.cc \
               pagefault.cc \
               print_vcpu_state.cc \
+              replicalog.cc \
               syscalls.cc \
               swifi.cc \
               trap_limit.cc \
@@ -46,6 +47,7 @@ SRC_CC      = main.cc \
               app_thread.cc \
               handler.cc \
               emulation.cc \
+              logging.cc \
               $(OBSERVERS) \
               $(ASMJIT)
 
@@ -56,7 +58,7 @@ SRC_CC      = main.cc \
 
 # list requirements of your program here
 REQUIRES_LIBS = libvcpu libstdc++ libloader libudis86 libiniparser libpthread \
-                cxx_io libio-vbus
+                cxx_io libio-vbus libuu
 #REQUIRES_LIBS += lwip liblwip_netif_ankh
 
 include $(L4DIR)/mk/prog.mk
index 9fb2d83771a30b11ad7ad9220b08f989c9a97cd8..564fe4bd0a93e29302ed2a9822d8fa8892352d63 100644 (file)
@@ -5,7 +5,7 @@
  *
  *    Definitions of applications, instances
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
@@ -132,6 +132,7 @@ class App_instance
                        l4_fpage_t fp = l4_fpage(local, shift, flags);
                        //DEBUG() << "fp: " << fp.raw;
                        l4_msgtag_t tag = vcpu_task()->map(L4Re::This_task, fp, remote);
+                       _check(l4_msgtag_has_error(tag), "error mapping page");
                        //DEBUG() << "mapped " << std::hex << fp.raw << " : " << std::hex << tag.raw;
                        for (unsigned offs = 0; offs < (L4_PAGESIZE << (shift - L4_PAGESHIFT));
                                  offs += L4_PAGESIZE) {
@@ -153,6 +154,7 @@ class App_instance
                        while (size > 0) {
                                unsigned frame_l = local_start  >> L4_PAGESHIFT;
                                unsigned frame_r = remote_start >> L4_PAGESHIFT;
+                               (void)frame_l; (void)frame_r;
                                unsigned shift   = 0;
 
 /* Macro checks whether the size fits a given number of pages */
@@ -181,9 +183,8 @@ class App_instance
                        fp.raw = fpraw;
                        remote = l4_fpage_page(fp) << L4_PAGESHIFT;
 
-                       //DEBUG() << "unmap @ " << std::hex << "0x" << remote;
                        l4_addr_t a = _mappings[remote];
-                       //DEBUG() << std::hex << remote << " -> " << "0x" << a;
+                       DEBUG() << "unmap @ " << std::hex << remote << " -> " << "0x" << a;
                        vcpu_task()->unmap(l4_fpage(a, L4_PAGESIZE, L4_FPAGE_RO), L4_FP_ALL_SPACES);
                        _mappings[remote] = 0;
                        //enter_kdebug("unmapped");
index 6fd57e3cb1331af4a754b2e824aedfc8c61091a7..4adf06d6e238a4267c67809d9d764fb8d4bbdf2d 100644 (file)
@@ -7,7 +7,7 @@
  *    Implementation of application loading. Similar to the stuff
  *    moe and ned do.
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
index e6aad63d7f72e7591fa98d2e74517485b46cd71b..e5e897a34ed8d4b9c4e1570535b4d108ad43a35f 100644 (file)
@@ -7,7 +7,7 @@
  *    Implementation of application loading. Similar to the stuff
  *    moe and ned do.
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
@@ -187,12 +187,8 @@ Romain::App_model::add_env()
 
 Romain::App_model::Dataspace Romain::App_model::alloc_ds(unsigned long size) const
 {
-       Dataspace ds = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
-       _check(!ds.is_valid(), "ds cap allocation failed");
-
-       long r = L4Re::Env::env()->mem_alloc()->alloc(size, ds);
-       _check(r != 0, "dataspace allocation failed");
-
+       Dataspace ds;
+       Romain::Region_map::allocate_ds(&ds, size);
        return ds;
 }
 
index a4f23d2a2f32274f1e7d7622dea228b85006c26c..e318ee6d890ca2f9f38834e61cb0637075cf0e83 100644 (file)
@@ -3,7 +3,7 @@
  *
  *     App_thread functions for creating and preparing a new VCPU
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
@@ -110,10 +110,10 @@ Romain::App_thread::csum_state()
             + _vcpu->r()->sp
             + _vcpu->r()->ax
             + _vcpu->r()->bx
+#if 0
             + _vcpu->r()->cx
             + _vcpu->r()->dx
             + _vcpu->r()->bp
-#if 0
             + _vcpu->r()->fs
             + _vcpu->r()->gs
 #endif
index 00a4379f763db3e5e9f4f9f035b7c2ff4910f5e9..eedcd8408e8b1af1ace895d7c46bcbaae57ccc9a 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Handling of Romain config stuff
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
@@ -74,10 +74,10 @@ struct ConfigIntValue : public ConfigValue
 struct ConfigStringValue : public ConfigValue
 {
        char const *_val;
-       ConfigStringValue(char const * const key, char *_default = 0)
+       ConfigStringValue(char const * const key, char const *_default = 0)
                : ConfigValue()
        {
-               _val = iniparser_getstring(_dict, key, _default);
+               _val = iniparser_getstring(_dict, key, const_cast<char*>(_default));
        }
 
        operator char const *() { return _val; }
index 4ced208fbf2de846eae30d93d4f06d9409be44b5..730655c75f40bb33be4a762db9e1d3a6827e0e79 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Globally used constants
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
 namespace Romain
 {
        enum {
-               MAX_REPLICAS       =  3,        // maximum # of allowed replicas
-               MAX_OBSERVERS      = 16,        // maximum # of fault observers
-               TRAMPOLINE_SIZE    = 64,        // size of the per-thread trampoline area
-               HANDLER_STACK_SIZE = (1 << 14), // size of the VCPU handler stack
-               DEBUG_ENTRIES      = 1000,      // dbg: # of 64bit entries in thread->_measurements
-               FIRST_REPLICA_CAP  = 0x1000,    // first replica cap markes as unused
-               LOCK_INFO_PAGE     = 0xA000,    // address the lock info page is mapped to in replicas
+               MAX_REPLICAS        =  3,        // maximum # of allowed replicas
+               MAX_OBSERVERS       = 16,        // maximum # of fault observers
+               TRAMPOLINE_SIZE     = 64,        // size of the per-thread trampoline area
+               HANDLER_STACK_SIZE  = (1 << 14), // size of the VCPU handler stack
+               DEBUG_ENTRIES       = 1000,      // dbg: # of 64bit entries in thread->_measurements
+               FIRST_REPLICA_CAP   = 0x1000,    // first replica cap markes as unused
+               LOCK_INFO_PAGE      = 0xA000,    // address the lock info page is mapped to in replicas
+               REPLICA_TSC_ADDRESS = 0xC000,    // start of replica-shared TSC buffer
+               REPLICA_LOG_ADDRESS = 0xB0000000,   // start of replica log buffer (XXX: don't go lower -> KIP is there!)
        };
 }
index e7dbc2bd8748e9f6c89532748ab12f600d2d1981..a08943aa6cb23df3e568b9d869cd5d9c188a1e5d 100644 (file)
@@ -7,7 +7,7 @@
  *     Basic definition of an instruction emulator. Used
  *     by the framework to emulate memory write instructions.
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
index b630ec152a36eb0ab948f04d61e9a1fd5d87dda3..63dd7292d2a72fe6f125c8f80884fe3af681a063 100644 (file)
@@ -3,7 +3,7 @@
  *
  *     Implementation of the write instruction emulator.
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
index 77d3a9e8566c59b7289a2e44c6cf017c578fca8f..39855d6bccc05f6173e494861fad078624cd712c 100644 (file)
@@ -6,7 +6,7 @@
  *
  *     Romain exception definitions.
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
@@ -38,6 +38,10 @@ class Romain_error : public L4::Base_exception
 };
 
 
+/*
+ * XXX: Meh ... the use of the condition is actually opposite to what one would expect
+ *      for a standard ASSERT. This drives me nuts. Need to fix it some day.
+ */
 #define _check(cond, message) \
        do { \
                if (cond) { \
index 8bb6494b54ac4e77a193457b7f1ccb2b489e4368..03fc127ef9e601d85e37451bf397b31880404d7f 100644 (file)
@@ -7,7 +7,7 @@
  *     (simplegdb:singlestep). It will then place a breakpoint (0xCC) on this address
  *     and once this BP is hit, start single-stepping from this point on.
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
index df980504d6de56a70fb9168c7b925830c5174461..4e08873f5e98bd0ca41a90b755876b5b1df9dd5e 100644 (file)
@@ -4,7 +4,7 @@
  *
  *     Debugging interface
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
index 5708f35aac617cadb715ce114a94b60f5ea5610d..0c5b7213111ed2e01e5640e0c1a92d1a6f5ba0a3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * kiptime.cc --
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
index c23bd0c76369c71e19144a7afa932696b62fb25b..af875d4a3e66b183f5e6d4cf308e5e47f78fc9c8 100644 (file)
@@ -1,3 +1,15 @@
+/*
+ * lock_observer.cc --
+ *
+ *     Deterministic lock acquisition
+ *
+ * (c) 2012-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ *     economic rights: Technische Universität Dresden (Germany)
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+
 #include "lock_observer.h"
 
 #define DEBUGt(t) DEBUG() <<  "[" << t->vcpu() << "] "
@@ -7,7 +19,17 @@ Romain::PThreadLockObserver::Create()
 { return new PThreadLock_priv(); }
 
 
-void Romain::PThreadLock_priv::status() const { }
+void Romain::PThreadLock_priv::status() const
+{
+       INFO() << "LOCK.lock   = " << det_lock_count;
+       INFO() << "LOCK.unlock = " << det_unlock_count;
+       INFO() << "MTX.lock    = " << mtx_lock_count;
+       INFO() << "MTX.unlock  = " << mtx_unlock_count;
+       INFO() << "pt.lock     = " << pt_lock_count;
+       INFO() << "pt.unlock   = " << pt_unlock_count;
+       INFO() << "# ignored   = " << ignore_count;
+       INFO() << "Total count = " << total_count;
+}
 
 
 Romain::Observer::ObserverReturnVal
@@ -20,15 +42,20 @@ Romain::PThreadLock_priv::notify(Romain::App_instance* inst,
                return Romain::Observer::Ignored;
        }
 
+       DEBUG() << "LOCK observer";
+       l4util_inc32(&total_count);
+
        /*
         * HACK: intercept notifications coming from the replication-
         *       aware pthread library.
         */
        if (thread->vcpu()->r()->ip == 0xA021) {
+               l4util_inc32(&det_lock_count);
                det_lock(inst, thread, group, model);
                //thread->vcpu()->r()->flags |= TrapFlag;
                return Romain::Observer::Replicatable;
        } else if (thread->vcpu()->r()->ip == 0xA041) {
+               l4util_inc32(&det_unlock_count);
                det_unlock(inst, thread, group, model);
                return Romain::Observer::Replicatable;
        }
@@ -42,52 +69,72 @@ Romain::PThreadLock_priv::notify(Romain::App_instance* inst,
 
        HANDLE_BP(mutex_lock_id, mutex_lock);
        HANDLE_BP(mutex_unlock_id, mutex_unlock);
-       HANDLE_BP(mutex_init_id, mutex_init);
+       //HANDLE_BP(mutex_init_id, mutex_init);
        HANDLE_BP(pt_lock_id, lock);
        HANDLE_BP(pt_unlock_id, unlock);
 
 #undef HANDLE_BP
 
+       l4util_inc32(&ignore_count);
        return Romain::Observer::Ignored;
 }
 
+
+void Romain::PThreadLock_priv::attach_lock_info_page(Romain::App_model *am)
+{
+       _lip_ds           = am->alloc_ds(L4_PAGESIZE);
+       _lip_local        = am->local_attach_ds(_lip_ds, L4_PAGESIZE, 0);
+       INFO() << "Local LIP address: " << std::hex << _lip_local;
+       void* remote__lip = (void*)am->prog_attach_ds(Romain::LOCK_INFO_PAGE,
+                                                     L4_PAGESIZE, _lip_ds, 0, 0,
+                                                     "lock info page",
+                                                     _lip_local, true);
+       _check(reinterpret_cast<l4_umword_t>(remote__lip) != Romain::LOCK_INFO_PAGE,
+              "LIP did not attach to proper remote location");
+
+       am->lockinfo_local(_lip_local);
+       am->lockinfo_remote(Romain::LOCK_INFO_PAGE);
+
+       memset((void*)_lip_local, 0, L4_PAGESIZE);
+}
+
+
 void Romain::PThreadLock_priv::startup_notify(Romain::App_instance *inst,
                                               Romain::App_thread *,
                                               Romain::Thread_group *,
                                               Romain::App_model *am)
 {
-       static unsigned callCount = 0;
-       lock_info *lip            = reinterpret_cast<lock_info*>(_lip_local);
+       static unsigned callCount  = 0;
+       lock_info *lip             = reinterpret_cast<lock_info*>(_lip_local);
 
-       if (!callCount) {
 #if INTERNAL_DETERMINISM
-               _lip_ds           = am->alloc_ds(L4_PAGESIZE);
-               _lip_local        = am->local_attach_ds(_lip_ds, L4_PAGESIZE, 0);
-               INFO() << "Local LIP address: " << std::hex << _lip_local;
-               lip               = reinterpret_cast<lock_info*>(_lip_local);
-               void* remote__lip = (void*)am->prog_attach_ds(Romain::LOCK_INFO_PAGE,
-                                                             L4_PAGESIZE, _lip_ds, 0, 0,
-                                                             "lock info page",
-                                                             _lip_local, true);
-
-               am->lockinfo_local(_lip_local);
-               am->lockinfo_remote(Romain::LOCK_INFO_PAGE);
-
-               memset((void*)_lip_local, 0, L4_PAGESIZE);
-
-               lip->locks[0].lockdesc = 0xFFFFFFFF;
+       if (!callCount) {
+               /*
+                * For internal determinism, we make sure that we only attach the
+                * lock info page once (for the first replica), because the LIP
+                * is shared across all replicas.
+                */
+               attach_lock_info_page(am);
+               lip                    = reinterpret_cast<lock_info*>(_lip_local);
+               lip->locks[0].lockdesc = 0xFAFAFAFA;
                lip->locks[0].owner    = 0xDEADBEEF;
 
 #endif
                //DEBUG() << "Replica LIP address: " << std::hex << remote_lock_info;
 
+               /*
+                * Breakpoints / patching of function entries is only done once,
+                * because code is shared across all replicas.
+                */
                for (unsigned idx = 0; idx < pt_max_wrappers; ++idx) {
                        DEBUG() << idx;
                        _functions[idx].activate(inst, am);
                }
+#if INTERNAL_DETERMINISM
        }
        callCount++;
        lip->replica_count += 1;
+#endif
        //enter_kdebug();
 }
 
@@ -131,6 +178,7 @@ void Romain::PThreadLock_priv::lock(Romain::App_instance *inst,
                                     Romain::Thread_group *tg,
                                     Romain::App_model *am)
 {
+       l4util_inc32(&pt_lock_count);
        l4_addr_t stack  = am->rm()->remote_to_local(t->vcpu()->r()->sp, inst->id());
        l4_umword_t ret  = *(l4_umword_t*)stack;
        l4_umword_t lock = t->vcpu()->r()->ax;
@@ -140,8 +188,6 @@ void Romain::PThreadLock_priv::lock(Romain::App_instance *inst,
        DEBUG() << "Lock @ " << std::hex << lock;
        DEBUG() << "Return addr " << std::hex << ret;
 
-       //enter_kdebug("lock");
-
        lookup_or_create(lock)->lock(tg);
 
        t->vcpu()->r()->sp += sizeof(l4_umword_t); // RET: inc. ESP
@@ -159,6 +205,7 @@ void Romain::PThreadLock_priv::unlock(Romain::App_instance *inst,
                                       Romain::Thread_group *tg,
                                       Romain::App_model *am)
 {
+       l4util_inc32(&pt_unlock_count);
        l4_addr_t stack     = am->rm()->remote_to_local(t->vcpu()->r()->sp, inst->id());
        l4_umword_t retaddr = *(l4_umword_t*)stack;
        l4_umword_t lock    = *(l4_umword_t*)(stack + 1*sizeof(l4_umword_t));
@@ -183,11 +230,13 @@ void Romain::PThreadLock_priv::unlock(Romain::App_instance *inst,
 void Romain::PThreadLock_priv::mutex_lock(Romain::App_instance* inst, Romain::App_thread* t,
                                           Romain::Thread_group* group, Romain::App_model* model)
 {
+       l4util_inc32(&mtx_lock_count);
+
        l4_addr_t stack     = model->rm()->remote_to_local(t->vcpu()->r()->sp, inst->id());
        l4_umword_t retaddr = *(l4_umword_t*)stack;
        l4_umword_t lock    = *(l4_umword_t*)(stack + 1*sizeof(l4_umword_t));
 
-       //DEBUG() << "lock @ " << std::hex << lock << " ESP.local = " << stack;
+       DEBUG() << "lock @ " << std::hex << lock << " ESP.local = " << stack;
        PThreadMutex* mtx = _locks[lock];
        if (!mtx) {
                /*
@@ -217,6 +266,8 @@ void Romain::PThreadLock_priv::mutex_lock(Romain::App_instance* inst, Romain::Ap
 void Romain::PThreadLock_priv::mutex_unlock(Romain::App_instance* inst, Romain::App_thread* t,
                                             Romain::Thread_group* group, Romain::App_model* model)
 {
+       l4util_inc32(&mtx_unlock_count);
+
        l4_addr_t stack     = model->rm()->remote_to_local(t->vcpu()->r()->sp, inst->id());
        l4_umword_t retaddr = *(l4_umword_t*)stack;
        l4_umword_t lock    = *(l4_umword_t*)(stack + 1*sizeof(l4_umword_t));
index ac8e12501d3167fbff4b28eba2a3bfafd6dcb2a8..64268b1b262c48e1d48cb39231c8cc7f580c96b3 100644 (file)
@@ -5,7 +5,7 @@
  *
  *     Deterministic lock acquisition
  *
- * (c) 2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2012-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
@@ -18,7 +18,9 @@
 #define EXTERNAL_DETERMINISM 0
 #define INTERNAL_DETERMINISM 1
 
+EXTERN_C_BEGIN
 #include <l4/plr/pthread_rep.h>
+EXTERN_C_END
 
 namespace Romain
 {
@@ -55,7 +57,7 @@ namespace Romain
                         * which may not be the case due to replication).
                         */ 
                        sem_init(&sem, 0, 1);
-                       //pthread_mutex_init(&mtx, 0);
+                       pthread_mutex_init(&mtx, 0);
                }
 
 
@@ -64,18 +66,23 @@ namespace Romain
                 */
                int lock(Romain::Thread_group* tg)
                {
+                       pthread_mutex_lock(&mtx);
                        /*
                         * If this is recursive, only increment the counter.
                         */
                        if (recursive and counter) {
-                               if (tg != owner)
+                               if (tg != owner) {
+                                       pthread_mutex_unlock(&mtx);
                                        return 1; // EPERM
+                               }
                                counter++;
+                               pthread_mutex_unlock(&mtx);
                                return 0;
                        }
 
                        owner = tg;
                        counter++;
+                       pthread_mutex_unlock(&mtx);
 
                        return sem_wait(&sem);
                        //return pthread_mutex_lock(&mtx);
@@ -87,11 +94,13 @@ namespace Romain
                 */
                int unlock()
                {
+                       pthread_mutex_lock(&mtx);
                        counter--;
 
                        if (recursive and (counter == 0)) {
                                owner = 0;
                        }
+                       pthread_mutex_unlock(&mtx);
 
                        return sem_post(&sem);
                        //return pthread_mutex_unlock(&mtx);
@@ -139,7 +148,12 @@ namespace Romain
                                do_patch(am);
                        }
 #else
+                       DEBUG() << lockID_to_str(function_id);
+                       if ((orig_address == 0) or (orig_address == ~0))
+                               return;
+                       bp = new Breakpoint(orig_address);
                        bp->activate(inst, am);
+                       DEBUG() << "BP set.";
 #endif
                }
 
@@ -290,14 +304,29 @@ namespace Romain
                std::map<l4_umword_t, PThreadMutex*> _locks;
                Romain::App_model::Dataspace         _lip_ds;
                l4_addr_t                            _lip_local;
+               pthread_mutex_t                      _tablemtx;
+
+               unsigned /* Internal determinism counters */
+                            det_lock_count,   // counter: det_lock
+                        det_unlock_count, // counter: det_unlock
+                        /* External determinism counters: */
+                        mtx_lock_count,   // counter: pthread_mutex_lock
+                        mtx_unlock_count, // counter: pthread_mutex_unlock
+                        pt_lock_count,    // counter: __pthread_lock
+                        pt_unlock_count,  // counter: __pthread_unlock
+                        /* Global counter */
+                        ignore_count,     // counter: call ignored
+                        total_count;      // counter: total invocations
 
                PThreadMutex* lookup_or_fail(unsigned addr)
                {
+                       pthread_mutex_lock(&_tablemtx);
                        PThreadMutex* r = _locks[addr];
                        if (!r) {
                                ERROR() << "Called with uninitialized mutex?";
                                enter_kdebug("op on uninitialized mutex");
                        }
+                       pthread_mutex_unlock(&_tablemtx);
                        return r;
                }
 
@@ -305,6 +334,7 @@ namespace Romain
                PThreadMutex* lookup_or_create(unsigned addr, bool init_locked = false,
                                               Romain::Thread_group* tg = 0)
                {
+                       pthread_mutex_lock(&_tablemtx);
                        PThreadMutex* mtx = _locks[addr];
                        if (!mtx) {
                                mtx           = new PThreadMutex(false);
@@ -314,6 +344,7 @@ namespace Romain
                                        mtx->lock(tg);
                                }
                        }
+                       pthread_mutex_unlock(&_tablemtx);
                        return mtx;
                }
 
@@ -327,7 +358,7 @@ namespace Romain
                        l4_addr_t lock      = *(l4_addr_t*)(stackaddr + 4);
                        DEBUG() << "\033[35mLOCK @ \033[0m" << std::hex << lock;
                        lookup_or_create(lock, true, tg)->lock(tg);
-                       enter_kdebug("det_lock");
+                       //enter_kdebug("det_lock");
                }
 
 
@@ -340,21 +371,35 @@ namespace Romain
                        l4_addr_t lock      = *(l4_addr_t*)(stackaddr + 4);
                        DEBUG() << "\033[35mUNLOCK @ \033[0m" << std::hex << lock;
 
+                       pthread_mutex_lock(&_tablemtx);
                        PThreadMutex* m = _locks[lock];
-                       while (!m) {
-                               l4_thread_yield();
-                               m = _locks[lock];
+                       if (!m) {
+                               /* This may actually happen! The unlocker is simply faster sending the
+                                * notification than the locker is in sending his wakeup. Hence,
+                                * we need to potentially create the respective lock here.
+                                */
+                               l4_umword_t mtx_kind_ptr = am->rm()->remote_to_local(lock + 12, inst->id());
+                               m            = new PThreadMutex(*(l4_umword_t*)mtx_kind_ptr == PTHREAD_MUTEX_RECURSIVE_NP);
+                               _locks[lock] = m;
                        }
-
-                       lookup_or_fail(lock)->unlock();
-                       enter_kdebug("det_unlock");
+                       pthread_mutex_unlock(&_tablemtx);
+                       m->unlock();
+                       //enter_kdebug("det_unlock");
                }
 
+
+               void attach_lock_info_page(Romain::App_model *am);
+
                
                public:
                PThreadLock_priv()
+                       : det_lock_count(0), det_unlock_count(0),
+                         mtx_lock_count(0), mtx_unlock_count(0),
+                         pt_lock_count(0), pt_unlock_count(0),
+                         ignore_count(0), total_count(0)
                {
-#if 1
+                       pthread_mutex_init(&_tablemtx, 0);
+#if 0
                        _functions[mutex_init_id].configure("threads:mutex_init",
                                                            "threads:mutex_init_rep",
                                                            mutex_init_id);
index 013ddf1cfbcda20c7790fe294700753c47fa6ddb..17aeac0afef6c5e164c2811149eed11d74c4020e 100644 (file)
@@ -3,7 +3,7 @@
  *
  *    General fault observer functions
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
@@ -32,6 +32,7 @@ Romain::ObserverFactory::CreateObserver(char const *name)
        CASE("kip-time",   KIPTimeObserver::Create());
        CASE("trap_limit", TrapLimitObserver::Create());
        CASE("threads",    PThreadLockObserver::Create());
+       CASE("replicalog", new ReplicaLogObserver());
 
 #if 0
        if (strcmp(name, "gdb") == 0) {
index ddf407568e224374facea22b5cc5490aafa719f9..b60e529449f7b7060b60beb13851368bcc8272c4 100644 (file)
@@ -5,7 +5,7 @@
  *
  *    Fault observer interface
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
@@ -150,4 +150,21 @@ namespace Romain
                public:
                static PThreadLockObserver* Create();
        };
+
+
+       class ReplicaLogObserver : public Observer
+       {
+               DECLARE_OBSERVER("replica::log");
+
+               public:
+                       ReplicaLogObserver();
+
+               private:
+                       struct {
+                               l4_addr_t local_addr;
+                       } buffers[Romain::MAX_REPLICAS];
+
+                       void map_eventlog(Romain::App_instance *i, int logsizeMB);
+                       void dump_eventlog(unsigned id) const;
+       };
 }
index 78e4bd76eeec6511abe31cc80bcd6401cfd66b31..2bb1a2bf2253822df31d4a5e27f3249ab263a0f3 100644 (file)
@@ -18,6 +18,7 @@
 #include "../app_loading"
 #include "../locking.h"
 #include "../configuration"
+#include "syscalls_handler.h"
 
 #include "observers.h"
 
@@ -60,6 +61,15 @@ Romain::PageFaultObserver::notify(Romain::App_instance *i, Romain::App_thread *t
        bool write_pf = vcpu->r()->err & 0x2;
        l4_addr_t pfa = vcpu->r()->pfa;
 
+       Measurements::GenericEvent *ev = Romain::_the_instance_manager->logbuf()->next();
+       ev->header.tsc         = Romain::_the_instance_manager->logbuf()->getTime(Log::logLocalTSC);
+       ev->header.vcpu        = (l4_uint32_t)t->vcpu();
+       ev->header.type        = Measurements::Pagefault;
+       ev->data.pf.address    = pfa;
+       ev->data.pf.rw         = write_pf ? 1 : 0;
+       ev->data.pf.localbase  = 0;
+       ev->data.pf.remotebase = 0;
+
        MSGt(t) << (write_pf ? "\033[31mwrite\033[0m" : "\033[34;1mread\033[0m")
              << " page fault @ 0x" << std::hex << pfa;
 
@@ -117,6 +127,8 @@ Romain::PageFaultObserver::notify(Romain::App_instance *i, Romain::App_thread *t
                        }
 #undef MAX_MAP_SHIFT
 #endif
+                       ev->data.pf.localbase  = n->second.local_region(i->id()).start() + offset_in_region;
+                       ev->data.pf.remotebase = n->first.start() + offset_in_region;
 
                        i->map(n->second.local_region(i->id()).start() + offset_in_region, // local addr
                                   n->first.start() + offset_in_region,                        // remote addr
diff --git a/l4/pkg/plr/server/src/fault_handlers/replicalog.cc b/l4/pkg/plr/server/src/fault_handlers/replicalog.cc
new file mode 100644 (file)
index 0000000..a146cfa
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * replicalog.cc --
+ *
+ *     Fault observer that attaches a magic event buffer
+ *     (see measurements.h) to each replica and dumps the replicas'
+ *     event buffers after the program terminates.
+ *
+ * (c) 2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ *     economic rights: Technische Universität Dresden (Germany)
+ *
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+
+#include "observers.h"
+#include "../configuration"
+#include "../memory"
+#include "../manager"
+
+#include <l4/plr/uu.h>
+
+namespace Romain {
+       extern InstanceManager *_the_instance_manager;
+}
+
+Romain::ReplicaLogObserver::ReplicaLogObserver()
+{
+       for (unsigned i = 0; i < Romain::MAX_REPLICAS; ++i) {
+               buffers[i].local_addr = 0;
+       }
+}
+
+
+void
+Romain::ReplicaLogObserver::map_eventlog(Romain::App_instance *i, int logsizeMB)
+{
+       int size = logsizeMB << 20;
+       unsigned mapops = 0;
+       l4_addr_t local_map_addr = buffers[i->id()].local_addr;
+       l4_addr_t remote_map_addr = Romain::REPLICA_LOG_ADDRESS;
+
+       /* 1. map the TSC shared page read-only */
+       INFO() << "shared tsc @ " << Romain::_the_instance_manager->logbuf()->timestamp;
+       i->map_aligned(reinterpret_cast<l4_addr_t>(Romain::_the_instance_manager->logbuf()->timestamp),
+                      Romain::REPLICA_TSC_ADDRESS, L4_PAGESHIFT, L4_FPAGE_RO);
+
+       /* Now initialize the shared event buffer */
+       Measurements::EventBuf* buf = reinterpret_cast<Measurements::EventBuf*>(buffers[i->id()].local_addr);
+       buf->index = 0;
+       buf->sharedTSC = true;
+       buf->set_buffer((unsigned char*)remote_map_addr + sizeof(Measurements::GenericEvent), (logsizeMB << 20) - sizeof(Measurements::GenericEvent));
+       INFO() << buf->index << " " << buf->size << std::endl;
+
+       while (size > 0) {
+
+               unsigned sz, shift;
+
+               if (size >= (4 << 20)) { // map 4 MB page
+                       sz = L4_SUPERPAGESIZE;
+                       shift = L4_SUPERPAGESHIFT;
+               } else { // map 4 kB page
+                       sz = L4_PAGESIZE;
+                       shift = L4_PAGESHIFT;
+               }
+
+               i->map_aligned(local_map_addr, remote_map_addr, shift, L4_FPAGE_RW);
+               size            -= sz;
+               local_map_addr  += sz;
+               remote_map_addr += sz;
+               mapops          += 1;
+       }
+
+       INFO() << "Mapped to replica. Used " << mapops << " map() operations";
+}
+
+
+void Romain::ReplicaLogObserver::startup_notify(Romain::App_instance *i,
+                                                                   Romain::App_thread *t,
+                                                                   Romain::Thread_group *tg,
+                                                                   Romain::App_model *a)
+{
+       static bool logregion_reserved = false;
+
+       int logMB = ConfigIntValue("general:replicalogsize");
+       if (logMB == -1) { // use general logbuf size if no specific size was set
+               logMB = ConfigIntValue("general:logbuf");
+       }
+
+       INFO() << "Replica log size: " << logMB << " MB";
+
+       /* Reserve the area at the replicas' RM. We map this buffer without going through
+          the official channels. */
+       if (!logregion_reserved) {
+               a->rm()->attach_area(Romain::REPLICA_LOG_ADDRESS, logMB << 20, 0, L4_SUPERPAGESHIFT);
+               logregion_reserved = true;
+       }
+
+       L4::Cap<L4Re::Dataspace> mem;
+       buffers[i->id()].local_addr = Romain::Region_map::allocate_and_attach(&mem, logMB << 20, 0, L4_SUPERPAGESHIFT);
+       INFO() << "Buffer for instance " << i->id() << " @ " << std::hex << buffers[i->id()].local_addr;
+       l4_touch_rw(reinterpret_cast<void*>(buffers[i->id()].local_addr), logMB << 20);
+
+       map_eventlog(i, logMB);
+
+       //enter_kdebug("LogObserver::startup");
+}
+
+
+Romain::Observer::ObserverReturnVal
+Romain::ReplicaLogObserver::notify(Romain::App_instance *i,
+                                   Romain::App_thread *t,
+                                   Romain::Thread_group *tg,
+                                   Romain::App_model *a)
+{
+       /* We don't handle any events. */
+       return Romain::Observer::Ignored;
+}
+
+
+void
+Romain::ReplicaLogObserver::dump_eventlog(unsigned id) const
+{
+       INFO() << "Dumping ... " << id;
+
+       Measurements::EventBuf *buf = reinterpret_cast<Measurements::EventBuf*>(buffers[id].local_addr);
+       INFO() << "  event buffer @ " << std::hex << buf;
+
+       char filename[32];
+       snprintf(filename, 32, "replica%d.log", id);
+
+       INFO() << "file: " << filename;
+
+       unsigned oldest = buf->oldest();
+
+       INFO() << "oldest: " << oldest;
+
+       l4_umword_t dump_start, dump_size;
+       if (!oldest) {
+               dump_start = 0;
+               dump_size  = buf->index * sizeof(Measurements::GenericEvent);
+       } else {
+               dump_start = oldest * sizeof(Measurements::GenericEvent);
+               dump_size  = buf->size * sizeof(Measurements::GenericEvent);
+       }
+
+       /* buf addr is relocated in replica AS -> need to retransform */
+       char *bufaddr = ((l4_addr_t)buf->buffer - Romain::REPLICA_LOG_ADDRESS) + (char*)buf;
+
+       INFO() << "file: " << filename << " start " << dump_start << " size " << dump_size;
+       uu_dumpz_ringbuffer(filename, bufaddr,
+                           buf->size * sizeof(Measurements::GenericEvent),
+                           dump_start, dump_size);
+}
+
+
+void
+Romain::ReplicaLogObserver::status() const
+{
+       for (unsigned i = 0; i < Romain::MAX_REPLICAS; ++i) {
+               if (buffers[i].local_addr != 0) {
+                       dump_eventlog(i);
+               }
+       }
+       //enter_kdebug("LogObserver::status");
+}
index c07e6a2a07079508f2eafd97dfd36ea0ad8c604d..aec84a3e1437941d62c0ef3af1f63af954f5a252 100644 (file)
@@ -5,7 +5,7 @@
  *
  *     Fault observer for fault injection experiments
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
index 25f35d19d3a7e8652471a2f7fa2c004c62a9d145..50282af6040163b535d0d5aa5144d263b6be96a6 100644 (file)
@@ -3,7 +3,7 @@
  *
  *     Implementation of Romain syscall handling.
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
@@ -67,6 +67,13 @@ Romain::SyscallObserver::notify(Romain::App_instance *i,
                l4_msgtag_t *tag = reinterpret_cast<l4_msgtag_t*>(&t->vcpu()->r()->ax);
                MSG() << "SYSENTER(" << tg->name << ") tag = " << std::hex << tag->label();
 
+               Measurements::GenericEvent* ev = Romain::_the_instance_manager->logbuf()->next();
+               ev->header.tsc     = Romain::_the_instance_manager->logbuf()->getTime(Log::logLocalTSC);
+               ev->header.vcpu    = (l4_uint32_t)t->vcpu();
+               ev->header.type    = Measurements::Syscall;
+               ev->data.sys.eip   = t->vcpu()->r()->bx;
+               ev->data.sys.label = tag->label();
+
                /*
                 * Fiasco-specific:
                 *      EBX is return address
@@ -139,8 +146,18 @@ Romain::SyscallObserver::notify(Romain::App_instance *i,
                                        INFO() << "Instance " << i->id() << " exitting. Time "
                                               << "\033[33;1m" << tv.tv_sec << "." << tv.tv_usec
                                               << "\033[0m";
+
+                                       Measurements::GenericEvent* ev = Romain::_the_instance_manager->logbuf()->next();
+                                       ev->header.tsc                 = Romain::_the_instance_manager->logbuf()->getTime(Log::logLocalTSC);
+                                       ev->header.vcpu                = (l4_uint32_t)t->vcpu();
+                                       ev->header.type                = Measurements::Thread_stop;
+
                                        Romain::_the_instance_manager->query_observer_status();
+
+                                       Romain::_the_instance_manager->logdump();
+                                       
                                        if (1) enter_kdebug("*#^");
+
                                        nullhandler.proxy_syscall(i, t, tg, a);
                                        retval = Romain::Observer::Replicatable;
                                }
@@ -332,8 +349,10 @@ void Romain::SyscallObserver::handle_task(Romain::App_instance* i,
        l4_umword_t    op = l4_utcb_mr_u(utcb)->mr[0] & L4_THREAD_OPCODE_MASK;
        switch(op) {
                case L4_TASK_UNMAP_OP:
+#if 0
                        MSGt(t) << "unmap";
                        i->unmap(l4_utcb_mr_u(utcb)->mr[2]);
+#endif
                        break;
                case L4_TASK_CAP_INFO_OP:
                        nullhandler.proxy_syscall(i,t,0,a);
@@ -403,7 +422,7 @@ Romain::Scheduling::handle(Romain::App_instance* inst,
                Romain::Thread_group* group = theObjectFactory.thread_for_cap(cap);
                group->scheduler_run(t);
        } else {
-               enter_kdebug("run_thread != 1");
+               //enter_kdebug("run_thread != 1");
                SyscallHandler::proxy_syscall(inst, t, tg, am);
        }
 
@@ -421,7 +440,6 @@ Romain::IrqHandler::handle(Romain::App_instance* inst,
        unsigned op     = l4_utcb_mr_u(utcb)->mr[0];
        unsigned label  = l4_utcb_mr_u(utcb)->mr[1];
        unsigned cap    = t->vcpu()->r()->dx & L4_CAP_MASK;
-       l4_msgtag_t ret;
 
        L4::Cap<L4::Irq> irq(cap);
 
index 559d40987636fa5acfadcc6b81bb18246b2afbad..af80ac1ba162a85eee1ad2f16f9754ac90a7bd4c 100644 (file)
@@ -5,7 +5,7 @@
  *
  *     Implementation of the factory system call
  *
- * (c) 2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2012-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
@@ -64,7 +64,7 @@ class Factory : public SyscallHandler
                 * made sure that all faults raised by these threads will be resolved,
                 * because we cannot be sure if they run before or after any subsequent
                 * code. */
-               unsigned cnt = 0;
+               //unsigned cnt = 0;
                for (std::vector<Romain::App_thread*>::const_iterator it = newgroup->threads.begin();
                         it != newgroup->threads.end(); ++it)
                {
index 2b10c2daac8263b8c9218215b5ccc70d2a377f78..558b337a725441eccd9da06ed0b000154e540a7b 100644 (file)
@@ -5,7 +5,7 @@
  *
  *     Interface for system call wrappers
  *
- * (c) 2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2012-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
index 4c5f9503c6bb99eff5e23885e0e3bb7b876fd850..a1d36d1395e1eafb3d6f235db009a368ec341cb5 100644 (file)
@@ -4,7 +4,7 @@
  *     Observer counting traps and terminating the
  *     application after a specified amount of calls.
  *
- * (c) 2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2012-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
index 202ebe2d33e1e2af7b9391c3b4337489e029a11f..a95b0a358f97eda4b7baed9d7460e1783f47bee7 100644 (file)
@@ -5,7 +5,7 @@
  *     system calls. Also, this observer handles Fiasco JDB
  *     traps.
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
index 23bddfbff0212bb36a98a45a91756605e856ed1b..ba5d969ec118d57b8a0065e1f53754eb524897e6 100644 (file)
@@ -7,7 +7,7 @@
  *    Definition of the generic fault handling class as well as
  *    specific sub-classes.
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
@@ -25,7 +25,7 @@ namespace Romain
        class App_model;
        class App_instance;
        class App_thread;
-       class Thread_group;
+       struct Thread_group;
 
 /* Make this a macro because every sub-class will have to define
  * these two virtual functions.
index 9669e2a6ad807254e0e88857346df7de6213ffc9..65f3afcb489d522257240b22df4979cd5b67facc 100644 (file)
@@ -5,7 +5,7 @@
  *
  *     Definition of external connectivity for the GDB server stub
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
index ae57eb7a59e07849d73b167b8c9711a069df75b4..9cc837e8b56f408c326a555191696972fb21cbf3 100644 (file)
@@ -3,7 +3,7 @@
  *
  *     GDB stub implemented on top of the Romain framework
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
index 02c464e50d7a084289a29dfd2f1d216034dbcacd..dcbf6afd1d1fd2e121a60b637bacd908206646bc 100644 (file)
@@ -5,7 +5,7 @@
  *
  *     Definition of the GDB server stub
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
index 7f57c696808e6476536d7f3dc01b9d490607862f..a6e50dfd204c63c0414ac6a009d49f3546288702 100644 (file)
@@ -3,7 +3,7 @@
  *
  *     Connectivity through serial interface
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
index dffbea1f0b1215bac1fe70c6b90504883b16ad80..c55aa59a26bc944f9d6d14354680bba14b87a8af 100644 (file)
@@ -3,7 +3,7 @@
  *
  *     Connectivity through TCP/IP
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
index a42c385b879bdbbe694543b93aa8b04c3812c4d7..ea5930a82d5008f5d17203ca8a91b0da3c6a4a1e 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Here's where the real stuff is going on
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
 #include "exceptions"
 #include "emulation"
 #include "app_loading"
+#include "fault_handlers/syscalls_handler.h"
 
 #include <cassert>
 
 #include <l4/sys/kdebug.h>
 #include <l4/util/bitops.h>
+#include <l4/util/rdtsc.h>
 
 #include <pthread-l4.h>
 #include <l4/sys/segment.h>
@@ -28,6 +30,8 @@
 #define MSGi(inst) MSG() << "[" << (inst)->id() << "] "
 #define MSGit(inst,tg) MSG() << "[" << (inst)->id() << "] \033[34;1m{" << tg->name << "}\033[0m "
 
+#define ____dummy " /* ST2 highlighting fix XXX */
+
 EXTERN_C void *pthread_fn(void *data);
 EXTERN_C void *pthread_fn(void *data)
 {
@@ -302,7 +306,7 @@ EXTERN_C void *split_handler_fn(void* data)
 
 #endif // SPLIT_HANDLING
 
-void __attribute__((noreturn)) Romain::InstanceManager::VCPU_startup(Romain::InstanceManager *,
+void __attribute__((noreturn)) Romain::InstanceManager::VCPU_startup(Romain::InstanceManager *m,
                                                                      Romain::App_instance *i,
                                                                      Romain::App_thread *t,
                                                                      Romain::Thread_group *tg,
@@ -332,6 +336,11 @@ void __attribute__((noreturn)) Romain::InstanceManager::VCPU_startup(Romain::Ins
 
        MSGit(i,tg) << "Resuming instance @ " << (void*)vcpu->r()->ip << " ...";
 
+       Measurements::GenericEvent* ev = m->logbuf()->next();
+       ev->header.tsc                 = Romain::_the_instance_manager->logbuf()->getTime(Log::logLocalTSC);
+       ev->header.vcpu                = (l4_uint32_t)vcpu;
+       ev->header.type                = Measurements::Thread_start;
+
        L4::Cap<L4::Thread> cap = t->vcpu_cap();
 
        cap->vcpu_resume_commit(cap->vcpu_resume_start());
@@ -364,6 +373,12 @@ static void local_vCPU_handling(Romain::InstanceManager *m,
                MSGit(i,tg) << "\033[33;1mTRAP 0x" << std::hex << vcpu->r()->trapno
                        << " @ 0x" << vcpu->r()->ip << "\033[0m";
 
+               if (t->vcpu()->r()->ip == 0xA041) {
+                       m->fault_notify(i,t,tg,a);
+                       break;
+               }
+
+#if 0
                /*
                 * HACK: In case we are using lock-internal determinism, there's a special
                 *       entry address in which a single replica will signal us if we need
@@ -376,6 +391,7 @@ static void local_vCPU_handling(Romain::InstanceManager *m,
                        m->fault_notify(i,t,tg,a);
                        break;
                }
+#endif
 
                Romain::Observer::ObserverReturnVal v         = Romain::Observer::Invalid;
 
@@ -501,6 +517,14 @@ void __attribute__((noreturn)) Romain::InstanceManager::VCPU_handler(Romain::Ins
        vcpu->state()->clear(L4_VCPU_F_EXCEPTIONS | L4_VCPU_F_DEBUG_EXC);
        handler_prolog(t);
 
+       Measurements::GenericEvent* ev = m->logbuf()->next();
+       ev->header.tsc     = Romain::_the_instance_manager->logbuf()->getTime(Log::logLocalTSC);
+       ev->header.vcpu        = (l4_uint32_t)vcpu;
+       ev->header.type        = Measurements::Trap;
+       ev->data.trap.start    = 1;
+       ev->data.trap.trapaddr = vcpu->r()->ip;
+       ev->data.trap.trapno   = vcpu->r()->trapno;
+
 #if MIGRATE_VCPU
        migrated_vCPU_handling(m, i, t, tg, a);
 #elif SPLIT_HANDLING
@@ -511,6 +535,13 @@ void __attribute__((noreturn)) Romain::InstanceManager::VCPU_handler(Romain::Ins
 #error No vCPU handling method selected!
 #endif
 
+       ev = m->logbuf()->next();
+       ev->header.tsc     = Romain::_the_instance_manager->logbuf()->getTime(Log::logLocalTSC);
+       ev->header.vcpu      = (l4_uint32_t)vcpu;
+       ev->header.type      = Measurements::Trap;
+       ev->data.trap.start  = 0;
+       ev->data.trap.trapno = ~0U;
+
        L4::Cap<L4::Thread> self;
        self->vcpu_resume_commit(self->vcpu_resume_start());
 
index 2047e40ac78cd4d687d3a060a3408b8f79ba7284..557d60bbbbe0988336e6968ee6112a27f1b3b347 100644 (file)
@@ -4,7 +4,7 @@
  *
  *     Global locking stuff
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
index 16f9cd4df63c427be604706c277a0f353a3c2342..8c24a7e2014c3c09ab82c03e4d1df272554d7908 100644 (file)
@@ -6,7 +6,7 @@
  *
  *     Logging. Main ideas from http://www.drdobbs.com/cpp/201804215
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
@@ -65,6 +65,8 @@ class Log
                static LogLevel    maxLog;
                static bool        withtime;
                static l4_umword_t logFlags;
+               static bool        logLocalTSC;
+               static bool        replicaLogBuf;
 
                Log() { }
                
diff --git a/l4/pkg/plr/server/src/logging.cc b/l4/pkg/plr/server/src/logging.cc
new file mode 100644 (file)
index 0000000..966e835
--- /dev/null
@@ -0,0 +1,56 @@
+#include "log"
+#include <l4/plr/measurements.h>
+#include <pthread-l4.h>
+#include <l4/util/rdtsc.h>
+#include <l4/sys/debugger.h>
+#include <l4/sys/kdebug.h>
+#include <l4/sys/scheduler>
+#include <l4/re/env>
+#include <l4/re/error_helper>
+
+using L4Re::chksys;
+
+struct timerArgs
+{
+       unsigned cpu;
+       l4_addr_t timer;
+};
+
+
+static timerArgs global_arg;
+
+void *timerThread(void *argp)
+{
+       char const *name = "Romain::timer";
+       L4::Cap<L4::Thread> self(pthread_getl4cap(pthread_self()));
+       l4_debugger_set_object_name(self.cap(), name);
+
+       l4_sched_param_t sp = l4_sched_param(2);
+       sp.affinity = l4_sched_cpu_set(global_arg.cpu, 0);
+       chksys(L4Re::Env::env()->scheduler()->run_thread(self, sp));
+
+       INFO() << "Timer thread. CPU " << global_arg.cpu << ". Timestamp @ 0x" << std::hex << global_arg.timer;
+
+       while (1) {
+               *((volatile l4_uint64_t*)global_arg.timer) = l4_rdtsc();
+       }
+
+       enter_kdebug("timer returned");
+
+       return 0;
+}
+
+void
+Measurements::EventBuf::launchTimerThread(l4_addr_t timer, unsigned CPU)
+{
+       pthread_t tmr;
+
+       global_arg.timer = timer;
+       global_arg.cpu   = CPU;
+
+       int err = pthread_create(&tmr, 0, timerThread, (void*)&global_arg);
+       if (err) {
+               ERROR() << "Error creating timer thread: " << err;
+               enter_kdebug();
+       }
+}
index 6000a535adfa41ad40bf8da2f7aa86b1157ad5fa..255e052df23a35e989188eb38bba263e6c73ef71 100644 (file)
@@ -3,7 +3,7 @@
  * 
  *     Main program entry point.
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
@@ -27,6 +27,8 @@ using L4Re::chkcap;
 Romain::Log::LogLevel Romain::Log::maxLog = Romain::Log::INFO;
 l4_umword_t Romain::Log::logFlags         = Romain::Log::None;
 bool Romain::Log::withtime                = false;
+bool Romain::Log::logLocalTSC             = false;
+bool Romain::Log::replicaLogBuf           = false;
 
 namespace Romain {
        l4re_aux_t* l4re_aux;
@@ -57,6 +59,12 @@ static int _main(int argc, char const **argv)
        (void)argc; (void)argv;
        INFO() << "FILE: " << argv[1];
 
+       sleep(2);
+
+       struct timeval tv;
+       gettimeofday(&tv, NULL);
+       srandom(tv.tv_usec);
+
        setup_aux(argc, argv);
 
        Romain::_the_instance_manager = new Romain::InstanceManager(argc-1, &argv[1]);
index a142c8fd4840248edea8b081862b74fd40f84306..3d28fe31663399eed0d999d6ebed972b8df9c136 100644 (file)
@@ -6,7 +6,7 @@
  *     Definition of the instance manager that knows about all
  *     redundant VCPUs as well as the fault observers.
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
@@ -29,6 +29,7 @@
 #include <cstdio>
 
 #include "redundancy.h"
+#include <l4/plr/measurements.h>
 
 #if SPLIT_HANDLING
 EXTERN_C void *split_handler_fn(void*);
@@ -60,6 +61,8 @@ namespace Romain
                        unsigned     _argc;       // client argc
                        char const **_argv;       // argv of the client
 
+                       Measurements::EventBuf *_logBuf;
+
 #if SPLIT_HANDLING
                        pthread_t _split_handler; // resilient core handler thread
 #endif // SPLIT_HANDLING
@@ -81,6 +84,7 @@ namespace Romain
                        void configure_logflags(char *flags);
                        void configure_fault_observers();
                        void configure_redundancy();
+                       void configure_logbuf(int size);
 
                public:
                        InstanceManager(unsigned argc, char const **argv, unsigned num_instances = 1);
@@ -195,6 +199,9 @@ namespace Romain
 
                        unsigned instance_count() const { return _num_inst; }
 
+                       Measurements::EventBuf* logbuf() { return _logBuf; }
+                       void logdump();
+
                        static void VCPU_handler(Romain::InstanceManager *m, Romain::App_instance *i, Romain::App_thread *t, Romain::Thread_group* tg, Romain::App_model *a);
                        static void VCPU_startup(Romain::InstanceManager *m, Romain::App_instance *i, Romain::App_thread *t, Romain::Thread_group* tg, Romain::App_model *a);
 
index 87fa78efb413d9b37c4fd218580aac3a2b8eb832..58d7746b991c15e623f89943cc2f12096c070eab 100644 (file)
@@ -3,7 +3,7 @@
  *
  *     Instance manager implementation.
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
 #include "configuration"
 
 #include <l4/sys/segment.h>
+#include <l4/re/mem_alloc>
+#include <l4/re/rm>
+#include <l4/re/env>
+#include <l4/re/dataspace>
+#include <l4/re/util/cap_alloc>
+#include <l4/plr/uu.h>
 
 #define MSG() DEBUGf(Romain::Log::Manager)
 #include "fault_handlers/syscalls_factory.h"
 
 Romain::Configuration Romain::globalconfig;
 
+
 L4_INLINE unsigned countbits(long v)
 {
        v = v - ((v >> 1) & 0x55555555);                         // reuse input as temporary
@@ -28,19 +35,21 @@ L4_INLINE unsigned countbits(long v)
        return ((v + ((v >> 4) & 0xF0F0F0F)) * 0x1010101) >> 24; // count
 }
 
+
 L4_INLINE l4_umword_t count_online_cpus()
 {
-       l4_umword_t ret;
-       l4_sched_cpu_set_t set = l4_sched_cpu_set(0, 0);
-       if (l4_error(L4Re::Env::env()->scheduler()->info(&ret, &set)) < 0) {
+       l4_umword_t maxcpu = 0;
+       l4_sched_cpu_set_t cpuonline = l4_sched_cpu_set(0, 0);
+       if (l4_error(L4Re::Env::env()->scheduler()->info(&maxcpu, &cpuonline)) < 0) {
                ERROR() << "reading CPU info";
        }
-       ret = countbits(set.map);
 
-       INFO() << "Found " << ret << " CPUs.";
-       return ret;
+       INFO() << "Online " << countbits(cpuonline.map) << " / MAX " << maxcpu;
+
+       return countbits(cpuonline.map) > maxcpu ? maxcpu : countbits(cpuonline.map);
 }
 
+
 Romain::InstanceManager::InstanceManager(unsigned int argc,
                                          char const **argv,
                                          unsigned num_instances)
@@ -50,7 +59,8 @@ Romain::InstanceManager::InstanceManager(unsigned int argc,
          _num_inst(num_instances),
          _num_cpu(1),
          _argc(argc), // XXX: remove
-         _argv(argv)  // XXX: remove
+         _argv(argv), // XXX: remove
+         _logBuf(0)
 {
        configure();
 
@@ -145,6 +155,7 @@ void Romain::InstanceManager::configure_fault_observers()
        StringObserverConfig("general:debug", this);
        BoolObserverConfig("general:intercept_kip", this, "kip-time");
        BoolObserverConfig("general:swifi", this, "swifi");
+       BoolObserverConfig("general:logreplica", this, "replicalog");
 }
 
 
@@ -165,6 +176,21 @@ void Romain::InstanceManager::configure_redundancy()
        }
 }
 
+
+void Romain::InstanceManager::configure_logbuf(int sizeMB)
+{
+       INFO() << "Log buffer size: " << sizeMB << " MB requested.";
+       unsigned size_in_bytes = sizeMB << 20;
+
+       L4::Cap<L4Re::Dataspace> ds;
+
+       l4_addr_t addr = Romain::Region_map::allocate_and_attach(&ds, size_in_bytes, 0, L4_SUPERPAGESHIFT);
+    INFO() << "Log buffer attached to 0x" << std::hex << addr;
+
+    _logBuf->set_buffer(reinterpret_cast<unsigned char*>(addr), size_in_bytes);
+}
+
+
 /*
  * Romain ini file settings
  * =====================
@@ -204,6 +230,30 @@ void Romain::InstanceManager::configure_redundancy()
  *       - gdb        -> GDB stub logging
  *       - all        -> everything
  *
+ *  logbuf [int] (-1)
+ *       - establish a log buffer with the given size in MB
+ *       - runtime events are logged into this buffer and can later
+ *         be dumped for postprocessing -> this is an alternative to
+ *         printing a lot of stuff to the serial console
+ *
+ *  logcpu [int]
+ *       - event generation needs a global timestamp. On real SMP hardware
+ *         CPUs disagree on their local TSC values. As a workaround, we start
+ *         a dedicated thread that busily writes its local TSC to a global timer
+ *         variable that is then read by everyone else. This of course requires
+ *         the thread to solely run on a dedicated CPU. This option sets the
+ *         respective CPU #.
+ *
+ *  logrdtsc [bool] (false)
+ *       - use local TSC instead of global time stamp counter for event timestamps
+ *         -> use on Qemu where a dedicated timestamp thread does not work properly
+ *
+ *  logreplica [bool] (false)
+ *       - assign each replica a log buffer (mapped to REPLICA_LOG_ADDRESS)
+ *
+ *  replicalogsize [int] (-1)
+ *       - buffser size for the replica-specific log buffer
+ *
  *  swifi [bool] (false)
  *       - Perform fault injection experiments, details are configured
  *         in the [swifi] section.
@@ -272,6 +322,39 @@ void Romain::InstanceManager::configure_redundancy()
  */
 void Romain::InstanceManager::configure()
 {
+#define USE_SHARABLE_TIMESTAMP 1
+
+       int logMB = ConfigIntValue("general:logbuf");
+
+#if USE_SHARABLE_TIMESTAMP
+       _logBuf = new Measurements::EventBuf(true);
+       L4::Cap<L4Re::Dataspace> tsds;
+       l4_addr_t ts_addr = Romain::Region_map::allocate_and_attach(&tsds, L4_PAGESIZE);
+       l4_touch_ro((void*)ts_addr, L4_PAGESIZE);
+       _logBuf->set_tsc_buffer(reinterpret_cast<l4_uint64_t*>(ts_addr));
+#else
+       _logBuf = new Measurements::EventBuf();
+#endif
+       if (logMB != -1) {
+               configure_logbuf(logMB);
+       }
+
+       Log::logLocalTSC = ConfigBoolValue("general:logrdtsc", false);
+
+       /*
+        * These modes are exclusive: either we use the local TSC _xor_ we start a
+        * timer thread on a dedicated CPU.
+        */
+       if (!Log::logLocalTSC) {
+               int logCPU = ConfigIntValue("general:logcpu");
+               if (logCPU != -1) {
+                       INFO() << "Starting counter thread on CPU " << logCPU;
+                       INFO() << "Timestamp @ 0x" << std::hex << (l4_addr_t)_logBuf->timestamp;
+                       Measurements::EventBuf::launchTimerThread((l4_addr_t)_logBuf->timestamp,
+                                                                 logCPU);
+               }
+       }
+
        char *log = strdup(ConfigStringValue("general:log", "none"));
        configure_logflags(log);
        
@@ -283,6 +366,30 @@ void Romain::InstanceManager::configure()
 }
 
 
+void Romain::InstanceManager::logdump()
+{
+       int logMB = ConfigIntValue("general:logbuf");
+       if (logMB != -1) {
+               char const *filename = "sampledump.txt";
+
+               unsigned oldest = _logBuf->oldest();
+               unsigned dump_start, dump_size;
+
+               if (oldest == 0) { // half-full -> dump from 0 to index
+                       dump_start = 0;
+                       dump_size  = _logBuf->index * sizeof(Measurements::GenericEvent);
+               } else { // buffer completely full -> dump full size starting from oldest entry
+                       dump_start = oldest * sizeof(Measurements::GenericEvent);
+                       dump_size  = _logBuf->size * sizeof(Measurements::GenericEvent);
+               }
+
+               uu_dumpz_ringbuffer(filename, _logBuf->buffer,
+                                   _logBuf->size * sizeof(Measurements::GenericEvent),
+                                   dump_start, dump_size);
+       }
+}
+
+
 /*
  * Prepare the stack that is used by the fault handler whenever a
  * VCPU enters the master task.
@@ -340,7 +447,23 @@ Romain::InstanceManager::create_thread(l4_umword_t eip, l4_umword_t esp,
                 */
                if (_num_cpu > 1) {
                        INFO() << instance_id << " " << (instance_id+1) % _num_cpu << " " << _num_cpu;
-                       at->cpu((instance_id + 1) % _num_cpu);
+                       
+                       /* XXX REPLICAS PER CPU XXX */
+                       at->cpu(group->uid % _num_cpu);
+
+                       /* XXX INSTANCES PER CPU XXX */
+                       //at->cpu((instance_id + 1) % _num_cpu);
+
+                       /* XXX OVERLAPPING REPLICAS XXX */
+                       //at->cpu((group->uid + instance_id) % _num_cpu);
+
+                       /* XXX RANDOM PLACEMENT XXX */
+                       //at->cpu(random() % _num_cpu);
+                       
+                       /* XXX Threads assigned RR to CPUs */
+                       //static int threadcount = 1;
+                       //at->cpu(threadcount % _num_cpu);
+                       //threadcount++;
                } else {
                        at->cpu(0);
                }
index 3927f45f3b22af4218d77d169e1e9aff0ad12bc1..d7e47a2a8465c4677fde5ad91ebccbe098fb4c1d 100644 (file)
@@ -5,7 +5,7 @@
  *
  *     Memory management classes, mirroring the L4 RM's ones.
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
@@ -145,13 +145,14 @@ namespace Romain
                        };
 
                private:
-                       l4_cap_idx_t             _cap;
-                       Romain::Region            _local_regions[Romain::MAX_REPLICAS];
-                       l4_addr_t                _offs;
-                       DS                       _mem[Romain::MAX_REPLICAS];
-                       unsigned char            _flags;
-                       RegionWritableType       _row;
-                       bool                     _shared;
+                       l4_cap_idx_t             _cap; // capability of the underlying dataspace
+                       Romain::Region            _local_regions[Romain::MAX_REPLICAS]; // replicated regions (writable regions exist in
+                                                                                           // multiple instances)
+                       l4_addr_t                _offs; // offset in DS
+                       DS                       _mem[Romain::MAX_REPLICAS]; // DS capabilities of underlying dataspaces
+                       unsigned char            _flags; // region flags
+                       RegionWritableType       _row; // rw state
+                       bool                     _shared; // is DS shared across all replicas (true for internal determinism's lock info page)
 
                public:
 
@@ -310,18 +311,12 @@ namespace Romain
                        {
                                if (orig_id == inst_id) return true;
 
-                               L4::Cap<L4Re::Dataspace> mem = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
-                               _check(!mem.is_valid(), "could not allocate ds cap?");
-
+                               L4::Cap<L4Re::Dataspace> mem;
                                unsigned long size = r.local_region(orig_id).size();
-                               int ret = L4Re::Env::env()->mem_alloc()->alloc(size, mem);
-                               _check(ret != 0, "memory allocation failed");
 
-                               l4_addr_t a = 0;
-                               ret = L4Re::Env::env()->rm()->attach(&a, size,
-                                                                    L4Re::Rm::Search_addr,
-                                                                    mem, 0);
-                               _check(ret != 0, "attach failed");
+                               l4_addr_t a = Romain::Region_map::allocate_and_attach(&mem, size);
+                               _check(a == 0, "DS allocation failed");
+
                                memcpy((void*)a, (void*)r.local_region(orig_id).start(), size);
 
                                //DEBUG() << "COPY: DS " << std::hex << mem.cap() << " SIZE " << size
@@ -333,6 +328,37 @@ namespace Romain
                        }
 
 
+                       /*
+                        * Allocate a master-local dataspace object.
+                        */
+                       static void
+                       allocate_ds(L4::Cap<L4Re::Dataspace> *cap, unsigned size)
+                       {
+                               *cap = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
+                               _check(!cap->is_valid(), "error allocating DS capability");
+
+                               int error = L4Re::Env::env()->mem_alloc()->alloc(size, *cap);
+                               _check(error != 0, "error allocating memory");
+                       }
+
+
+                       /*
+                        * Allocate and attach a master-local dataspace object.
+                        */
+                       static l4_addr_t
+                       allocate_and_attach(L4::Cap<L4Re::Dataspace> *cap, unsigned size,
+                                               unsigned offs = 0, unsigned align = L4_PAGESHIFT)
+                       {
+                               Romain::Region_map::allocate_ds(cap, size);
+
+                               l4_addr_t a = 0;
+                               int error = L4Re::Env::env()->rm()->attach(&a, size, L4Re::Rm::Search_addr, *cap, offs, align);
+                               _check(error != 0, "attach failed");
+
+                               return a;
+                       }
+
+
                        /*
                         * Check if a node already has a mapping to one of the replicas. If so,
                         * take a shortcut mapping to the next one (determined by inst parameter).
index 0b689a3ade1cf5ce38dbba89029d51cb2af8d9b0..00ba7913b589fd4fa07a15cda01edf2da9594cf0 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Memory management implementation
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
@@ -173,11 +173,9 @@ void *Romain::Region_map::attach_locally(void* addr, unsigned long size,
         */
        if (!(dsstat.flags & L4Re::Dataspace::Map_rw)) {
                //MSG() << "Copying to rw dataspace.";
-               L4::Cap<L4Re::Dataspace> mem = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
-               _check(!mem.is_valid(), "could not alloc ds cap");
-               //MSG() << "  mem_alloc(" << eff_size << ", " << std::hex << mem.cap() << ")";
-               r = L4Re::Env::env()->mem_alloc()->alloc(eff_size, mem);
-               _check(r != 0, "memory allocation failed");
+               L4::Cap<L4Re::Dataspace> mem;
+
+               Romain::Region_map::allocate_ds(&mem, eff_size);
 
                mem->copy_in(0, *ds, page_base, hdlr->offset() + size);
                ds        = &mem; // taking pointer to stack?? XXX
@@ -219,10 +217,7 @@ void *Romain::Region_map::attach(void* addr, unsigned long size,
        void *ret = 0;
        Romain::Region_handler _handler(hdlr);
 
-       if (shared) {
-               //DEBUG() << "======> SHARED <======";
-               _handler.shared(true);
-       }
+       _handler.shared(shared);
 
        /* Only attach locally, if this hasn't been done beforehand yet. */
        if (!_handler.local_region(_active_instance).start()) {
index 2846744ef8d9e971924c652592f60cf12e8e515e..7eb20cf06725ca24e7f3f610d506a3fc9d12f5d1 100644 (file)
@@ -5,7 +5,7 @@
  *
  *  Interface for handling redundancy comparisons
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
index e6f3755ffdc715e60128a218e5ddc547b3b1e672..1fb02d5d73ace0dc10740b585f515969e677b548 100644 (file)
@@ -3,7 +3,7 @@
  *
  *    n-way modular redundancy implementation 
  *
- * (c) 2011-2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
@@ -14,6 +14,8 @@
 #include "../redundancy.h"
 #include "../app_loading"
 #include "../fault_observers"
+#include "../manager"
+#include "../fault_handlers/syscalls_handler.h"
 
 #define MSG() DEBUGf(Romain::Log::Redundancy)
 #define MSGi(inst) MSG() << "[" << (inst)->id() << "] "
@@ -48,7 +50,7 @@
  */
 
 Romain::DMR::DMR(unsigned instances)
-       : _leave_count(0), _enter_count(0), _block_count(0),
+       : _enter_count(0), _leave_count(0), _block_count(0),
       _rv(Romain::RedundancyCallback::Invalid),
       _num_instances(instances), _num_instances_bak(0)
 {
@@ -116,7 +118,8 @@ Romain::DMR::checksum_replicas()
                                if (_orig_vcpu[cnt])
                                        _orig_vcpu[cnt]->vcpu()->print_state();
                        }
-                       //enter_kdebug("checksum");
+                       ERROR() << "Instances: " << _num_instances << " this inst " << idx;
+                       enter_kdebug("checksum");
 #endif
                        return false;
                }
@@ -131,6 +134,7 @@ class RecoverAbort
                static __attribute__((noreturn)) void recover()
                {
                        ERROR() << "Aborting after error.";
+                       Romain::_the_instance_manager->logdump();
                        enter_kdebug("abort");
                        throw("ERROR -> abort");
                }
index 056659ab369edb71d5648db8a5c362aefb3b169d..8c6397df7f4bc5d4dc5b435aedd63f45bec8e61b 100644 (file)
@@ -5,7 +5,7 @@
  *
  *    Thread group -> representation of a single replicated thread
  *
- * (c) 2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+ * (c) 2012-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
  *     economic rights: Technische Universität Dresden (Germany)
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
@@ -99,8 +99,10 @@ struct GateAgent
 #if USE_IRQ
                gate_irq->trigger();
                l4_umword_t lbl;
-               l4_msgtag_t tag = l4_ipc_wait(l4_utcb(), &lbl, L4_IPC_NEVER);
-               /* XXX IPC error check */
+               l4_ipc_wait(l4_utcb(), &lbl, L4_IPC_NEVER);
+               /* No error check. After return from this call, the UTCB contains
+                * the IPC error the gate agent received, which may in fact be a real
+                * IPC error -> it is up to the app to check and react on it. */
 #endif
 
                DEBUG() << "agent returned.";
@@ -108,7 +110,7 @@ struct GateAgent
 
 
        GateAgent(unsigned cap_idx, Romain::Thread_group *tg)
-               : current_client(0), owner_group(tg)
+               : owner_group(tg), current_client(0)
        {
                DEBUG() << "\033[31;1mGateAgent\033[0m";
                sem_init(&init_sem, 0, 0);
index 3206090281008bd7a68c11318d1f738ebb533ae2..2eb3dd5279187628b5f52c5c256233a69a932b0c 100755 (executable)
@@ -5,6 +5,13 @@
 #    Tool for parsing binaries and finding the relevant instrumentation
 #    points for a fault injection campaign (which is then coordinated by
 #    IGOR).
+#
+# (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+#     economic rights: Technische Universität Dresden (Germany)
+#
+#  This file is part of TUD:OS and distributed under the terms of the
+#  GNU General Public License 2.
+#  Please see the COPYING-GPL-2 file for details.
 
 import sys, os
 import udis86
index 031deef046e2acd957a3763776f1c4868862ca26..1229b8c7d40feee196102bf9f673a373b34b3640 100755 (executable)
@@ -4,6 +4,13 @@
 #
 #    Tool for generating scripts running fault injection experiments
 #    based on Romain running in QEMU
+#
+# (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+#     economic rights: Technische Universität Dresden (Germany)
+#
+#  This file is part of TUD:OS and distributed under the terms of the
+#  GNU General Public License 2.
+#  Please see the COPYING-GPL-2 file for details.
 
 import time
 import os,sys
index a9041204ff62c5af7254b8f6731edf854d5c8904..86d3bd54904ff33d157f809a351708568be5d917 100755 (executable)
@@ -1,6 +1,13 @@
 #!/usr/bin/python
 
 # Timur (*T*est*I*ng *M*achinari*U*m for *R*omain)
+#
+# (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+#     economic rights: Technische Universität Dresden (Germany)
+#
+#  This file is part of TUD:OS and distributed under the terms of the
+#  GNU General Public License 2.
+#  Please see the COPYING-GPL-2 file for details.
 
 import os, sys, sre
 import subprocess       # launching qemu
diff --git a/l4/pkg/plr/tools/tsar/tsar b/l4/pkg/plr/tools/tsar/tsar
new file mode 100755 (executable)
index 0000000..91a82f3
--- /dev/null
@@ -0,0 +1,267 @@
+#!/usr/bin/python
+# -*- coding: iso-8859-1 -*-
+#vi: ft=python
+#
+# TSAR - Trace Sequence AnalyzeR
+#        *     *        *      *
+# Tool to extract and analyze Romain event logs
+#
+# (c) 2012-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
+#     economic rights: Technische Universität Dresden (Germany)
+#
+#  This file is part of TUD:OS and distributed under the terms of the
+#  GNU General Public License 2.
+#  Please see the COPYING-GPL-2 file for details.
+
+import gzip
+import operator
+import os
+import re
+import sys
+import struct
+import tempfile
+import uu
+
+import tsar_events
+
+
+class EventFactory:
+    """Event factory: random access to Event objects
+       based on an underlying trace reader."""
+
+    def __init__(self, traceReader):
+        self.input = traceReader.raw_read()
+        self.offset = 0
+        self.idpfx = traceReader.prefix()
+
+    def uid(self, utcb):
+        return "%s:%x" % (self.idpfx, utcb)
+
+    def reset(self):
+        self.offset = 0
+
+    def _build(self, start):
+        """Get the Event object in the input stream
+           at the given position"""
+
+        if start >= len(self.input):
+            return None
+
+        eventTypes = [
+            None,
+            tsar_events.SyscallEvent,
+            tsar_events.PagefaultEvent,
+            tsar_events.SwifiEvent,
+            tsar_events.FooEvent,
+            tsar_events.TrapEvent,
+            tsar_events.ThreadStartEvent,
+            tsar_events.ThreadStopEvent,
+        ]
+
+        #print "Input: %d bytes" % len(bytes)
+
+        (tsc, utcb, typ) = struct.unpack_from("QIB", self.input[start:])
+
+        try:
+            return eventTypes[typ](self.input[start:], tsc, utcb,
+                                   self.uid(utcb))
+        except IndexError:
+            print "Index error with event type %d" % typ
+            sys.exit(1)
+
+    def nextEvent(self):
+        """Get the next event in stream
+
+        Allows iterating over the stream."""
+        start = self.offset * tsar_events.Event.EVENTSIZE
+        self.offset += 1
+        return self._build(start)
+
+    def eventAtOffset(self, offset):
+        """Get event at a specified offset.
+
+        Random access to the stream."""
+        start = offset * tsar_events.Event.EVENTSIZE
+        return self._build(start)
+
+
+class TraceReader:
+    """Reader for zipped uu-encoded data"""
+
+    def __init__(self, logfile):
+        tmp = tempfile.NamedTemporaryFile(mode="w+b")
+        # XXX also print UID here
+        print "UUDecoding %s -> %s" % (logfile.name, tmp.name)
+        uu.decode(logfile.name, tmp.name)
+        self.zipFile = gzip.open(tmp.name)
+
+        self.pfx = os.path.splitext(os.path.basename(logfile.name))[0]
+
+    def prefix(self):
+        return self.pfx
+
+    def raw_read(self):
+        """Read the raw bytes from the underlying stream
+           into a string."""
+        decomp = ""
+        bytes = self.zipFile.read(1024)
+        while bytes != "":
+            decomp += bytes
+            bytes = self.zipFile.read(1024)
+        print "Read %d bytes." % len(decomp)
+
+        return decomp
+
+
+class EventList:
+    """
+    Raw list of events from potentially multiple event stream sources
+    """
+    def __init__(self):
+        self.streams = []
+        self.stream_index = 0
+
+    def addStream(self, eventFactory):
+        """Add another stream to the event sources"""
+        self.streams += [eventFactory]
+
+    def reset(self):
+        """Reset the event list"""
+        for s in self.streams:
+            s.reset()
+        self.stream_index = 0
+
+    def next(self):
+        """Return the next event.
+
+        Continuously calling this function iterates over the associated
+        streams one at a time. Returns 'None' if no more events are to
+        be found
+        """
+
+        if self.stream_index >= len(self.streams):
+            return None
+
+        ev = self.streams[self.stream_index].nextEvent()
+
+        if ev is None:
+            self.stream_index += 1
+            return self.next()
+
+        return ev
+
+
+def print_plain(events):
+    """Plain dump of an event list"""
+    for e in events:
+        print e
+
+
+def print_pretty(events):
+    """Pretty-printed event list.
+
+    Prints a table. First column is a time stamp. Every other
+    colunm represents one distinct replica
+    """
+    ids = []
+
+    # first run to determine UTCB IDs
+    for e in events:
+        if e.uid() not in ids:
+            ids += [e.uid()]
+    ids.sort()
+
+    # header
+    print "\033[32m%14s" % "Timestamp",
+    for i in ids:
+        print "| %20s" % ("UID %s" % i[0:16]),
+    print "\033[0m"
+
+    # printing run
+    for e in events:
+        first = True
+        for line in e.pretty():
+            if first:
+                print "%14s" % e.ts,
+                first = False
+            else:
+                print " " * 14,
+
+            idx = ids.index(e.uid())
+
+            for i in range(0, idx):
+                print "|",
+                print " " * 20,
+            if e.type == tsar_events.Event.TRAP_TYPE and e.is_start:
+                print "| \033[33m%20s\033[0m" % line,
+            else:
+                print "| %20s" % line,
+            for i in range(idx + 1, len(ids)):
+                print "|",
+                print " " * 20,
+            print
+
+
+def remove_vt100(line):
+    """Remoe any occurrence of a VT100 color sequence from a string"""
+    return re.sub("\033\[\d+(;\d+)?m", "", line)
+
+
+def extractLogs(inputFile):
+    """Take a QEMU log file (Fiasco serial output) and extract the
+       UU-encoded trace dumps from it.
+    """
+    files = []         # list of trace files
+    inLogFile = False  # are we currently operating on a dump?
+
+    for l in file(inputFile).readlines():
+        v = remove_vt100(l)
+
+        # start and end indicators
+        startmo = re.match("romain.*(begin 644 .*.gz)", v)
+        endmo = re.match("romain.*end", v)
+
+        if startmo:
+            curFile = tempfile.NamedTemporaryFile(mode="w+")
+            inLogFile = True
+
+        # Write lines belonging to the dump to temporary file.
+        # Remove L4Re's log prefix upfront
+        if inLogFile:
+            curFile.write(v.replace("romain  | ", ""))
+
+        if inLogFile and endmo:
+            files += [curFile]
+            inLogFile = False
+
+    return files
+
+
+def main():
+    if len(sys.argv) < 2:
+        print "Need at least 1 argument"
+        sys.exit(1)
+
+    elist = EventList()
+
+    for f in extractLogs(sys.argv[1]):
+        print "=== %s ===" % f.name
+        f.seek(0)  # need to reset file seek ptr
+        elist.addStream(EventFactory(TraceReader(f)))
+
+    events = []
+
+    e = elist.next()
+    while e is not None:
+        events += [e]
+        e = elist.next()
+
+    # events are not necessarily sorted by time right now!
+    events.sort(key=operator.attrgetter('ts'))
+
+    #print_plain(events)
+    print_pretty(events)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/l4/pkg/plr/tools/tsar/tsar_events.py b/l4/pkg/plr/tools/tsar/tsar_events.py
new file mode 100644 (file)
index 0000000..b1516a1
--- /dev/null
@@ -0,0 +1,162 @@
+#!/usr/bin/python
+
+import struct
+
+class Event:
+    """Event base class"""
+
+    HEADSIZE = 13
+    EVENTSIZE = 32
+
+    SYSCALL_TYPE = 1
+    PAGEFAULT_TYPE = 2
+    SWIFI_TYPE = 3
+    FOO_TYPE = 4
+    TRAP_TYPE = 5
+    THREAD_START_TYPE = 6
+    THREAD_STOP_TYPE = 7
+
+    @staticmethod
+    def eventName(ev):
+        """Get name for event type"""
+        syscall_names = ["INV", "SYS", "PF",
+                         "SWIFI", "FOO", "TRAP",
+                         "START", "STOP"]
+        return syscall_names[ev]
+
+    def __init__(self, time=0, typ=0, utcb=0, uid=None):
+        self.ts = time
+        self.type = typ
+        self.utcb = utcb
+        if uid is None:
+               self.id = self.utcb
+        else:
+               self.id = uid
+
+    def uid(self):
+       return self.id
+
+    def __repr__(self):
+        return "%d [%8x|%5s]" % (self.ts, self.utcb,
+                                 Event.eventName(self.type))
+
+
+class SyscallEvent(Event):
+    def __init__(self, raw, time=0, utcb=0, uid=None):
+        Event.__init__(self, time, Event.SYSCALL_TYPE, utcb, uid)
+        (self.ip, self.label, ) = struct.unpack_from("II",
+                                                     raw[Event.HEADSIZE:])
+
+    def __repr__(self):
+        return Event.__repr__(self) + " SYSCALL %08x, ret to %08x" % \
+            (self.label, self.ip)
+
+    def pretty(self, cols=20):
+        return ["SYSCALL %08x" % (self.label),
+                " ret -> %08x" % (self.ip)]
+
+
+class PagefaultEvent(Event):
+    def __init__(self, raw, time=0, utcb=0, uid=None):
+        Event.__init__(self, time, Event.PAGEFAULT_TYPE, utcb, uid)
+        (self.writepf, ) = struct.unpack_from("B", raw[Event.HEADSIZE:])
+        (self.pfa,
+         self.local,
+         self.remote) = struct.unpack_from("III", raw[Event.HEADSIZE + 1:])
+        #print hex(self.pfa)
+
+    def __repr__(self):
+        r = Event.__repr__(self)
+        if (self.writepf):
+            r += " w"
+        r += "r pf @ %08x -> %08x" % (self.local, self.remote)
+        return r
+
+    def pretty(self, cols=20):
+        r = []
+        if self.writepf:
+            r += ["wr pf @ 0x%x" % self.pfa]
+        else:
+            r += ["r pf @ 0x%x" % self.pfa]
+        r += ["%x -> %x" % (self.local, self.remote)]
+        return r
+
+
+class SwifiEvent(Event):
+    def __init__(self, raw, time=0, utcb=0, uid=None):
+        Event.__init__(self, time, Event.SWIFI_TYPE, utcb, uid)
+
+    def pretty(self, cols=20):
+        return ["SWIFI"]
+
+
+class FooEvent(Event):
+    def __init__(self, raw, time=0, utcb=0, uid=None):
+        Event.__init__(self, time, Event.FOO_TYPE, utcb, uid)
+        (self.is_start, ) = struct.unpack_from("I", raw[Event.HEADSIZE:])
+
+    def __repr__(self):
+        r = Event.__repr__(self)
+        if self.is_start == 0:
+            r += " STOP"
+        else:
+            r += " START"
+        return r
+
+    def pretty(self, cols=20):
+        return ["FOO"]
+
+
+class TrapEvent(Event):
+
+    counters = {}
+
+    def __init__(self, raw, time=0, utcb=0, uid=None):
+        Event.__init__(self, time, Event.TRAP_TYPE, utcb, uid)
+        (self.is_start, ) = struct.unpack_from("B", raw[Event.HEADSIZE:])
+        (self.trapaddr, self.trapno, ) = \
+            struct.unpack_from("II", raw[Event.HEADSIZE + 1:])
+
+        #print "S %d T %d" % (self.is_start, self.trapno)
+
+    def __repr__(self):
+        r = Event.__repr__(self)
+        if self.is_start == 1:
+            r += " start, trapno %x" % self.trapno
+        else:
+            r += " done"
+        return r
+
+    def pretty(self, cols=20):
+        if self.is_start:
+            return ["TRAP %x @ %08x" % (self.trapno, self.trapaddr)]
+        else:
+            return ["--- TRAP END ---"]
+
+
+class ThreadStartEvent(Event):
+
+    def __init__(self, raw, time=0, utcb=0, uid=None):
+        Event.__init__(self, time, Event.THREAD_START_TYPE, utcb, uid)
+
+    def __repr__(self):
+        r = Event.__repr__(self)
+        r += "Thread::Start"
+        return r
+
+    def pretty(self, cols=20):
+        return ["Thread::Start"]
+
+
+class ThreadStopEvent(Event):
+
+    def __init__(self, raw, time=0, utcb=0, uid=None):
+        Event.__init__(self, time, Event.THREAD_STOP_TYPE, utcb, uid)
+
+    def __repr__(self):
+        r = Event.__repr__(self)
+        r += "Thread::Exit"
+        return r
+
+    def pretty(self, cols=20):
+        return ["Thread::Exit"]
index 1cdcb1963e77deceeec4026ba1fed281e5c7085c..f501ec17e3896b20255428caf994fa6a8453d568 100644 (file)
@@ -147,7 +147,7 @@ Serial_drv::init()
   printf("serial-drv: virtual base at:%lx\n", virt_base);
 
   L4::Io_register_block_mmio *regs = new L4::Io_register_block_mmio(virt_base);
-  _uart = new (malloc(sizeof(L4::Uart_pl011))) L4::Uart_pl011;
+  _uart = new (malloc(sizeof(L4::Uart_pl011))) L4::Uart_pl011(24019200);
   //_uart = new (malloc(sizeof(L4::Uart_omap35x))) L4::Uart_omap35x;
   _uart->startup(regs);
 
index f3ce39305f1cbb492195e891ebdfbc96a7278c27..d6aee51d8e4faabbd9888190e525299b5d5951e1 100644 (file)
@@ -1,4 +1,7 @@
 
 
-The contrib directory contains the unmodified contents of
-sqlite-autoconf-3071401.tar.gz
+The contrib directory contains the nearly unmodified contents of
+sqlite-autoconf-3071500.tar.gz
+
+The current change is to undef HAVE_POSIX_FALLOCATE in case of uclibc
+because uclibc does not have it.
index 3931d834b4b243e91eb326a4d50275310b274681..6fc4f33c0e5a7331107ead6d6b6a110b467dccd7 100644 (file)
@@ -12,7 +12,7 @@ sqlite3_DEPENDENCIES = $(top_builddir)/libsqlite3.la
 
 include_HEADERS = sqlite3.h sqlite3ext.h
 
-EXTRA_DIST = sqlite3.pc sqlite3.1 tea
+EXTRA_DIST = sqlite3.1 tea
 pkgconfigdir = ${libdir}/pkgconfig
 pkgconfig_DATA = sqlite3.pc
 
index d4f1386f37922de5f641db03306ab76b66fc0f7c..e74bc0138d80264715bbde6f7b1d71980826f60e 100644 (file)
@@ -1,9 +1,8 @@
-# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
-# Inc.
+# 2003, 2004, 2005  Free Software Foundation, Inc.
 # This Makefile.in is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
 
 
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
 VPATH = @srcdir@
 pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
 pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = .
 am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
 install_sh_DATA = $(install_sh) -c -m 644
 install_sh_PROGRAM = $(install_sh) -c
 install_sh_SCRIPT = $(install_sh) -c
@@ -38,73 +40,56 @@ POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
 bin_PROGRAMS = sqlite3$(EXEEXT)
-subdir = .
 DIST_COMMON = README $(am__configure_deps) $(include_HEADERS) \
        $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
        $(srcdir)/sqlite3.pc.in $(top_srcdir)/configure INSTALL \
        config.guess config.sub depcomp install-sh ltmain.sh missing
+subdir = .
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
        $(ACLOCAL_M4)
 am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
- configure.lineno config.status.lineno
+ configure.lineno configure.status.lineno
 mkinstalldirs = $(install_sh) -d
 CONFIG_CLEAN_FILES = sqlite3.pc
-CONFIG_CLEAN_VPATH_FILES =
 am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
 am__vpath_adj = case $$p in \
     $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
     *) f=$$p;; \
   esac;
-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
-am__install_max = 40
-am__nobase_strip_setup = \
-  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
-am__nobase_strip = \
-  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
-am__nobase_list = $(am__nobase_strip_setup); \
-  for p in $$list; do echo "$$p $$p"; done | \
-  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
-  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
-    if (++n[$$2] == $(am__install_max)) \
-      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
-    END { for (dir in files) print dir, files[dir] }'
-am__base_list = \
-  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
-  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
 am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \
        "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(pkgconfigdir)" \
        "$(DESTDIR)$(includedir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
 LTLIBRARIES = $(lib_LTLIBRARIES)
 libsqlite3_la_LIBADD =
 am_libsqlite3_la_OBJECTS = sqlite3.lo
 libsqlite3_la_OBJECTS = $(am_libsqlite3_la_OBJECTS)
-libsqlite3_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-       $(libsqlite3_la_LDFLAGS) $(LDFLAGS) -o $@
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
 PROGRAMS = $(bin_PROGRAMS)
 am_sqlite3_OBJECTS = shell.$(OBJEXT)
 sqlite3_OBJECTS = $(am_sqlite3_OBJECTS)
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I. -I$(srcdir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__depfiles_maybe = depfiles
-am__mv = mv -f
 COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
        $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
-       --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
-       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+       $(AM_CFLAGS) $(CFLAGS)
 CCLD = $(CC)
-LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
-       --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
-       $(LDFLAGS) -o $@
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(AM_LDFLAGS) $(LDFLAGS) -o $@
 SOURCES = $(libsqlite3_la_SOURCES) $(sqlite3_SOURCES)
 DIST_SOURCES = $(libsqlite3_la_SOURCES) $(sqlite3_SOURCES)
 man1dir = $(mandir)/man1
 NROFF = nroff
 MANS = $(man_MANS)
+pkgconfigDATA_INSTALL = $(INSTALL_DATA)
 DATA = $(pkgconfig_DATA)
+includeHEADERS_INSTALL = $(INSTALL_HEADER)
 HEADERS = $(include_HEADERS)
 ETAGS = etags
 CTAGS = ctags
@@ -112,14 +97,16 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 distdir = $(PACKAGE)-$(VERSION)
 top_distdir = $(distdir)
 am__remove_distdir = \
-  { test ! -d "$(distdir)" \
-    || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
-         && rm -fr "$(distdir)"; }; }
+  { test ! -d $(distdir) \
+    || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+         && rm -fr $(distdir); }; }
 DIST_ARCHIVES = $(distdir).tar.gz
 GZIP_ENV = --best
 distuninstallcheck_listfiles = find . -type f -print
 distcleancheck_listfiles = find . -type f -print
 ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
 AMTAR = @AMTAR@
 AR = @AR@
 AUTOCONF = @AUTOCONF@
@@ -132,62 +119,57 @@ CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
 DYNAMIC_EXTENSION_FLAGS = @DYNAMIC_EXTENSION_FLAGS@
+ECHO = @ECHO@
 ECHO_C = @ECHO_C@
 ECHO_N = @ECHO_N@
 ECHO_T = @ECHO_T@
 EGREP = @EGREP@
 EXEEXT = @EXEEXT@
-FGREP = @FGREP@
+F77 = @F77@
+FFLAGS = @FFLAGS@
 GREP = @GREP@
-INSTALL = @INSTALL@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LD = @LD@
 LDFLAGS = @LDFLAGS@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
 LN_S = @LN_S@
 LTLIBOBJS = @LTLIBOBJS@
 MAKEINFO = @MAKEINFO@
 MKDIR_P = @MKDIR_P@
-NM = @NM@
-NMEDIT = @NMEDIT@
-OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
 PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
 PACKAGE_NAME = @PACKAGE_NAME@
 PACKAGE_STRING = @PACKAGE_STRING@
 PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
 RANLIB = @RANLIB@
 READLINE_LIBS = @READLINE_LIBS@
-SED = @SED@
 SET_MAKE = @SET_MAKE@
 SHELL = @SHELL@
 STRIP = @STRIP@
 THREADSAFE_FLAGS = @THREADSAFE_FLAGS@
 VERSION = @VERSION@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
 ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
 am__include = @am__include@
 am__leading_dot = @am__leading_dot@
 am__quote = @am__quote@
@@ -199,7 +181,6 @@ build_alias = @build_alias@
 build_cpu = @build_cpu@
 build_os = @build_os@
 build_vendor = @build_vendor@
-builddir = @builddir@
 datadir = @datadir@
 datarootdir = @datarootdir@
 docdir = @docdir@
@@ -218,7 +199,6 @@ libdir = @libdir@
 libexecdir = @libexecdir@
 localedir = @localedir@
 localstatedir = @localstatedir@
-lt_ECHO = @lt_ECHO@
 mandir = @mandir@
 mkdir_p = @mkdir_p@
 oldincludedir = @oldincludedir@
@@ -228,12 +208,8 @@ program_transform_name = @program_transform_name@
 psdir = @psdir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
 sysconfdir = @sysconfdir@
 target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
 AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE
 lib_LTLIBRARIES = libsqlite3.la
 libsqlite3_la_SOURCES = sqlite3.c
@@ -242,7 +218,7 @@ sqlite3_SOURCES = shell.c sqlite3.h
 sqlite3_LDADD = $(top_builddir)/libsqlite3.la @READLINE_LIBS@
 sqlite3_DEPENDENCIES = $(top_builddir)/libsqlite3.la
 include_HEADERS = sqlite3.h sqlite3ext.h
-EXTRA_DIST = sqlite3.pc sqlite3.1 tea
+EXTRA_DIST = sqlite3.1 tea
 pkgconfigdir = ${libdir}/pkgconfig
 pkgconfig_DATA = sqlite3.pc
 man_MANS = sqlite3.1
@@ -256,15 +232,15 @@ $(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
        @for dep in $?; do \
          case '$(am__configure_deps)' in \
            *$$dep*) \
-             echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
-             $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
+             echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \
+             cd $(srcdir) && $(AUTOMAKE) --foreign  \
                && exit 0; \
              exit 1;; \
          esac; \
        done; \
-       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
-       $(am__cd) $(top_srcdir) && \
-         $(AUTOMAKE) --foreign Makefile
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  Makefile
 .PRECIOUS: Makefile
 Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
        @case '$?' in \
@@ -280,33 +256,28 @@ $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENC
        $(SHELL) ./config.status --recheck
 
 $(top_srcdir)/configure:  $(am__configure_deps)
-       $(am__cd) $(srcdir) && $(AUTOCONF)
+       cd $(srcdir) && $(AUTOCONF)
 $(ACLOCAL_M4):  $(am__aclocal_m4_deps)
-       $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
-$(am__aclocal_m4_deps):
+       cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
 sqlite3.pc: $(top_builddir)/config.status $(srcdir)/sqlite3.pc.in
        cd $(top_builddir) && $(SHELL) ./config.status $@
 install-libLTLIBRARIES: $(lib_LTLIBRARIES)
        @$(NORMAL_INSTALL)
-       test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
-       @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
-       list2=; for p in $$list; do \
+       test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
+       @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
          if test -f $$p; then \
-           list2="$$list2 $$p"; \
+           f=$(am__strip_dir) \
+           echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+           $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
          else :; fi; \
-       done; \
-       test -z "$$list2" || { \
-         echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
-         $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
-       }
+       done
 
 uninstall-libLTLIBRARIES:
        @$(NORMAL_UNINSTALL)
-       @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
-       for p in $$list; do \
-         $(am__strip_dir) \
-         echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
-         $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+       @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+         p=$(am__strip_dir) \
+         echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+         $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
        done
 
 clean-libLTLIBRARIES:
@@ -318,53 +289,38 @@ clean-libLTLIBRARIES:
          rm -f "$${dir}/so_locations"; \
        done
 libsqlite3.la: $(libsqlite3_la_OBJECTS) $(libsqlite3_la_DEPENDENCIES) 
-       $(libsqlite3_la_LINK) -rpath $(libdir) $(libsqlite3_la_OBJECTS) $(libsqlite3_la_LIBADD) $(LIBS)
+       $(LINK) -rpath $(libdir) $(libsqlite3_la_LDFLAGS) $(libsqlite3_la_OBJECTS) $(libsqlite3_la_LIBADD) $(LIBS)
 install-binPROGRAMS: $(bin_PROGRAMS)
        @$(NORMAL_INSTALL)
-       test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
-       @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
-       for p in $$list; do echo "$$p $$p"; done | \
-       sed 's/$(EXEEXT)$$//' | \
-       while read p p1; do if test -f $$p || test -f $$p1; \
-         then echo "$$p"; echo "$$p"; else :; fi; \
-       done | \
-       sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
-           -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
-       sed 'N;N;N;s,\n, ,g' | \
-       $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
-         { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
-           if ($$2 == $$4) files[d] = files[d] " " $$1; \
-           else { print "f", $$3 "/" $$4, $$1; } } \
-         END { for (d in files) print "f", d, files[d] }' | \
-       while read type dir files; do \
-           if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
-           test -z "$$files" || { \
-           echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
-           $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
-           } \
-       ; done
+       test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+         if test -f $$p \
+            || test -f $$p1 \
+         ; then \
+           f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+          echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+          $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+         else :; fi; \
+       done
 
 uninstall-binPROGRAMS:
        @$(NORMAL_UNINSTALL)
-       @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
-       files=`for p in $$list; do echo "$$p"; done | \
-         sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
-             -e 's/$$/$(EXEEXT)/' `; \
-       test -n "$$list" || exit 0; \
-       echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
-       cd "$(DESTDIR)$(bindir)" && rm -f $$files
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+         echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+         rm -f "$(DESTDIR)$(bindir)/$$f"; \
+       done
 
 clean-binPROGRAMS:
-       @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
-       echo " rm -f" $$list; \
-       rm -f $$list || exit $$?; \
-       test -n "$(EXEEXT)" || exit 0; \
-       list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
-       echo " rm -f" $$list; \
-       rm -f $$list
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+         echo " rm -f $$p $$f"; \
+         rm -f $$p $$f ; \
+       done
 sqlite3$(EXEEXT): $(sqlite3_OBJECTS) $(sqlite3_DEPENDENCIES) 
        @rm -f sqlite3$(EXEEXT)
-       $(LINK) $(sqlite3_OBJECTS) $(sqlite3_LDADD) $(LIBS)
+       $(LINK) $(sqlite3_LDFLAGS) $(sqlite3_OBJECTS) $(sqlite3_LDADD) $(LIBS)
 
 mostlyclean-compile:
        -rm -f *.$(OBJEXT)
@@ -376,22 +332,22 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sqlite3.Plo@am__quote@
 
 .c.o:
-@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@   if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@   then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(COMPILE) -c $<
 
 .c.obj:
-@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@   if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@   then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(COMPILE) -c `$(CYGPATH_W) '$<'`
 
 .c.lo:
-@am__fastdepCC_TRUE@   $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_TRUE@   if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@   then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(LTCOMPILE) -c -o $@ $<
@@ -403,190 +359,171 @@ clean-libtool:
        -rm -rf .libs _libs
 
 distclean-libtool:
-       -rm -f libtool config.lt
-install-man1: $(man_MANS)
+       -rm -f libtool
+uninstall-info-am:
+install-man1: $(man1_MANS) $(man_MANS)
        @$(NORMAL_INSTALL)
-       test -z "$(man1dir)" || $(MKDIR_P) "$(DESTDIR)$(man1dir)"
-       @list=''; test -n "$(man1dir)" || exit 0; \
-       { for i in $$list; do echo "$$i"; done; \
-       l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
-         sed -n '/\.1[a-z]*$$/p'; \
-       } | while read p; do \
-         if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
-         echo "$$d$$p"; echo "$$p"; \
-       done | \
-       sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
-             -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
-       sed 'N;N;s,\n, ,g' | { \
-       list=; while read file base inst; do \
-         if test "$$base" = "$$inst"; then list="$$list $$file"; else \
-           echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
-           $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
-         fi; \
+       test -z "$(man1dir)" || $(mkdir_p) "$(DESTDIR)$(man1dir)"
+       @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
+       l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+       for i in $$l2; do \
+         case "$$i" in \
+           *.1*) list="$$list $$i" ;; \
+         esac; \
        done; \
-       for i in $$list; do echo "$$i"; done | $(am__base_list) | \
-       while read files; do \
-         test -z "$$files" || { \
-           echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
-           $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
-       done; }
-
+       for i in $$list; do \
+         if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+         else file=$$i; fi; \
+         ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+         case "$$ext" in \
+           1*) ;; \
+           *) ext='1' ;; \
+         esac; \
+         inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+         inst=`echo $$inst | sed -e 's/^.*\///'`; \
+         inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+         echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
+         $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst"; \
+       done
 uninstall-man1:
        @$(NORMAL_UNINSTALL)
-       @list=''; test -n "$(man1dir)" || exit 0; \
-       files=`{ for i in $$list; do echo "$$i"; done; \
-       l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
-         sed -n '/\.1[a-z]*$$/p'; \
-       } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
-             -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
-       test -z "$$files" || { \
-         echo " ( cd '$(DESTDIR)$(man1dir)' && rm -f" $$files ")"; \
-         cd "$(DESTDIR)$(man1dir)" && rm -f $$files; }
+       @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
+       l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+       for i in $$l2; do \
+         case "$$i" in \
+           *.1*) list="$$list $$i" ;; \
+         esac; \
+       done; \
+       for i in $$list; do \
+         ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+         case "$$ext" in \
+           1*) ;; \
+           *) ext='1' ;; \
+         esac; \
+         inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+         inst=`echo $$inst | sed -e 's/^.*\///'`; \
+         inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+         echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \
+         rm -f "$(DESTDIR)$(man1dir)/$$inst"; \
+       done
 install-pkgconfigDATA: $(pkgconfig_DATA)
        @$(NORMAL_INSTALL)
-       test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)"
-       @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
-       for p in $$list; do \
+       test -z "$(pkgconfigdir)" || $(mkdir_p) "$(DESTDIR)$(pkgconfigdir)"
+       @list='$(pkgconfig_DATA)'; for p in $$list; do \
          if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
-         echo "$$d$$p"; \
-       done | $(am__base_list) | \
-       while read files; do \
-         echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \
-         $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \
+         f=$(am__strip_dir) \
+         echo " $(pkgconfigDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
+         $(pkgconfigDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgconfigdir)/$$f"; \
        done
 
 uninstall-pkgconfigDATA:
        @$(NORMAL_UNINSTALL)
-       @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
-       files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
-       test -n "$$files" || exit 0; \
-       echo " ( cd '$(DESTDIR)$(pkgconfigdir)' && rm -f" $$files ")"; \
-       cd "$(DESTDIR)$(pkgconfigdir)" && rm -f $$files
+       @list='$(pkgconfig_DATA)'; for p in $$list; do \
+         f=$(am__strip_dir) \
+         echo " rm -f '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
+         rm -f "$(DESTDIR)$(pkgconfigdir)/$$f"; \
+       done
 install-includeHEADERS: $(include_HEADERS)
        @$(NORMAL_INSTALL)
-       test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
-       @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
-       for p in $$list; do \
+       test -z "$(includedir)" || $(mkdir_p) "$(DESTDIR)$(includedir)"
+       @list='$(include_HEADERS)'; for p in $$list; do \
          if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
-         echo "$$d$$p"; \
-       done | $(am__base_list) | \
-       while read files; do \
-         echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \
-         $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \
+         f=$(am__strip_dir) \
+         echo " $(includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \
+         $(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \
        done
 
 uninstall-includeHEADERS:
        @$(NORMAL_UNINSTALL)
-       @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
-       files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
-       test -n "$$files" || exit 0; \
-       echo " ( cd '$(DESTDIR)$(includedir)' && rm -f" $$files ")"; \
-       cd "$(DESTDIR)$(includedir)" && rm -f $$files
+       @list='$(include_HEADERS)'; for p in $$list; do \
+         f=$(am__strip_dir) \
+         echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \
+         rm -f "$(DESTDIR)$(includedir)/$$f"; \
+       done
 
 ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
        list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
        unique=`for i in $$list; do \
            if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
          done | \
-         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-             END { if (nonempty) { for (i in files) print i; }; }'`; \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
        mkid -fID $$unique
 tags: TAGS
 
 TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
                $(TAGS_FILES) $(LISP)
-       set x; \
+       tags=; \
        here=`pwd`; \
        list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
        unique=`for i in $$list; do \
            if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
          done | \
-         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-             END { if (nonempty) { for (i in files) print i; }; }'`; \
-       shift; \
-       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
          test -n "$$unique" || unique=$$empty_fix; \
-         if test $$# -gt 0; then \
-           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-             "$$@" $$unique; \
-         else \
-           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-             $$unique; \
-         fi; \
+         $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+           $$tags $$unique; \
        fi
 ctags: CTAGS
 CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
                $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
        list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
        unique=`for i in $$list; do \
            if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
          done | \
-         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-             END { if (nonempty) { for (i in files) print i; }; }'`; \
-       test -z "$(CTAGS_ARGS)$$unique" \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(CTAGS_ARGS)$$tags$$unique" \
          || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-            $$unique
+            $$tags $$unique
 
 GTAGS:
        here=`$(am__cd) $(top_builddir) && pwd` \
-         && $(am__cd) $(top_srcdir) \
-         && gtags -i $(GTAGS_ARGS) "$$here"
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
 
 distclean-tags:
        -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
 
 distdir: $(DISTFILES)
-       @list='$(MANS)'; if test -n "$$list"; then \
-         list=`for p in $$list; do \
-           if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
-           if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
-         if test -n "$$list" && \
-           grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
-           echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \
-           grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/         /' >&2; \
-           echo "       to fix them, install help2man, remove and regenerate the man pages;" >&2; \
-           echo "       typically \`make maintainer-clean' will remove them" >&2; \
-           exit 1; \
-         else :; fi; \
-       else :; fi
        $(am__remove_distdir)
-       test -d "$(distdir)" || mkdir "$(distdir)"
-       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       list='$(DISTFILES)'; \
-         dist_files=`for file in $$list; do echo $$file; done | \
-         sed -e "s|^$$srcdirstrip/||;t" \
-             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
-       case $$dist_files in \
-         */*) $(MKDIR_P) `echo "$$dist_files" | \
-                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
-                          sort -u` ;; \
-       esac; \
-       for file in $$dist_files; do \
+       mkdir $(distdir)
+       $(mkdir_p) $(distdir)/.
+       @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+       list='$(DISTFILES)'; for file in $$list; do \
+         case $$file in \
+           $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+           $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+         esac; \
          if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+         if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+           dir="/$$dir"; \
+           $(mkdir_p) "$(distdir)$$dir"; \
+         else \
+           dir=''; \
+         fi; \
          if test -d $$d/$$file; then \
-           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
-           if test -d "$(distdir)/$$file"; then \
-             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-           fi; \
            if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
            fi; \
-           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
          else \
-           test -f "$(distdir)/$$file" \
-           || cp -p $$d/$$file "$(distdir)/$$file" \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
            || exit 1; \
          fi; \
        done
-       -test -n "$(am__skip_mode_fix)" \
-       || find "$(distdir)" -type d ! -perm -755 \
-               -exec chmod u+rwx,go+rx {} \; -o \
+       -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
          ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
          ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
-         ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
-       || chmod -R a+r "$(distdir)"
+         ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \
+       || chmod -R a+r $(distdir)
 dist-gzip: distdir
        tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
        $(am__remove_distdir)
@@ -595,14 +532,6 @@ dist-bzip2: distdir
        tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
        $(am__remove_distdir)
 
-dist-lzma: distdir
-       tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
-       $(am__remove_distdir)
-
-dist-xz: distdir
-       tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz
-       $(am__remove_distdir)
-
 dist-tarZ: distdir
        tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
        $(am__remove_distdir)
@@ -626,17 +555,13 @@ dist dist-all: distdir
 distcheck: dist
        case '$(DIST_ARCHIVES)' in \
        *.tar.gz*) \
-         GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
+         GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
        *.tar.bz2*) \
-         bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
-       *.tar.lzma*) \
-         lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\
-       *.tar.xz*) \
-         xz -dc $(distdir).tar.xz | $(am__untar) ;;\
+         bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
        *.tar.Z*) \
          uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
        *.shar.gz*) \
-         GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
+         GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
        *.zip*) \
          unzip $(distdir).zip ;;\
        esac
@@ -644,11 +569,9 @@ distcheck: dist
        mkdir $(distdir)/_build
        mkdir $(distdir)/_inst
        chmod a-w $(distdir)
-       test -d $(distdir)/_build || exit 0; \
        dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
          && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
-         && am__cwd=`pwd` \
-         && $(am__cd) $(distdir)/_build \
+         && cd $(distdir)/_build \
          && ../configure --srcdir=.. --prefix="$$dc_install_base" \
            $(DISTCHECK_CONFIGURE_FLAGS) \
          && $(MAKE) $(AM_MAKEFLAGS) \
@@ -670,15 +593,13 @@ distcheck: dist
          && rm -rf "$$dc_destdir" \
          && $(MAKE) $(AM_MAKEFLAGS) dist \
          && rm -rf $(DIST_ARCHIVES) \
-         && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
-         && cd "$$am__cwd" \
-         || exit 1
+         && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
        $(am__remove_distdir)
        @(echo "$(distdir) archives ready for distribution: "; \
          list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
-         sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+         sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}'
 distuninstallcheck:
-       @$(am__cd) '$(distuninstallcheck_dir)' \
+       @cd $(distuninstallcheck_dir) \
        && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
           || { echo "ERROR: files left after uninstall:" ; \
                if test -n "$(DESTDIR)"; then \
@@ -702,7 +623,7 @@ install-binPROGRAMS: install-libLTLIBRARIES
 
 installdirs:
        for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(includedir)"; do \
-         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+         test -z "$$dir" || $(mkdir_p) "$$dir"; \
        done
 install: install-am
 install-exec: install-exec-am
@@ -724,7 +645,6 @@ clean-generic:
 
 distclean-generic:
        -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
 
 maintainer-clean-generic:
        @echo "This command is intended for maintainers to use"
@@ -747,8 +667,6 @@ dvi-am:
 
 html: html-am
 
-html-am:
-
 info: info-am
 
 info-am:
@@ -756,30 +674,12 @@ info-am:
 install-data-am: install-includeHEADERS install-man \
        install-pkgconfigDATA
 
-install-dvi: install-dvi-am
-
-install-dvi-am:
-
 install-exec-am: install-binPROGRAMS install-libLTLIBRARIES
 
-install-html: install-html-am
-
-install-html-am:
-
 install-info: install-info-am
 
-install-info-am:
-
 install-man: install-man1
 
-install-pdf: install-pdf-am
-
-install-pdf-am:
-
-install-ps: install-ps-am
-
-install-ps-am:
-
 installcheck-am:
 
 maintainer-clean: maintainer-clean-am
@@ -803,34 +703,30 @@ ps: ps-am
 ps-am:
 
 uninstall-am: uninstall-binPROGRAMS uninstall-includeHEADERS \
-       uninstall-libLTLIBRARIES uninstall-man uninstall-pkgconfigDATA
+       uninstall-info-am uninstall-libLTLIBRARIES uninstall-man \
+       uninstall-pkgconfigDATA
 
 uninstall-man: uninstall-man1
 
-.MAKE: install-am install-strip
-
 .PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \
        clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \
        clean-libtool ctags dist dist-all dist-bzip2 dist-gzip \
-       dist-lzma dist-shar dist-tarZ dist-xz dist-zip distcheck \
-       distclean distclean-compile distclean-generic \
-       distclean-libtool distclean-tags distcleancheck distdir \
-       distuninstallcheck dvi dvi-am html html-am info info-am \
-       install install-am install-binPROGRAMS install-data \
-       install-data-am install-dvi install-dvi-am install-exec \
-       install-exec-am install-html install-html-am \
-       install-includeHEADERS install-info install-info-am \
-       install-libLTLIBRARIES install-man install-man1 install-pdf \
-       install-pdf-am install-pkgconfigDATA install-ps install-ps-am \
-       install-strip installcheck installcheck-am installdirs \
-       maintainer-clean maintainer-clean-generic mostlyclean \
-       mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
-       pdf pdf-am ps ps-am tags uninstall uninstall-am \
-       uninstall-binPROGRAMS uninstall-includeHEADERS \
+       dist-shar dist-tarZ dist-zip distcheck distclean \
+       distclean-compile distclean-generic distclean-libtool \
+       distclean-tags distcleancheck distdir distuninstallcheck dvi \
+       dvi-am html html-am info info-am install install-am \
+       install-binPROGRAMS install-data install-data-am install-exec \
+       install-exec-am install-includeHEADERS install-info \
+       install-info-am install-libLTLIBRARIES install-man \
+       install-man1 install-pkgconfigDATA install-strip installcheck \
+       installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-compile \
+       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+       tags uninstall uninstall-am uninstall-binPROGRAMS \
+       uninstall-includeHEADERS uninstall-info-am \
        uninstall-libLTLIBRARIES uninstall-man uninstall-man1 \
        uninstall-pkgconfigDATA
 
-
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
index 8a0568572ef10a0359963c821bb4e8edd145b1e2..9bf7979ec43c23adbeb1b353892b1a91a84d27e2 100755 (executable)
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for sqlite 3.7.14.1.
+# Generated by GNU Autoconf 2.68 for sqlite 3.7.15.
 #
 # Report bugs to <http://www.sqlite.org>.
 #
@@ -714,8 +714,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='sqlite'
 PACKAGE_TARNAME='sqlite'
-PACKAGE_VERSION='3.7.14.1'
-PACKAGE_STRING='sqlite 3.7.14.1'
+PACKAGE_VERSION='3.7.15'
+PACKAGE_STRING='sqlite 3.7.15'
 PACKAGE_BUGREPORT='http://www.sqlite.org'
 PACKAGE_URL=''
 
@@ -1437,7 +1437,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures sqlite 3.7.14.1 to adapt to many kinds of systems.
+\`configure' configures sqlite 3.7.15 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1507,7 +1507,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of sqlite 3.7.14.1:";;
+     short | recursive ) echo "Configuration of sqlite 3.7.15:";;
    esac
   cat <<\_ACEOF
 
@@ -1617,7 +1617,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-sqlite configure 3.7.14.1
+sqlite configure 3.7.15
 generated by GNU Autoconf 2.68
 
 Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2237,7 +2237,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by sqlite $as_me 3.7.14.1, which was
+It was created by sqlite $as_me 3.7.15, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   $ $0 $@
@@ -2906,7 +2906,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='sqlite'
- VERSION='3.7.14.1'
+ VERSION='3.7.15'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -20487,7 +20487,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by sqlite $as_me 3.7.14.1, which was
+This file was extended by sqlite $as_me 3.7.15, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -20544,7 +20544,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-sqlite config.status 3.7.14.1
+sqlite config.status 3.7.15
 configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
index 36c1aed1654d69388d8a084f324d95bccf2c262b..657d496e166b7d734bb964352743bf9583e2ac8d 100644 (file)
@@ -8,7 +8,7 @@
 #
 
 AC_PREREQ(2.61)
-AC_INIT(sqlite, 3.7.14.1, http://www.sqlite.org)
+AC_INIT(sqlite, 3.7.15, http://www.sqlite.org)
 AC_CONFIG_SRCDIR([sqlite3.c])
 
 # Use automake.
index a17d966245c15a0183df882518283fef263c505d..7dd741b2d7fa2f467c96125dd61892cfbd2c1ca4 100644 (file)
@@ -541,6 +541,9 @@ static void output_c_string(FILE *out, const char *z){
     if( c=='\\' ){
       fputc(c, out);
       fputc(c, out);
+    }else if( c=='"' ){
+      fputc('\\', out);
+      fputc('"', out);
     }else if( c=='\t' ){
       fputc('\\', out);
       fputc('t', out);
@@ -696,7 +699,7 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int
           }else{
             w = 0;
           }
-          if( w<=0 ){
+          if( w==0 ){
             w = strlen30(azCol[i] ? azCol[i] : "");
             if( w<10 ) w = 10;
             n = strlen30(azArg && azArg[i] ? azArg[i] : p->nullvalue);
@@ -706,7 +709,11 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int
             p->actualWidth[i] = w;
           }
           if( p->showHeader ){
-            fprintf(p->out,"%-*.*s%s",w,w,azCol[i], i==nArg-1 ? "\n": "  ");
+            if( w<0 ){
+              fprintf(p->out,"%*.*s%s",-w,-w,azCol[i], i==nArg-1 ? "\n": "  ");
+            }else{
+              fprintf(p->out,"%-*.*s%s",w,w,azCol[i], i==nArg-1 ? "\n": "  ");
+            }
           }
         }
         if( p->showHeader ){
@@ -714,6 +721,7 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int
             int w;
             if( i<ArraySize(p->actualWidth) ){
                w = p->actualWidth[i];
+               if( w<0 ) w = -w;
             }else{
                w = 10;
             }
@@ -735,8 +743,13 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int
            strlen30(azArg[i])>w ){
           w = strlen30(azArg[i]);
         }
-        fprintf(p->out,"%-*.*s%s",w,w,
-            azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": "  ");
+        if( w<0 ){
+          fprintf(p->out,"%*.*s%s",-w,-w,
+              azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": "  ");
+        }else{
+          fprintf(p->out,"%-*.*s%s",w,w,
+              azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": "  ");
+        }
       }
       break;
     }
@@ -786,14 +799,14 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int
       if( p->cnt++==0 && p->showHeader ){
         for(i=0; i<nArg; i++){
           output_c_string(p->out,azCol[i] ? azCol[i] : "");
-          fprintf(p->out, "%s", p->separator);
+          if(i<nArg-1) fprintf(p->out, "%s", p->separator);
         }
         fprintf(p->out,"\n");
       }
       if( azArg==0 ) break;
       for(i=0; i<nArg; i++){
         output_c_string(p->out, azArg[i] ? azArg[i] : p->nullvalue);
-        fprintf(p->out, "%s", p->separator);
+        if(i<nArg-1) fprintf(p->out, "%s", p->separator);
       }
       fprintf(p->out,"\n");
       break;
@@ -1416,9 +1429,10 @@ static char zHelp[] =
   "                         list     Values delimited by .separator string\n"
   "                         tabs     Tab-separated values\n"
   "                         tcl      TCL list elements\n"
-  ".nullvalue STRING      Print STRING in place of NULL values\n"
+  ".nullvalue STRING      Use STRING in place of NULL values\n"
   ".output FILENAME       Send output to FILENAME\n"
   ".output stdout         Send output to the screen\n"
+  ".print STRING...       Print literal STRING\n"
   ".prompt MAIN CONTINUE  Replace the standard prompts\n"
   ".quit                  Exit this program\n"
   ".read FILENAME         Execute SQL in FILENAME\n"
@@ -2007,6 +2021,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
       p->mode = MODE_Html;
     }else if( n2==3 && strncmp(azArg[1],"tcl",n2)==0 ){
       p->mode = MODE_Tcl;
+      sqlite3_snprintf(sizeof(p->separator), p->separator, " ");
     }else if( n2==3 && strncmp(azArg[1],"csv",n2)==0 ){
       p->mode = MODE_Csv;
       sqlite3_snprintf(sizeof(p->separator), p->separator, ",");
@@ -2070,6 +2085,15 @@ static int do_meta_command(char *zLine, struct callback_data *p){
     }
   }else
 
+  if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
+    int i;
+    for(i=1; i<nArg; i++){
+      if( i>1 ) fprintf(p->out, " ");
+      fprintf(p->out, "%s", azArg[i]);
+    }
+    fprintf(p->out, "\n");
+  }else
+
   if( c=='p' && strncmp(azArg[0], "prompt", n)==0 && (nArg==2 || nArg==3)){
     if( nArg >= 2) {
       strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
@@ -2493,6 +2517,13 @@ static int do_meta_command(char *zLine, struct callback_data *p){
     }
   }else
 
+#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
+  if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
+    extern int sqlite3WhereTrace;
+    sqlite3WhereTrace = atoi(azArg[1]);
+  }else
+#endif
+
   if( c=='w' && strncmp(azArg[0], "width", n)==0 && nArg>1 ){
     int j;
     assert( nArg<=ArraySize(azArg) );
@@ -2684,7 +2715,7 @@ static int process_input(struct callback_data *p, FILE *in){
     free(zSql);
   }
   free(zLine);
-  return errCnt;
+  return errCnt>0;
 }
 
 /*
@@ -2797,11 +2828,14 @@ static const char zOptions[] =
   "   -bail                stop after hitting an error\n"
   "   -batch               force batch I/O\n"
   "   -column              set output mode to 'column'\n"
-  "   -cmd command         run \"command\" before reading stdin\n"
+  "   -cmd COMMAND         run \"COMMAND\" before reading stdin\n"
   "   -csv                 set output mode to 'csv'\n"
   "   -echo                print commands before execution\n"
-  "   -init filename       read/process named file\n"
+  "   -init FILENAME       read/process named file\n"
   "   -[no]header          turn headers on or off\n"
+#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
+  "   -heap SIZE           Size of heap for memsys3 or memsys5\n"
+#endif
   "   -help                show this message\n"
   "   -html                set output mode to HTML\n"
   "   -interactive         force interactive I/O\n"
@@ -2810,8 +2844,8 @@ static const char zOptions[] =
 #ifdef SQLITE_ENABLE_MULTIPLEX
   "   -multiplex           enable the multiplexor VFS\n"
 #endif
-  "   -nullvalue 'text'    set text string for NULL values\n"
-  "   -separator 'x'       set output field separator (|)\n"
+  "   -nullvalue TEXT      set text string for NULL values. Default ''\n"
+  "   -separator SEP       set output field separator. Default: '|'\n"
   "   -stats               print memory stats before each finalize\n"
   "   -version             show SQLite version\n"
   "   -vfs NAME            use NAME as the default VFS\n"
@@ -2847,6 +2881,19 @@ static void main_init(struct callback_data *data) {
   sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
 }
 
+/*
+** Get the argument to an --option.  Throw an error and die if no argument
+** is available.
+*/
+static char *cmdline_option_value(int argc, char **argv, int i){
+  if( i==argc ){
+    fprintf(stderr, "%s: Error: missing argument to %s\n",
+            argv[0], argv[argc-1]);
+    exit(1);
+  }
+  return argv[i];
+}
+
 int main(int argc, char **argv){
   char *zErrMsg = 0;
   struct callback_data data;
@@ -2876,24 +2923,35 @@ int main(int argc, char **argv){
   ** the size of the alternative malloc heap,
   ** and the first command to execute.
   */
-  for(i=1; i<argc-1; i++){
+  for(i=1; i<argc; i++){
     char *z;
-    if( argv[i][0]!='-' ) break;
     z = argv[i];
+    if( z[0]!='-' ){
+      if( data.zDbFilename==0 ){
+        data.zDbFilename = z;
+        continue;
+      }
+      if( zFirstCmd==0 ){
+        zFirstCmd = z;
+        continue;
+      }
+      fprintf(stderr,"%s: Error: too many options: \"%s\"\n", Argv0, argv[i]);
+      fprintf(stderr,"Use -help for a list of options.\n");
+      return 1;
+    }
     if( z[1]=='-' ) z++;
     if( strcmp(z,"-separator")==0
      || strcmp(z,"-nullvalue")==0
      || strcmp(z,"-cmd")==0
     ){
-      i++;
+      (void)cmdline_option_value(argc, argv, ++i);
     }else if( strcmp(z,"-init")==0 ){
-      i++;
-      zInitFile = argv[i];
-    /* Need to check for batch mode here to so we can avoid printing
-    ** informational messages (like from process_sqliterc) before 
-    ** we do the actual processing of arguments later in a second pass.
-    */
+      zInitFile = cmdline_option_value(argc, argv, ++i);
     }else if( strcmp(z,"-batch")==0 ){
+      /* Need to check for batch mode here to so we can avoid printing
+      ** informational messages (like from process_sqliterc) before 
+      ** we do the actual processing of arguments later in a second pass.
+      */
       stdin_is_interactive = 0;
     }else if( strcmp(z,"-heap")==0 ){
 #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
@@ -2901,7 +2959,7 @@ int main(int argc, char **argv){
       const char *zSize;
       sqlite3_int64 szHeap;
 
-      zSize = argv[++i];
+      zSize = cmdline_option_value(argc, argv, ++i);
       szHeap = atoi(zSize);
       for(j=0; (c = zSize[j])!=0; j++){
         if( c=='M' ){ szHeap *= 1000000; break; }
@@ -2928,7 +2986,7 @@ int main(int argc, char **argv){
       sqlite3_multiplex_initialize(0, 1);
 #endif
     }else if( strcmp(z,"-vfs")==0 ){
-      sqlite3_vfs *pVfs = sqlite3_vfs_find(argv[++i]);
+      sqlite3_vfs *pVfs = sqlite3_vfs_find(cmdline_option_value(argc,argv,++i));
       if( pVfs ){
         sqlite3_vfs_register(pVfs, 1);
       }else{
@@ -2937,31 +2995,15 @@ int main(int argc, char **argv){
       }
     }
   }
-  if( i<argc ){
-    data.zDbFilename = argv[i++];
-  }else{
+  if( data.zDbFilename==0 ){
 #ifndef SQLITE_OMIT_MEMORYDB
     data.zDbFilename = ":memory:";
 #else
-    data.zDbFilename = 0;
-#endif
-  }
-  if( i<argc ){
-    zFirstCmd = argv[i++];
-  }
-  if( i<argc ){
-    fprintf(stderr,"%s: Error: too many options: \"%s\"\n", Argv0, argv[i]);
-    fprintf(stderr,"Use -help for a list of options.\n");
-    return 1;
-  }
-  data.out = stdout;
-
-#ifdef SQLITE_OMIT_MEMORYDB
-  if( data.zDbFilename==0 ){
     fprintf(stderr,"%s: Error: no database filename specified\n", Argv0);
     return 1;
-  }
 #endif
+  }
+  data.out = stdout;
 
   /* Go ahead and open the database file if it already exists.  If the
   ** file does not exist, delay opening it.  This prevents empty database
@@ -2986,8 +3028,9 @@ int main(int argc, char **argv){
   ** file is processed so that the command-line arguments will override
   ** settings in the initialization file.
   */
-  for(i=1; i<argc && argv[i][0]=='-'; i++){
+  for(i=1; i<argc; i++){
     char *z = argv[i];
+    if( z[0]!='-' ) continue;
     if( z[1]=='-' ){ z++; }
     if( strcmp(z,"-init")==0 ){
       i++;
@@ -3003,25 +3046,11 @@ int main(int argc, char **argv){
       data.mode = MODE_Csv;
       memcpy(data.separator,",",2);
     }else if( strcmp(z,"-separator")==0 ){
-      i++;
-      if(i>=argc){
-        fprintf(stderr,"%s: Error: missing argument for option: %s\n",
-                        Argv0, z);
-        fprintf(stderr,"Use -help for a list of options.\n");
-        return 1;
-      }
       sqlite3_snprintf(sizeof(data.separator), data.separator,
-                       "%.*s",(int)sizeof(data.separator)-1,argv[i]);
+                       "%s",cmdline_option_value(argc,argv,++i));
     }else if( strcmp(z,"-nullvalue")==0 ){
-      i++;
-      if(i>=argc){
-        fprintf(stderr,"%s: Error: missing argument for option: %s\n",
-                        Argv0, z);
-        fprintf(stderr,"Use -help for a list of options.\n");
-        return 1;
-      }
       sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue,
-                       "%.*s",(int)sizeof(data.nullvalue)-1,argv[i]);
+                       "%s",cmdline_option_value(argc,argv,++i));
     }else if( strcmp(z,"-header")==0 ){
       data.showHeader = 1;
     }else if( strcmp(z,"-noheader")==0 ){
@@ -3055,8 +3084,7 @@ int main(int argc, char **argv){
       usage(1);
     }else if( strcmp(z,"-cmd")==0 ){
       if( i==argc-1 ) break;
-      i++;
-      z = argv[i];
+      z = cmdline_option_value(argc,argv,++i);
       if( z[0]=='.' ){
         rc = do_meta_command(z, &data);
         if( rc && bail_on_error ) return rc;
index 55039b963ca356a172ef76148e266f67a07d0650..f7dabc6c7f7d02d1fdd21301682a23304a7e2605 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 ** This file is an amalgamation of many separate C source files from SQLite
-** version 3.7.14.1.  By combining all the individual C code files into this 
+** version 3.7.15.  By combining all the individual C code files into this 
 ** single large file, the entire code can be compiled as a single translation
 ** unit.  This allows many compilers to do optimizations that would not be
 ** possible if the files were compiled separately.  Performance improvements
@@ -673,9 +673,9 @@ extern "C" {
 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
 ** [sqlite_version()] and [sqlite_source_id()].
 */
-#define SQLITE_VERSION        "3.7.14.1"
-#define SQLITE_VERSION_NUMBER 3007014
-#define SQLITE_SOURCE_ID      "2012-10-04 19:37:12 091570e46d04e84b67228e0bdbcd6e1fb60c6bdb"
+#define SQLITE_VERSION        "3.7.15"
+#define SQLITE_VERSION_NUMBER 3007015
+#define SQLITE_SOURCE_ID      "2012-12-12 13:36:53 cd0b37c52658bfdf992b1e3dc467bae1835a94ae"
 
 /*
 ** CAPI3REF: Run-Time Library Version Numbers
@@ -1040,10 +1040,12 @@ SQLITE_API int sqlite3_exec(
 #define SQLITE_IOERR_SHMLOCK           (SQLITE_IOERR | (20<<8))
 #define SQLITE_IOERR_SHMMAP            (SQLITE_IOERR | (21<<8))
 #define SQLITE_IOERR_SEEK              (SQLITE_IOERR | (22<<8))
+#define SQLITE_IOERR_DELETE_NOENT      (SQLITE_IOERR | (23<<8))
 #define SQLITE_LOCKED_SHAREDCACHE      (SQLITE_LOCKED |  (1<<8))
 #define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
 #define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))
 #define SQLITE_CANTOPEN_ISDIR          (SQLITE_CANTOPEN | (2<<8))
+#define SQLITE_CANTOPEN_FULLPATH       (SQLITE_CANTOPEN | (3<<8))
 #define SQLITE_CORRUPT_VTAB            (SQLITE_CORRUPT | (1<<8))
 #define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
 #define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))
@@ -1421,6 +1423,26 @@ struct sqlite3_io_methods {
 ** compilation of the PRAGMA fails with an error.  ^The [SQLITE_FCNTL_PRAGMA]
 ** file control occurs at the beginning of pragma statement analysis and so
 ** it is able to override built-in [PRAGMA] statements.
+**
+** <li>[[SQLITE_FCNTL_BUSYHANDLER]]
+** ^This file-control may be invoked by SQLite on the database file handle
+** shortly after it is opened in order to provide a custom VFS with access
+** to the connections busy-handler callback. The argument is of type (void **)
+** - an array of two (void *) values. The first (void *) actually points
+** to a function of type (int (*)(void *)). In order to invoke the connections
+** busy-handler, this function should be invoked with the second (void *) in
+** the array as the only argument. If it returns non-zero, then the operation
+** should be retried. If it returns zero, the custom VFS should abandon the
+** current operation.
+**
+** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
+** ^Application can invoke this file-control to have SQLite generate a
+** temporary filename using the same algorithm that is followed to generate
+** temporary filenames for TEMP tables and other internal uses.  The
+** argument should be a char** which will be filled with the filename
+** written into memory obtained from [sqlite3_malloc()].  The caller should
+** invoke [sqlite3_free()] on the result to avoid a memory leak.
+**
 ** </ul>
 */
 #define SQLITE_FCNTL_LOCKSTATE               1
@@ -1437,6 +1459,8 @@ struct sqlite3_io_methods {
 #define SQLITE_FCNTL_VFSNAME                12
 #define SQLITE_FCNTL_POWERSAFE_OVERWRITE    13
 #define SQLITE_FCNTL_PRAGMA                 14
+#define SQLITE_FCNTL_BUSYHANDLER            15
+#define SQLITE_FCNTL_TEMPFILENAME           16
 
 /*
 ** CAPI3REF: Mutex Handle
@@ -2133,11 +2157,39 @@ struct sqlite3_mem_methods {
 ** disabled. The default value may be changed by compiling with the
 ** [SQLITE_USE_URI] symbol defined.
 **
+** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
+** <dd> This option takes a single integer argument which is interpreted as
+** a boolean in order to enable or disable the use of covering indices for
+** full table scans in the query optimizer.  The default setting is determined
+** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
+** if that compile-time option is omitted.
+** The ability to disable the use of covering indices for full table scans
+** is because some incorrectly coded legacy applications might malfunction
+** malfunction when the optimization is enabled.  Providing the ability to
+** disable the optimization allows the older, buggy application code to work
+** without change even with newer versions of SQLite.
+**
 ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
 ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE
 ** <dd> These options are obsolete and should not be used by new code.
 ** They are retained for backwards compatibility but are now no-ops.
 ** </dl>
+**
+** [[SQLITE_CONFIG_SQLLOG]]
+** <dt>SQLITE_CONFIG_SQLLOG
+** <dd>This option is only available if sqlite is compiled with the
+** SQLITE_ENABLE_SQLLOG pre-processor macro defined. The first argument should
+** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int).
+** The second should be of type (void*). The callback is invoked by the library
+** in three separate circumstances, identified by the value passed as the
+** fourth parameter. If the fourth parameter is 0, then the database connection
+** passed as the second argument has just been opened. The third argument
+** points to a buffer containing the name of the main database file. If the
+** fourth parameter is 1, then the SQL statement that the third parameter
+** points to has just been executed. Or, if the fourth parameter is 2, then
+** the connection being passed as the second parameter is being closed. The
+** third parameter is passed NULL In this case.
+** </dl>
 */
 #define SQLITE_CONFIG_SINGLETHREAD  1  /* nil */
 #define SQLITE_CONFIG_MULTITHREAD   2  /* nil */
@@ -2158,6 +2210,8 @@ struct sqlite3_mem_methods {
 #define SQLITE_CONFIG_URI          17  /* int */
 #define SQLITE_CONFIG_PCACHE2      18  /* sqlite3_pcache_methods2* */
 #define SQLITE_CONFIG_GETPCACHE2   19  /* sqlite3_pcache_methods2* */
+#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20  /* int */
+#define SQLITE_CONFIG_SQLLOG       21  /* xSqllog, void* */
 
 /*
 ** CAPI3REF: Database Connection Configuration Options
@@ -3166,7 +3220,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **     an error)^. 
 **     ^If "ro" is specified, then the database is opened for read-only 
 **     access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the 
-**     third argument to sqlite3_prepare_v2(). ^If the mode option is set to 
+**     third argument to sqlite3_open_v2(). ^If the mode option is set to 
 **     "rw", then the database is opened for read-write (but not create) 
 **     access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had 
 **     been set. ^Value "rwc" is equivalent to setting both 
@@ -3318,6 +3372,11 @@ SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int
 ** However, the error string might be overwritten or deallocated by
 ** subsequent calls to other SQLite interface functions.)^
 **
+** ^The sqlite3_errstr() interface returns the English-language text
+** that describes the [result code], as UTF-8.
+** ^(Memory to hold the error message string is managed internally
+** and must not be freed by the application)^.
+**
 ** When the serialized [threading mode] is in use, it might be the
 ** case that a second error occurs on a separate thread in between
 ** the time of the first error and the call to these interfaces.
@@ -3336,6 +3395,7 @@ SQLITE_API int sqlite3_errcode(sqlite3 *db);
 SQLITE_API int sqlite3_extended_errcode(sqlite3 *db);
 SQLITE_API const char *sqlite3_errmsg(sqlite3*);
 SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
+SQLITE_API const char *sqlite3_errstr(int);
 
 /*
 ** CAPI3REF: SQL Statement Object
@@ -5298,6 +5358,9 @@ SQLITE_API void *sqlite3_update_hook(
 ** future releases of SQLite.  Applications that care about shared
 ** cache setting should set it explicitly.
 **
+** This interface is threadsafe on processors where writing a
+** 32-bit integer is atomic.
+**
 ** See Also:  [SQLite Shared-Cache Mode]
 */
 SQLITE_API int sqlite3_enable_shared_cache(int);
@@ -8263,6 +8326,7 @@ typedef struct Parse Parse;
 typedef struct RowSet RowSet;
 typedef struct Savepoint Savepoint;
 typedef struct Select Select;
+typedef struct SelectDest SelectDest;
 typedef struct SrcList SrcList;
 typedef struct StrAccum StrAccum;
 typedef struct Table Table;
@@ -8359,6 +8423,9 @@ SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int);
 SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*);
 SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int);
 SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*);
+#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_DEBUG)
+SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p);
+#endif
 SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int);
 SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *);
 SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int);
@@ -8402,6 +8469,8 @@ SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int);
 SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
 SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
 
+SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p);
+
 /*
 ** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta
 ** should be one of the following values. The integer values are assigned 
@@ -8869,7 +8938,7 @@ typedef struct VdbeOpList VdbeOpList;
 #define OPFLG_OUT3            0x0040  /* out3:  P3 is an output */
 #define OPFLG_INITIALIZER {\
 /*   0 */ 0x00, 0x01, 0x01, 0x04, 0x04, 0x10, 0x00, 0x02,\
-/*   8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x24, 0x24,\
+/*   8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x24,\
 /*  16 */ 0x00, 0x00, 0x00, 0x24, 0x04, 0x05, 0x04, 0x00,\
 /*  24 */ 0x00, 0x01, 0x01, 0x05, 0x05, 0x00, 0x00, 0x00,\
 /*  32 */ 0x02, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,\
@@ -8916,7 +8985,7 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
 SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*);
 SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*);
 SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*);
-SQLITE_PRIVATE void sqlite3VdbeDeleteObject(sqlite3*,Vdbe*);
+SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3*,Vdbe*);
 SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,Parse*);
 SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*);
 SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int);
@@ -9106,11 +9175,14 @@ SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
 SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
 SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager);
 
-SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*);
-SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager);
-SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager);
-SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
-SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager);
+#ifndef SQLITE_OMIT_WAL
+SQLITE_PRIVATE   int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*);
+SQLITE_PRIVATE   int sqlite3PagerWalSupported(Pager *pPager);
+SQLITE_PRIVATE   int sqlite3PagerWalCallback(Pager *pPager);
+SQLITE_PRIVATE   int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
+SQLITE_PRIVATE   int sqlite3PagerCloseWal(Pager *pPager);
+#endif
+
 #ifdef SQLITE_ENABLE_ZIPVFS
 SQLITE_PRIVATE   int sqlite3PagerWalFramesize(Pager *pPager);
 #endif
@@ -9128,6 +9200,7 @@ SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
 SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
 SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *);
 SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *);
+SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *);
 
 /* Functions used to truncate the database file. */
 SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);
@@ -9825,6 +9898,7 @@ struct sqlite3 {
   unsigned int openFlags;       /* Flags passed to sqlite3_vfs.xOpen() */
   int errCode;                  /* Most recent error code (SQLITE_*) */
   int errMask;                  /* & result codes with this before returning */
+  u16 dbOptFlags;               /* Flags to enable/disable optimizations */
   u8 autoCommit;                /* The auto-commit flag. */
   u8 temp_store;                /* 1: file 2: memory 0: default */
   u8 mallocFailed;              /* True if we have seen a malloc failure */
@@ -9929,48 +10003,59 @@ struct sqlite3 {
 /*
 ** Possible values for the sqlite3.flags.
 */
-#define SQLITE_VdbeTrace      0x00000100  /* True to trace VDBE execution */
-#define SQLITE_InternChanges  0x00000200  /* Uncommitted Hash table changes */
-#define SQLITE_FullColNames   0x00000400  /* Show full column names on SELECT */
-#define SQLITE_ShortColNames  0x00000800  /* Show short columns names */
-#define SQLITE_CountRows      0x00001000  /* Count rows changed by INSERT, */
+#define SQLITE_VdbeTrace      0x00000001  /* True to trace VDBE execution */
+#define SQLITE_InternChanges  0x00000002  /* Uncommitted Hash table changes */
+#define SQLITE_FullColNames   0x00000004  /* Show full column names on SELECT */
+#define SQLITE_ShortColNames  0x00000008  /* Show short columns names */
+#define SQLITE_CountRows      0x00000010  /* Count rows changed by INSERT, */
                                           /*   DELETE, or UPDATE and return */
                                           /*   the count using a callback. */
-#define SQLITE_NullCallback   0x00002000  /* Invoke the callback once if the */
+#define SQLITE_NullCallback   0x00000020  /* Invoke the callback once if the */
                                           /*   result set is empty */
-#define SQLITE_SqlTrace       0x00004000  /* Debug print SQL as it executes */
-#define SQLITE_VdbeListing    0x00008000  /* Debug listings of VDBE programs */
-#define SQLITE_WriteSchema    0x00010000  /* OK to update SQLITE_MASTER */
-                         /*   0x00020000  Unused */
-#define SQLITE_IgnoreChecks   0x00040000  /* Do not enforce check constraints */
-#define SQLITE_ReadUncommitted 0x0080000  /* For shared-cache mode */
-#define SQLITE_LegacyFileFmt  0x00100000  /* Create new databases in format 1 */
-#define SQLITE_FullFSync      0x00200000  /* Use full fsync on the backend */
-#define SQLITE_CkptFullFSync  0x00400000  /* Use full fsync for checkpoint */
-#define SQLITE_RecoveryMode   0x00800000  /* Ignore schema errors */
-#define SQLITE_ReverseOrder   0x01000000  /* Reverse unordered SELECTs */
-#define SQLITE_RecTriggers    0x02000000  /* Enable recursive triggers */
-#define SQLITE_ForeignKeys    0x04000000  /* Enforce foreign key constraints  */
-#define SQLITE_AutoIndex      0x08000000  /* Enable automatic indexes */
-#define SQLITE_PreferBuiltin  0x10000000  /* Preference to built-in funcs */
-#define SQLITE_LoadExtension  0x20000000  /* Enable load_extension */
-#define SQLITE_EnableTrigger  0x40000000  /* True to enable triggers */
-
-/*
-** Bits of the sqlite3.flags field that are used by the
-** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface.
-** These must be the low-order bits of the flags field.
-*/
-#define SQLITE_QueryFlattener 0x01        /* Disable query flattening */
-#define SQLITE_ColumnCache    0x02        /* Disable the column cache */
-#define SQLITE_IndexSort      0x04        /* Disable indexes for sorting */
-#define SQLITE_IndexSearch    0x08        /* Disable indexes for searching */
-#define SQLITE_IndexCover     0x10        /* Disable index covering table */
-#define SQLITE_GroupByOrder   0x20        /* Disable GROUPBY cover of ORDERBY */
-#define SQLITE_FactorOutConst 0x40        /* Disable factoring out constants */
-#define SQLITE_IdxRealAsInt   0x80        /* Store REAL as INT in indices */
-#define SQLITE_DistinctOpt    0x80        /* DISTINCT using indexes */
-#define SQLITE_OptMask        0xff        /* Mask of all disablable opts */
+#define SQLITE_SqlTrace       0x00000040  /* Debug print SQL as it executes */
+#define SQLITE_VdbeListing    0x00000080  /* Debug listings of VDBE programs */
+#define SQLITE_WriteSchema    0x00000100  /* OK to update SQLITE_MASTER */
+                         /*   0x00000200  Unused */
+#define SQLITE_IgnoreChecks   0x00000400  /* Do not enforce check constraints */
+#define SQLITE_ReadUncommitted 0x0000800  /* For shared-cache mode */
+#define SQLITE_LegacyFileFmt  0x00001000  /* Create new databases in format 1 */
+#define SQLITE_FullFSync      0x00002000  /* Use full fsync on the backend */
+#define SQLITE_CkptFullFSync  0x00004000  /* Use full fsync for checkpoint */
+#define SQLITE_RecoveryMode   0x00008000  /* Ignore schema errors */
+#define SQLITE_ReverseOrder   0x00010000  /* Reverse unordered SELECTs */
+#define SQLITE_RecTriggers    0x00020000  /* Enable recursive triggers */
+#define SQLITE_ForeignKeys    0x00040000  /* Enforce foreign key constraints  */
+#define SQLITE_AutoIndex      0x00080000  /* Enable automatic indexes */
+#define SQLITE_PreferBuiltin  0x00100000  /* Preference to built-in funcs */
+#define SQLITE_LoadExtension  0x00200000  /* Enable load_extension */
+#define SQLITE_EnableTrigger  0x00400000  /* True to enable triggers */
+
+/*
+** Bits of the sqlite3.dbOptFlags field that are used by the
+** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
+** selectively disable various optimizations.
+*/
+#define SQLITE_QueryFlattener 0x0001   /* Query flattening */
+#define SQLITE_ColumnCache    0x0002   /* Column cache */
+#define SQLITE_GroupByOrder   0x0004   /* GROUPBY cover of ORDERBY */
+#define SQLITE_FactorOutConst 0x0008   /* Constant factoring */
+#define SQLITE_IdxRealAsInt   0x0010   /* Store REAL as INT in indices */
+#define SQLITE_DistinctOpt    0x0020   /* DISTINCT using indexes */
+#define SQLITE_CoverIdxScan   0x0040   /* Covering index scans */
+#define SQLITE_OrderByIdxJoin 0x0080   /* ORDER BY of joins via index */
+#define SQLITE_SubqCoroutine  0x0100   /* Evaluate subqueries as coroutines */
+#define SQLITE_AllOpts        0xffff   /* All optimizations */
+
+/*
+** Macros for testing whether or not optimizations are enabled or disabled.
+*/
+#ifndef SQLITE_OMIT_BUILTIN_TEST
+#define OptimizationDisabled(db, mask)  (((db)->dbOptFlags&(mask))!=0)
+#define OptimizationEnabled(db, mask)   (((db)->dbOptFlags&(mask))==0)
+#else
+#define OptimizationDisabled(db, mask)  0
+#define OptimizationEnabled(db, mask)   1
+#endif
 
 /*
 ** Possible values for the sqlite.magic field.
@@ -10121,32 +10206,22 @@ struct Column {
   char *zDflt;     /* Original text of the default value */
   char *zType;     /* Data type for this column */
   char *zColl;     /* Collating sequence.  If NULL, use the default */
-  u8 notNull;      /* True if there is a NOT NULL constraint */
-  u8 isPrimKey;    /* True if this column is part of the PRIMARY KEY */
+  u8 notNull;      /* An OE_ code for handling a NOT NULL constraint */
   char affinity;   /* One of the SQLITE_AFF_... values */
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-  u8 isHidden;     /* True if this column is 'hidden' */
-#endif
+  u16 colFlags;    /* Boolean properties.  See COLFLAG_ defines below */
 };
 
+/* Allowed values for Column.colFlags:
+*/
+#define COLFLAG_PRIMKEY  0x0001    /* Column is part of the primary key */
+#define COLFLAG_HIDDEN   0x0002    /* A hidden column in a virtual table */
+
 /*
 ** A "Collating Sequence" is defined by an instance of the following
 ** structure. Conceptually, a collating sequence consists of a name and
 ** a comparison routine that defines the order of that sequence.
 **
-** There may two separate implementations of the collation function, one
-** that processes text in UTF-8 encoding (CollSeq.xCmp) and another that
-** processes text encoded in UTF-16 (CollSeq.xCmp16), using the machine
-** native byte order. When a collation sequence is invoked, SQLite selects
-** the version that will require the least expensive encoding
-** translations, if any.
-**
-** The CollSeq.pUser member variable is an extra parameter that passed in
-** as the first argument to the UTF-8 comparison function, xCmp.
-** CollSeq.pUser16 is the equivalent for the UTF-16 comparison function,
-** xCmp16.
-**
-** If both CollSeq.xCmp and CollSeq.xCmp16 are NULL, it means that the
+** If CollSeq.xCmp is NULL, it means that the
 ** collating sequence is undefined.  Indices built on an undefined
 ** collating sequence may not be read or written.
 */
@@ -10284,28 +10359,28 @@ struct VTable {
 */
 struct Table {
   char *zName;         /* Name of the table or view */
-  int iPKey;           /* If not negative, use aCol[iPKey] as the primary key */
-  int nCol;            /* Number of columns in this table */
   Column *aCol;        /* Information about each column */
   Index *pIndex;       /* List of SQL indexes on this table. */
-  int tnum;            /* Root BTree node for this table (see note above) */
-  tRowcnt nRowEst;     /* Estimated rows in table - from sqlite_stat1 table */
   Select *pSelect;     /* NULL for tables.  Points to definition if a view. */
-  u16 nRef;            /* Number of pointers to this Table */
-  u8 tabFlags;         /* Mask of TF_* values */
-  u8 keyConf;          /* What to do in case of uniqueness conflict on iPKey */
   FKey *pFKey;         /* Linked list of all foreign keys in this table */
   char *zColAff;       /* String defining the affinity of each column */
 #ifndef SQLITE_OMIT_CHECK
   ExprList *pCheck;    /* All CHECK constraints */
 #endif
+  tRowcnt nRowEst;     /* Estimated rows in table - from sqlite_stat1 table */
+  int tnum;            /* Root BTree node for this table (see note above) */
+  i16 iPKey;           /* If not negative, use aCol[iPKey] as the primary key */
+  i16 nCol;            /* Number of columns in this table */
+  u16 nRef;            /* Number of pointers to this Table */
+  u8 tabFlags;         /* Mask of TF_* values */
+  u8 keyConf;          /* What to do in case of uniqueness conflict on iPKey */
 #ifndef SQLITE_OMIT_ALTERTABLE
   int addColOffset;    /* Offset in CREATE TABLE stmt to add a new column */
 #endif
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  VTable *pVTable;     /* List of VTable objects. */
   int nModuleArg;      /* Number of arguments to the module */
   char **azModuleArg;  /* Text of all module args. [0] is module name */
+  VTable *pVTable;     /* List of VTable objects. */
 #endif
   Trigger *pTrigger;   /* List of triggers stored in pSchema */
   Schema *pSchema;     /* Schema that contains this table */
@@ -10329,7 +10404,7 @@ struct Table {
 */
 #ifndef SQLITE_OMIT_VIRTUALTABLE
 #  define IsVirtual(X)      (((X)->tabFlags & TF_Virtual)!=0)
-#  define IsHiddenColumn(X) ((X)->isHidden)
+#  define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0)
 #else
 #  define IsVirtual(X)      0
 #  define IsHiddenColumn(X) 0
@@ -10674,13 +10749,15 @@ struct Expr {
     ExprList *pList;     /* Function arguments or in "<expr> IN (<expr-list)" */
     Select *pSelect;     /* Used for sub-selects and "<expr> IN (<select>)" */
   } x;
-  CollSeq *pColl;        /* The collation type of the column or 0 */
 
   /* If the EP_Reduced flag is set in the Expr.flags mask, then no
   ** space is allocated for the fields below this point. An attempt to
   ** access them will result in a segfault or malfunction.
   *********************************************************************/
 
+#if SQLITE_MAX_EXPR_DEPTH>0
+  int nHeight;           /* Height of the tree headed by this node */
+#endif
   int iTable;            /* TK_COLUMN: cursor number of table holding column
                          ** TK_REGISTER: register number
                          ** TK_TRIGGER: 1 -> new, 0 -> old */
@@ -10694,9 +10771,6 @@ struct Expr {
                          ** TK_AGG_FUNCTION: nesting depth */
   AggInfo *pAggInfo;     /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
   Table *pTab;           /* Table for TK_COLUMN expressions. */
-#if SQLITE_MAX_EXPR_DEPTH>0
-  int nHeight;           /* Height of the tree headed by this node */
-#endif
 };
 
 /*
@@ -10710,7 +10784,7 @@ struct Expr {
 #define EP_VarSelect  0x0020  /* pSelect is correlated, not constant */
 #define EP_DblQuoted  0x0040  /* token.z was originally in "..." */
 #define EP_InfixFunc  0x0080  /* True for an infix function: LIKE, GLOB, etc */
-#define EP_ExpCollate 0x0100  /* Collating sequence specified explicitly */
+#define EP_Collate    0x0100  /* Tree contains a TK_COLLATE opeartor */
 #define EP_FixedDest  0x0200  /* Result needed in a specific register */
 #define EP_IntValue   0x0400  /* Integer value contained in u.iValue */
 #define EP_xIsSelect  0x0800  /* x.pSelect is valid (otherwise x.pList is) */
@@ -10854,6 +10928,7 @@ struct SrcList {
   i16 nSrc;        /* Number of tables or subqueries in the FROM clause */
   i16 nAlloc;      /* Number of entries allocated in a[] below */
   struct SrcList_item {
+    Schema *pSchema;  /* Schema to which this item is fixed */
     char *zDatabase;  /* Name of database holding this table */
     char *zName;      /* Name of the table */
     char *zAlias;     /* The "B" part of a "A AS B" phrase.  zName is the "A" */
@@ -10862,8 +10937,9 @@ struct SrcList {
     int addrFillSub;  /* Address of subroutine to manifest a subquery */
     int regReturn;    /* Register holding return address of addrFillSub */
     u8 jointype;      /* Type of join between this able and the previous */
-    u8 notIndexed;    /* True if there is a NOT INDEXED clause */
-    u8 isCorrelated;  /* True if sub-query is correlated */
+    unsigned notIndexed :1;    /* True if there is a NOT INDEXED clause */
+    unsigned isCorrelated :1;  /* True if sub-query is correlated */
+    unsigned viaCoroutine :1;  /* Implemented as a co-routine */
 #ifndef SQLITE_OMIT_EXPLAIN
     u8 iSelectId;     /* If pSelect!=0, the id of the sub-select in EQP */
 #endif
@@ -10904,7 +10980,8 @@ struct SrcList {
 */
 struct WherePlan {
   u32 wsFlags;                   /* WHERE_* flags that describe the strategy */
-  u32 nEq;                       /* Number of == constraints */
+  u16 nEq;                       /* Number of == constraints */
+  u16 nOBSat;                    /* Number of ORDER BY terms satisfied */
   double nRow;                   /* Estimated number of rows (for EQP) */
   union {
     Index *pIdx;                   /* Index when WHERE_INDEXED is true */
@@ -10948,6 +11025,7 @@ struct WhereLevel {
     } in;                 /* Used when plan.wsFlags&WHERE_IN_ABLE */
     Index *pCovidx;       /* Possible covering index for WHERE_MULTI_OR */
   } u;
+  double rOptCost;      /* "Optimal" cost for this level */
 
   /* The following field is really not part of the current level.  But
   ** we need a place to cache virtual table index information for each
@@ -10980,24 +11058,28 @@ struct WhereLevel {
 ** into the second half to give some continuity.
 */
 struct WhereInfo {
-  Parse *pParse;       /* Parsing and code generating context */
-  u16 wctrlFlags;      /* Flags originally passed to sqlite3WhereBegin() */
-  u8 okOnePass;        /* Ok to use one-pass algorithm for UPDATE or DELETE */
-  u8 untestedTerms;    /* Not all WHERE terms resolved by outer loop */
-  u8 eDistinct;
-  SrcList *pTabList;             /* List of tables in the join */
-  int iTop;                      /* The very beginning of the WHERE loop */
-  int iContinue;                 /* Jump here to continue with next record */
-  int iBreak;                    /* Jump here to break out of the loop */
-  int nLevel;                    /* Number of nested loop */
-  struct WhereClause *pWC;       /* Decomposition of the WHERE clause */
-  double savedNQueryLoop;        /* pParse->nQueryLoop outside the WHERE loop */
-  double nRowOut;                /* Estimated number of output rows */
-  WhereLevel a[1];               /* Information about each nest loop in WHERE */
+  Parse *pParse;            /* Parsing and code generating context */
+  SrcList *pTabList;        /* List of tables in the join */
+  u16 nOBSat;               /* Number of ORDER BY terms satisfied by indices */
+  u16 wctrlFlags;           /* Flags originally passed to sqlite3WhereBegin() */
+  u8 okOnePass;             /* Ok to use one-pass algorithm for UPDATE/DELETE */
+  u8 untestedTerms;         /* Not all WHERE terms resolved by outer loop */
+  u8 eDistinct;             /* One of the WHERE_DISTINCT_* values below */
+  int iTop;                 /* The very beginning of the WHERE loop */
+  int iContinue;            /* Jump here to continue with next record */
+  int iBreak;               /* Jump here to break out of the loop */
+  int nLevel;               /* Number of nested loop */
+  struct WhereClause *pWC;  /* Decomposition of the WHERE clause */
+  double savedNQueryLoop;   /* pParse->nQueryLoop outside the WHERE loop */
+  double nRowOut;           /* Estimated number of output rows */
+  WhereLevel a[1];          /* Information about each nest loop in WHERE */
 };
 
-#define WHERE_DISTINCT_UNIQUE 1
-#define WHERE_DISTINCT_ORDERED 2
+/* Allowed values for WhereInfo.eDistinct and DistinctCtx.eTnctType */
+#define WHERE_DISTINCT_NOOP      0  /* DISTINCT keyword not used */
+#define WHERE_DISTINCT_UNIQUE    1  /* No duplicates */
+#define WHERE_DISTINCT_ORDERED   2  /* All duplicates are adjacent */
+#define WHERE_DISTINCT_UNORDERED 3  /* Duplicates are scattered */
 
 /*
 ** A NameContext defines a context in which to resolve table and column
@@ -11056,13 +11138,12 @@ struct NameContext {
 ** as the OP_OpenEphm instruction is coded because not
 ** enough information about the compound query is known at that point.
 ** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences
-** for the result set.  The KeyInfo for addrOpenTran[2] contains collating
+** for the result set.  The KeyInfo for addrOpenEphm[2] contains collating
 ** sequences for the ORDER BY clause.
 */
 struct Select {
   ExprList *pEList;      /* The fields of the result */
   u8 op;                 /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
-  char affinity;         /* MakeRecord with this affinity for SRT_Set */
   u16 selFlags;          /* Various SF_* values */
   int iLimit, iOffset;   /* Memory registers holding LIMIT & OFFSET counters */
   int addrOpenEphm[3];   /* OP_OpenEphem opcodes related to this select */
@@ -11083,14 +11164,15 @@ struct Select {
 ** Allowed values for Select.selFlags.  The "SF" prefix stands for
 ** "Select Flag".
 */
-#define SF_Distinct        0x01  /* Output should be DISTINCT */
-#define SF_Resolved        0x02  /* Identifiers have been resolved */
-#define SF_Aggregate       0x04  /* Contains aggregate functions */
-#define SF_UsesEphemeral   0x08  /* Uses the OpenEphemeral opcode */
-#define SF_Expanded        0x10  /* sqlite3SelectExpand() called on this */
-#define SF_HasTypeInfo     0x20  /* FROM subqueries have Table metadata */
-#define SF_UseSorter       0x40  /* Sort using a sorter */
-#define SF_Values          0x80  /* Synthesized from VALUES clause */
+#define SF_Distinct        0x0001  /* Output should be DISTINCT */
+#define SF_Resolved        0x0002  /* Identifiers have been resolved */
+#define SF_Aggregate       0x0004  /* Contains aggregate functions */
+#define SF_UsesEphemeral   0x0008  /* Uses the OpenEphemeral opcode */
+#define SF_Expanded        0x0010  /* sqlite3SelectExpand() called on this */
+#define SF_HasTypeInfo     0x0020  /* FROM subqueries have Table metadata */
+#define SF_UseSorter       0x0040  /* Sort using a sorter */
+#define SF_Values          0x0080  /* Synthesized from VALUES clause */
+#define SF_Materialize     0x0100  /* Force materialization of views */
 
 
 /*
@@ -11113,13 +11195,12 @@ struct Select {
 #define SRT_Coroutine   10  /* Generate a single row of result */
 
 /*
-** A structure used to customize the behavior of sqlite3Select(). See
-** comments above sqlite3Select() for details.
+** An instance of this object describes where to put of the results of
+** a SELECT statement.
 */
-typedef struct SelectDest SelectDest;
 struct SelectDest {
-  u8 eDest;         /* How to dispose of the results */
-  u8 affSdst;       /* Affinity used when eDest==SRT_Set */
+  u8 eDest;         /* How to dispose of the results.  On of SRT_* above. */
+  char affSdst;     /* Affinity used when eDest==SRT_Set */
   int iSDParm;      /* A parameter used by the eDest disposal method */
   int iSdst;        /* Base register where results are written */
   int nSdst;        /* Number of registers allocated */
@@ -11320,6 +11401,7 @@ struct AuthContext {
 #define OPFLAG_TYPEOFARG     0x80    /* OP_Column only used for typeof() */
 #define OPFLAG_BULKCSR       0x01    /* OP_Open** used to open bulk cursor */
 #define OPFLAG_P2ISREG       0x02    /* P2 to OP_Open** is a register number */
+#define OPFLAG_PERMUTE       0x01    /* OP_Compare: use the permutation */
 
 /*
  * Each trigger present in the database schema is stored as an instance of
@@ -11419,6 +11501,7 @@ struct TriggerStep {
 typedef struct DbFixer DbFixer;
 struct DbFixer {
   Parse *pParse;      /* The parsing context.  Error messages written here */
+  Schema *pSchema;    /* Fix items to this schema */
   const char *zDb;    /* Make sure all objects are contained in this database */
   const char *zType;  /* Type of the container - used for error messages */
   const Token *pName; /* Name of the container - used for error messages */
@@ -11461,6 +11544,7 @@ struct Sqlite3Config {
   int bCoreMutex;                   /* True to enable core mutexing */
   int bFullMutex;                   /* True to enable full mutexing */
   int bOpenUri;                     /* True to interpret filenames as URIs */
+  int bUseCis;                      /* Use covering indices for full-scans */
   int mxStrlen;                     /* Maximum string length */
   int szLookaside;                  /* Default lookaside buffer size */
   int nLookaside;                   /* Default lookaside buffer count */
@@ -11490,6 +11574,10 @@ struct Sqlite3Config {
   void (*xLog)(void*,int,const char*); /* Function for logging */
   void *pLogArg;                       /* First argument to xLog() */
   int bLocaltimeFault;              /* True to fail localtime() calls */
+#ifdef SQLITE_ENABLE_SQLLOG
+  void(*xSqllog)(void*,sqlite3*,const char*, int);
+  void *pSqllogArg;
+#endif
 };
 
 /*
@@ -11777,6 +11865,7 @@ SQLITE_PRIVATE   void sqlite3AutoincrementEnd(Parse *pParse);
 # define sqlite3AutoincrementBegin(X)
 # define sqlite3AutoincrementEnd(X)
 #endif
+SQLITE_PRIVATE int sqlite3CodeCoroutine(Parse*, Select*, SelectDest*);
 SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int);
 SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
 SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*);
@@ -11806,13 +11895,11 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, E
 #endif
 SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
 SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
-SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
-    Parse*,SrcList*,Expr*,ExprList**,ExprList*,u16,int);
+SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
 SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
 SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
 SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
 SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
-SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, int, int, int);
 SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int);
 SQLITE_PRIVATE void sqlite3ExprCachePush(Parse*);
 SQLITE_PRIVATE void sqlite3ExprCachePop(Parse*, int);
@@ -11829,6 +11916,7 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
 SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
 SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3*,const char*, const char*);
 SQLITE_PRIVATE Table *sqlite3LocateTable(Parse*,int isView,const char*, const char*);
+SQLITE_PRIVATE Table *sqlite3LocateTableItem(Parse*,int isView,struct SrcList_item *);
 SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
 SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
 SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
@@ -11952,7 +12040,7 @@ SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
 SQLITE_PRIVATE int sqlite3Atoi(const char*);
 SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
 SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
-SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8*, const u8**);
+SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**);
 
 /*
 ** Routines to read and write variable-length integers.  These used to
@@ -12005,8 +12093,9 @@ SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
 SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
 SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
 SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
-SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr*, CollSeq*);
-SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr*, Token*);
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, Token*);
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
+SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
 SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
 SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *);
 SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int);
@@ -12059,7 +12148,7 @@ SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const
 SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
 SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
 SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
-SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(sqlite3*, u8, CollSeq *, const char*);
+SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
 SQLITE_PRIVATE char sqlite3AffinityType(const char*);
 SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
 SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*);
@@ -12163,8 +12252,10 @@ SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
 SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
 SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3*);
 SQLITE_PRIVATE const char *sqlite3JournalModename(int);
-SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
-SQLITE_PRIVATE int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
+#ifndef SQLITE_OMIT_WAL
+SQLITE_PRIVATE   int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
+SQLITE_PRIVATE   int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
+#endif
 
 /* Declarations for functions in fkey.c. All of these are replaced by
 ** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign
@@ -12222,8 +12313,10 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, int*);
 SQLITE_PRIVATE   int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
 SQLITE_PRIVATE   int sqlite3JournalSize(sqlite3_vfs *);
 SQLITE_PRIVATE   int sqlite3JournalCreate(sqlite3_file *);
+SQLITE_PRIVATE   int sqlite3JournalExists(sqlite3_file *p);
 #else
   #define sqlite3JournalSize(pVfs) ((pVfs)->szOsFile)
+  #define sqlite3JournalExists(p) 1
 #endif
 
 SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *);
@@ -12452,6 +12545,10 @@ SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
 # define  SQLITE_USE_URI 0
 #endif
 
+#ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN
+# define SQLITE_ALLOW_COVERING_INDEX_SCAN 1
+#endif
+
 /*
 ** The following singleton contains the global configuration for
 ** the SQLite library.
@@ -12461,6 +12558,7 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
    1,                         /* bCoreMutex */
    SQLITE_THREADSAFE==1,      /* bFullMutex */
    SQLITE_USE_URI,            /* bOpenUri */
+   SQLITE_ALLOW_COVERING_INDEX_SCAN,   /* bUseCis */
    0x7ffffffe,                /* mxStrlen */
    128,                       /* szLookaside */
    500,                       /* nLookaside */
@@ -12489,6 +12587,10 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
    0,                         /* xLog */
    0,                         /* pLogArg */
    0,                         /* bLocaltimeFault */
+#ifdef SQLITE_ENABLE_SQLLOG
+   0,                         /* xSqllog */
+   0                          /* pSqllogArg */
+#endif
 };
 
 
@@ -12879,6 +12981,9 @@ static const char * const azCompileOpt[] = {
 #ifdef SQLITE_PROXY_DEBUG
   "PROXY_DEBUG",
 #endif
+#ifdef SQLITE_RTREE_INT_ONLY
+  "RTREE_INT_ONLY",
+#endif
 #ifdef SQLITE_SECURE_DELETE
   "SECURE_DELETE",
 #endif
@@ -13026,6 +13131,7 @@ struct VdbeCursor {
   Bool isIndex;         /* True if an index containing keys only - no data */
   Bool isOrdered;       /* True if the underlying table is BTREE_UNORDERED */
   Bool isSorter;        /* True if a new-style sorter */
+  Bool multiPseudo;     /* Multi-register pseudo-cursor */
   sqlite3_vtab_cursor *pVtabCursor;  /* The cursor for a virtual table */
   const sqlite3_module *pModule;     /* Module for cursor pVtabCursor */
   i64 seqCount;         /* Sequence counter */
@@ -13150,7 +13256,9 @@ struct Mem {
 #define MEM_RowSet    0x0020   /* Value is a RowSet object */
 #define MEM_Frame     0x0040   /* Value is a VdbeFrame object */
 #define MEM_Invalid   0x0080   /* Value is undefined */
-#define MEM_TypeMask  0x00ff   /* Mask of type bits */
+#define MEM_Cleared   0x0100   /* NULL set by OP_Null, not from data */
+#define MEM_TypeMask  0x01ff   /* Mask of type bits */
+
 
 /* Whenever Mem contains a valid string or blob representation, one of
 ** the following flags must be set to determine the memory management
@@ -13236,6 +13344,11 @@ struct Explain {
   char zBase[100];   /* Initial space */
 };
 
+/* A bitfield type for use inside of structures.  Always follow with :N where
+** N is the number of bits.
+*/
+typedef unsigned bft;  /* Bit Field Type */
+
 /*
 ** An instance of the virtual machine.  This structure contains the complete
 ** state of the virtual machine.
@@ -13277,15 +13390,16 @@ struct Vdbe {
   int pc;                 /* The program counter */
   int rc;                 /* Value to return */
   u8 errorAction;         /* Recovery action to do in case of an error */
-  u8 explain;             /* True if EXPLAIN present on SQL command */
-  u8 changeCntOn;         /* True to update the change-counter */
-  u8 expired;             /* True if the VM needs to be recompiled */
-  u8 runOnlyOnce;         /* Automatically expire on reset */
   u8 minWriteFileFormat;  /* Minimum file format for writable database files */
-  u8 inVtabMethod;        /* See comments above */
-  u8 usesStmtJournal;     /* True if uses a statement journal */
-  u8 readOnly;            /* True for read-only statements */
-  u8 isPrepareV2;         /* True if prepared with prepare_v2() */
+  bft explain:2;          /* True if EXPLAIN present on SQL command */
+  bft inVtabMethod:2;     /* See comments above */
+  bft changeCntOn:1;      /* True to update the change-counter */
+  bft expired:1;          /* True if the VM needs to be recompiled */
+  bft runOnlyOnce:1;      /* Automatically expire on reset */
+  bft usesStmtJournal:1;  /* True if uses a statement journal */
+  bft readOnly:1;         /* True for read-only statements */
+  bft isPrepareV2:1;      /* True if prepared with prepare_v2() */
+  bft doingRerun:1;       /* True if rerunning after an auto-reprepare */
   int nChange;            /* Number of db changes made since last reset */
   yDbMask btreeMask;      /* Bitmask of db->aDb[] entries referenced */
   yDbMask lockMask;       /* Subset of btreeMask that requires a lock */
@@ -13631,7 +13745,8 @@ SQLITE_API int sqlite3_db_status(
 
       db->pnBytesFreed = &nByte;
       for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
-        sqlite3VdbeDeleteObject(db, pVdbe);
+        sqlite3VdbeClearObject(db, pVdbe);
+        sqlite3DbFree(db, pVdbe);
       }
       db->pnBytesFreed = 0;
 
@@ -20527,25 +20642,23 @@ static const unsigned char sqlite3Utf8Trans1[] = {
         || (c&0xFFFFFFFE)==0xFFFE ){  c = 0xFFFD; }        \
   }
 SQLITE_PRIVATE u32 sqlite3Utf8Read(
-  const unsigned char *zIn,       /* First byte of UTF-8 character */
-  const unsigned char **pzNext    /* Write first byte past UTF-8 char here */
+  const unsigned char **pz    /* Pointer to string from which to read char */
 ){
   unsigned int c;
 
   /* Same as READ_UTF8() above but without the zTerm parameter.
   ** For this routine, we assume the UTF8 string is always zero-terminated.
   */
-  c = *(zIn++);
+  c = *((*pz)++);
   if( c>=0xc0 ){
     c = sqlite3Utf8Trans1[c-0xc0];
-    while( (*zIn & 0xc0)==0x80 ){
-      c = (c<<6) + (0x3f & *(zIn++));
+    while( (*(*pz) & 0xc0)==0x80 ){
+      c = (c<<6) + (0x3f & *((*pz)++));
     }
     if( c<0x80
         || (c&0xFFFFF800)==0xD800
         || (c&0xFFFFFFFE)==0xFFFE ){  c = 0xFFFD; }
   }
-  *pzNext = zIn;
   return c;
 }
 
@@ -20646,7 +20759,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
     if( desiredEnc==SQLITE_UTF16LE ){
       /* UTF-8 -> UTF-16 Little-endian */
       while( zIn<zTerm ){
-        /* c = sqlite3Utf8Read(zIn, zTerm, (const u8**)&zIn); */
         READ_UTF8(zIn, zTerm, c);
         WRITE_UTF16LE(z, c);
       }
@@ -20654,7 +20766,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
       assert( desiredEnc==SQLITE_UTF16BE );
       /* UTF-8 -> UTF-16 Big-endian */
       while( zIn<zTerm ){
-        /* c = sqlite3Utf8Read(zIn, zTerm, (const u8**)&zIn); */
         READ_UTF8(zIn, zTerm, c);
         WRITE_UTF16BE(z, c);
       }
@@ -20782,7 +20893,7 @@ SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char *zIn){
   u32 c;
 
   while( zIn[0] && zOut<=zIn ){
-    c = sqlite3Utf8Read(zIn, (const u8**)&zIn);
+    c = sqlite3Utf8Read((const u8**)&zIn);
     if( c!=0xfffd ){
       WRITE_UTF8(zOut, c);
     }
@@ -20887,7 +20998,7 @@ SQLITE_PRIVATE void sqlite3UtfSelfTest(void){
     assert( n>0 && n<=4 );
     z[0] = 0;
     z = zBuf;
-    c = sqlite3Utf8Read(z, (const u8**)&z);
+    c = sqlite3Utf8Read((const u8**)&z);
     t = i;
     if( i>=0xD800 && i<=0xDFFF ) t = 0xFFFD;
     if( (i&0xFFFFFFFE)==0xFFFE ) t = 0xFFFD;
@@ -22305,7 +22416,7 @@ static void removeElementGivenHash(
   }
   sqlite3_free( elem );
   pH->count--;
-  if( pH->count<=0 ){
+  if( pH->count==0 ){
     assert( pH->first==0 );
     assert( pH->count==0 );
     sqlite3HashClear(pH);
@@ -22603,6 +22714,17 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
 */
 #if SQLITE_OS_UNIX              /* This file is used on unix only */
 
+/* Use posix_fallocate() if it is available
+*/
+#if !defined(HAVE_POSIX_FALLOCATE) \
+      && (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L)
+# define HAVE_POSIX_FALLOCATE 1
+#endif
+
+#ifdef __UCLIBC__
+  #undef HAVE_POSIX_FALLOCATE
+#endif
+
 /*
 ** There are various methods for file locking used for concurrency
 ** control:
@@ -22775,6 +22897,10 @@ struct unixFile {
   const char *zPath;                  /* Name of the file */
   unixShm *pShm;                      /* Shared memory segment information */
   int szChunk;                        /* Configured by FCNTL_CHUNK_SIZE */
+#ifdef __QNXNTO__
+  int sectorSize;                     /* Device sector size */
+  int deviceCharacteristics;          /* Precomputed device characteristics */
+#endif
 #if SQLITE_ENABLE_LOCKING_STYLE
   int openFlags;                      /* The flags specified at open() */
 #endif
@@ -24851,13 +24977,13 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
 ** Close a file.  Make sure the lock has been released before closing.
 */
 static int dotlockClose(sqlite3_file *id) {
-  int rc;
+  int rc = SQLITE_OK;
   if( id ){
     unixFile *pFile = (unixFile*)id;
     dotlockUnlock(id, NO_LOCK);
     sqlite3_free(pFile->lockingContext);
+    rc = closeUnixFile(id);
   }
-  rc = closeUnixFile(id);
   return rc;
 }
 /****************** End of the dot-file lock implementation *******************
@@ -25061,10 +25187,12 @@ static int flockUnlock(sqlite3_file *id, int eFileLock) {
 ** Close a file.
 */
 static int flockClose(sqlite3_file *id) {
+  int rc = SQLITE_OK;
   if( id ){
     flockUnlock(id, NO_LOCK);
+    rc = closeUnixFile(id);
   }
-  return closeUnixFile(id);
+  return rc;
 }
 
 #endif /* SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORK */
@@ -25775,6 +25903,8 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
   i64 newOffset;
 #endif
   TIMER_START;
+  assert( cnt==(cnt&0x1ffff) );
+  cnt &= 0x1ffff;
   do{
 #if defined(USE_PREAD)
     got = osPread(id->h, pBuf, cnt, offset);
@@ -25864,6 +25994,8 @@ static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
 #if (!defined(USE_PREAD) && !defined(USE_PREAD64))
   i64 newOffset;
 #endif
+  assert( cnt==(cnt&0x1ffff) );
+  cnt &= 0x1ffff;
   TIMER_START;
 #if defined(USE_PREAD)
   do{ got = osPwrite(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR );
@@ -26329,6 +26461,9 @@ static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){
   }
 }
 
+/* Forward declaration */
+static int unixGetTempname(int nBuf, char *zBuf);
+
 /*
 ** Information and control of an open file handle.
 */
@@ -26366,6 +26501,14 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
       *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
       return SQLITE_OK;
     }
+    case SQLITE_FCNTL_TEMPFILENAME: {
+      char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
+      if( zTFile ){
+        unixGetTempname(pFile->pVfs->mxPathname, zTFile);
+        *(char**)pArg = zTFile;
+      }
+      return SQLITE_OK;
+    }
 #ifdef SQLITE_DEBUG
     /* The pager calls this method to signal that it has done
     ** a rollback and that the database is therefore unchanged and
@@ -26397,10 +26540,92 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
 ** a database and its journal file) that the sector size will be the
 ** same for both.
 */
-static int unixSectorSize(sqlite3_file *pFile){
-  (void)pFile;
+#ifndef __QNXNTO__ 
+static int unixSectorSize(sqlite3_file *NotUsed){
+  UNUSED_PARAMETER(NotUsed);
   return SQLITE_DEFAULT_SECTOR_SIZE;
 }
+#endif
+
+/*
+** The following version of unixSectorSize() is optimized for QNX.
+*/
+#ifdef __QNXNTO__
+#include <sys/dcmd_blk.h>
+#include <sys/statvfs.h>
+static int unixSectorSize(sqlite3_file *id){
+  unixFile *pFile = (unixFile*)id;
+  if( pFile->sectorSize == 0 ){
+    struct statvfs fsInfo;
+       
+    /* Set defaults for non-supported filesystems */
+    pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
+    pFile->deviceCharacteristics = 0;
+    if( fstatvfs(pFile->h, &fsInfo) == -1 ) {
+      return pFile->sectorSize;
+    }
+
+    if( !strcmp(fsInfo.f_basetype, "tmp") ) {
+      pFile->sectorSize = fsInfo.f_bsize;
+      pFile->deviceCharacteristics =
+        SQLITE_IOCAP_ATOMIC4K |       /* All ram filesystem writes are atomic */
+        SQLITE_IOCAP_SAFE_APPEND |    /* growing the file does not occur until
+                                      ** the write succeeds */
+        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
+                                      ** so it is ordered */
+        0;
+    }else if( strstr(fsInfo.f_basetype, "etfs") ){
+      pFile->sectorSize = fsInfo.f_bsize;
+      pFile->deviceCharacteristics =
+        /* etfs cluster size writes are atomic */
+        (pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) |
+        SQLITE_IOCAP_SAFE_APPEND |    /* growing the file does not occur until
+                                      ** the write succeeds */
+        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
+                                      ** so it is ordered */
+        0;
+    }else if( !strcmp(fsInfo.f_basetype, "qnx6") ){
+      pFile->sectorSize = fsInfo.f_bsize;
+      pFile->deviceCharacteristics =
+        SQLITE_IOCAP_ATOMIC |         /* All filesystem writes are atomic */
+        SQLITE_IOCAP_SAFE_APPEND |    /* growing the file does not occur until
+                                      ** the write succeeds */
+        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
+                                      ** so it is ordered */
+        0;
+    }else if( !strcmp(fsInfo.f_basetype, "qnx4") ){
+      pFile->sectorSize = fsInfo.f_bsize;
+      pFile->deviceCharacteristics =
+        /* full bitset of atomics from max sector size and smaller */
+        ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
+        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
+                                      ** so it is ordered */
+        0;
+    }else if( strstr(fsInfo.f_basetype, "dos") ){
+      pFile->sectorSize = fsInfo.f_bsize;
+      pFile->deviceCharacteristics =
+        /* full bitset of atomics from max sector size and smaller */
+        ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
+        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
+                                      ** so it is ordered */
+        0;
+    }else{
+      pFile->deviceCharacteristics =
+        SQLITE_IOCAP_ATOMIC512 |      /* blocks are atomic */
+        SQLITE_IOCAP_SAFE_APPEND |    /* growing the file does not occur until
+                                      ** the write succeeds */
+        0;
+    }
+  }
+  /* Last chance verification.  If the sector size isn't a multiple of 512
+  ** then it isn't valid.*/
+  if( pFile->sectorSize % 512 != 0 ){
+    pFile->deviceCharacteristics = 0;
+    pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
+  }
+  return pFile->sectorSize;
+}
+#endif /* __QNXNTO__ */
 
 /*
 ** Return the device characteristics for the file.
@@ -26417,11 +26642,15 @@ static int unixSectorSize(sqlite3_file *pFile){
 */
 static int unixDeviceCharacteristics(sqlite3_file *id){
   unixFile *p = (unixFile*)id;
+  int rc = 0;
+#ifdef __QNXNTO__
+  if( p->sectorSize==0 ) unixSectorSize(id);
+  rc = p->deviceCharacteristics;
+#endif
   if( p->ctrlFlags & UNIXFILE_PSOW ){
-    return SQLITE_IOCAP_POWERSAFE_OVERWRITE;
-  }else{
-    return 0;
+    rc |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
   }
+  return rc;
 }
 
 #ifndef SQLITE_OMIT_WAL
@@ -26837,11 +27066,19 @@ static int unixShmMap(
         ** the requested memory region.
         */
         if( !bExtend ) goto shmpage_out;
+#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
+        if( osFallocate(pShmNode->h, sStat.st_size, nByte)!=0 ){
+          rc = unixLogError(SQLITE_IOERR_SHMSIZE, "fallocate",
+                            pShmNode->zFilename);
+          goto shmpage_out;
+        }
+#else
         if( robust_ftruncate(pShmNode->h, nByte) ){
           rc = unixLogError(SQLITE_IOERR_SHMSIZE, "ftruncate",
                             pShmNode->zFilename);
           goto shmpage_out;
         }
+#endif
       }
     }
 
@@ -26859,7 +27096,7 @@ static int unixShmMap(
       if( pShmNode->h>=0 ){
         pMem = mmap(0, szRegion,
             pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, 
-            MAP_SHARED, pShmNode->h, pShmNode->nRegion*szRegion
+            MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
         );
         if( pMem==MAP_FAILED ){
           rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
@@ -28043,8 +28280,13 @@ static int unixDelete(
   int rc = SQLITE_OK;
   UNUSED_PARAMETER(NotUsed);
   SimulateIOError(return SQLITE_IOERR_DELETE);
-  if( osUnlink(zPath)==(-1) && errno!=ENOENT ){
-    return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
+  if( osUnlink(zPath)==(-1) ){
+    if( errno==ENOENT ){
+      rc = SQLITE_IOERR_DELETE_NOENT;
+    }else{
+      rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
+    }
+    return rc;
   }
 #ifndef SQLITE_DISABLE_DIRSYNC
   if( (dirSync & 1)!=0 ){
@@ -29889,6 +30131,66 @@ SQLITE_API int sqlite3_open_file_count = 0;
 /************** End of os_common.h *******************************************/
 /************** Continuing where we left off in os_win.c *********************/
 
+/*
+** Compiling and using WAL mode requires several APIs that are only
+** available in Windows platforms based on the NT kernel.
+*/
+#if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL)
+# error "WAL mode requires support from the Windows NT kernel, compile\
+ with SQLITE_OMIT_WAL."
+#endif
+
+/*
+** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions
+** based on the sub-platform)?
+*/
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+#  define SQLITE_WIN32_HAS_ANSI
+#endif
+
+/*
+** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions
+** based on the sub-platform)?
+*/
+#if SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT
+#  define SQLITE_WIN32_HAS_WIDE
+#endif
+
+/*
+** Do we need to manually define the Win32 file mapping APIs for use with WAL
+** mode (e.g. these APIs are available in the Windows CE SDK; however, they
+** are not present in the header file)?
+*/
+#if SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL)
+/*
+** Two of the file mapping APIs are different under WinRT.  Figure out which
+** set we need.
+*/
+#if SQLITE_OS_WINRT
+WINBASEAPI HANDLE WINAPI CreateFileMappingFromApp(HANDLE, \
+        LPSECURITY_ATTRIBUTES, ULONG, ULONG64, LPCWSTR);
+
+WINBASEAPI LPVOID WINAPI MapViewOfFileFromApp(HANDLE, ULONG, ULONG64, SIZE_T);
+#else
+#if defined(SQLITE_WIN32_HAS_ANSI)
+WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, \
+        DWORD, DWORD, DWORD, LPCSTR);
+#endif /* defined(SQLITE_WIN32_HAS_ANSI) */
+
+#if defined(SQLITE_WIN32_HAS_WIDE)
+WINBASEAPI HANDLE WINAPI CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, \
+        DWORD, DWORD, DWORD, LPCWSTR);
+#endif /* defined(SQLITE_WIN32_HAS_WIDE) */
+
+WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
+#endif /* SQLITE_OS_WINRT */
+
+/*
+** This file mapping API is common to both Win32 and WinRT.
+*/
+WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
+#endif /* SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL) */
+
 /*
 ** Macro to find the minimum of two numeric values.
 */
@@ -30094,14 +30396,6 @@ SQLITE_API int sqlite3_os_type = 0;
 static int sqlite3_os_type = 0;
 #endif
 
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
-#  define SQLITE_WIN32_HAS_ANSI
-#endif
-
-#if SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT
-#  define SQLITE_WIN32_HAS_WIDE
-#endif
-
 #ifndef SYSCALL
 #  define SYSCALL sqlite3_syscall_ptr
 #endif
@@ -30173,6 +30467,16 @@ static struct win_syscall {
 #define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \
         LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent)
 
+#if (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \
+        !defined(SQLITE_OMIT_WAL))
+  { "CreateFileMappingA",      (SYSCALL)CreateFileMappingA,      0 },
+#else
+  { "CreateFileMappingA",      (SYSCALL)0,                       0 },
+#endif
+
+#define osCreateFileMappingA ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
+        DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent)
+
 #if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
         !defined(SQLITE_OMIT_WAL))
   { "CreateFileMappingW",      (SYSCALL)CreateFileMappingW,      0 },
@@ -30181,7 +30485,7 @@ static struct win_syscall {
 #endif
 
 #define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
-        DWORD,DWORD,DWORD,LPCWSTR))aSyscall[6].pCurrent)
+        DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent)
 
 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
   { "CreateMutexW",            (SYSCALL)CreateMutexW,            0 },
@@ -30190,7 +30494,7 @@ static struct win_syscall {
 #endif
 
 #define osCreateMutexW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,BOOL, \
-        LPCWSTR))aSyscall[7].pCurrent)
+        LPCWSTR))aSyscall[8].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_ANSI)
   { "DeleteFileA",             (SYSCALL)DeleteFileA,             0 },
@@ -30198,7 +30502,7 @@ static struct win_syscall {
   { "DeleteFileA",             (SYSCALL)0,                       0 },
 #endif
 
-#define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[8].pCurrent)
+#define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[9].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_WIDE)
   { "DeleteFileW",             (SYSCALL)DeleteFileW,             0 },
@@ -30206,7 +30510,7 @@ static struct win_syscall {
   { "DeleteFileW",             (SYSCALL)0,                       0 },
 #endif
 
-#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[9].pCurrent)
+#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[10].pCurrent)
 
 #if SQLITE_OS_WINCE
   { "FileTimeToLocalFileTime", (SYSCALL)FileTimeToLocalFileTime, 0 },
@@ -30215,7 +30519,7 @@ static struct win_syscall {
 #endif
 
 #define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(CONST FILETIME*, \
-        LPFILETIME))aSyscall[10].pCurrent)
+        LPFILETIME))aSyscall[11].pCurrent)
 
 #if SQLITE_OS_WINCE
   { "FileTimeToSystemTime",    (SYSCALL)FileTimeToSystemTime,    0 },
@@ -30224,11 +30528,11 @@ static struct win_syscall {
 #endif
 
 #define osFileTimeToSystemTime ((BOOL(WINAPI*)(CONST FILETIME*, \
-        LPSYSTEMTIME))aSyscall[11].pCurrent)
+        LPSYSTEMTIME))aSyscall[12].pCurrent)
 
   { "FlushFileBuffers",        (SYSCALL)FlushFileBuffers,        0 },
 
-#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[12].pCurrent)
+#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[13].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_ANSI)
   { "FormatMessageA",          (SYSCALL)FormatMessageA,          0 },
@@ -30237,7 +30541,7 @@ static struct win_syscall {
 #endif
 
 #define osFormatMessageA ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPSTR, \
-        DWORD,va_list*))aSyscall[13].pCurrent)
+        DWORD,va_list*))aSyscall[14].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_WIDE)
   { "FormatMessageW",          (SYSCALL)FormatMessageW,          0 },
@@ -30246,15 +30550,19 @@ static struct win_syscall {
 #endif
 
 #define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \
-        DWORD,va_list*))aSyscall[14].pCurrent)
+        DWORD,va_list*))aSyscall[15].pCurrent)
 
+#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
   { "FreeLibrary",             (SYSCALL)FreeLibrary,             0 },
+#else
+  { "FreeLibrary",             (SYSCALL)0,                       0 },
+#endif
 
-#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[15].pCurrent)
+#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[16].pCurrent)
 
   { "GetCurrentProcessId",     (SYSCALL)GetCurrentProcessId,     0 },
 
-#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[16].pCurrent)
+#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[17].pCurrent)
 
 #if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
   { "GetDiskFreeSpaceA",       (SYSCALL)GetDiskFreeSpaceA,       0 },
@@ -30263,7 +30571,7 @@ static struct win_syscall {
 #endif
 
 #define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \
-        LPDWORD))aSyscall[17].pCurrent)
+        LPDWORD))aSyscall[18].pCurrent)
 
 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
   { "GetDiskFreeSpaceW",       (SYSCALL)GetDiskFreeSpaceW,       0 },
@@ -30272,7 +30580,7 @@ static struct win_syscall {
 #endif
 
 #define osGetDiskFreeSpaceW ((BOOL(WINAPI*)(LPCWSTR,LPDWORD,LPDWORD,LPDWORD, \
-        LPDWORD))aSyscall[18].pCurrent)
+        LPDWORD))aSyscall[19].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_ANSI)
   { "GetFileAttributesA",      (SYSCALL)GetFileAttributesA,      0 },
@@ -30280,7 +30588,7 @@ static struct win_syscall {
   { "GetFileAttributesA",      (SYSCALL)0,                       0 },
 #endif
 
-#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[19].pCurrent)
+#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent)
 
 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
   { "GetFileAttributesW",      (SYSCALL)GetFileAttributesW,      0 },
@@ -30288,7 +30596,7 @@ static struct win_syscall {
   { "GetFileAttributesW",      (SYSCALL)0,                       0 },
 #endif
 
-#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[20].pCurrent)
+#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[21].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_WIDE)
   { "GetFileAttributesExW",    (SYSCALL)GetFileAttributesExW,    0 },
@@ -30297,7 +30605,7 @@ static struct win_syscall {
 #endif
 
 #define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \
-        LPVOID))aSyscall[21].pCurrent)
+        LPVOID))aSyscall[22].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "GetFileSize",             (SYSCALL)GetFileSize,             0 },
@@ -30305,7 +30613,7 @@ static struct win_syscall {
   { "GetFileSize",             (SYSCALL)0,                       0 },
 #endif
 
-#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[22].pCurrent)
+#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent)
 
 #if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
   { "GetFullPathNameA",        (SYSCALL)GetFullPathNameA,        0 },
@@ -30314,7 +30622,7 @@ static struct win_syscall {
 #endif
 
 #define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \
-        LPSTR*))aSyscall[23].pCurrent)
+        LPSTR*))aSyscall[24].pCurrent)
 
 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
   { "GetFullPathNameW",        (SYSCALL)GetFullPathNameW,        0 },
@@ -30323,12 +30631,13 @@ static struct win_syscall {
 #endif
 
 #define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \
-        LPWSTR*))aSyscall[24].pCurrent)
+        LPWSTR*))aSyscall[25].pCurrent)
 
   { "GetLastError",            (SYSCALL)GetLastError,            0 },
 
-#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[25].pCurrent)
+#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent)
 
+#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
 #if SQLITE_OS_WINCE
   /* The GetProcAddressA() routine is only available on Windows CE. */
   { "GetProcAddressA",         (SYSCALL)GetProcAddressA,         0 },
@@ -30337,9 +30646,12 @@ static struct win_syscall {
   ** an ANSI string regardless of the _UNICODE setting */
   { "GetProcAddressA",         (SYSCALL)GetProcAddress,          0 },
 #endif
+#else
+  { "GetProcAddressA",         (SYSCALL)0,                       0 },
+#endif
 
 #define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \
-        LPCSTR))aSyscall[26].pCurrent)
+        LPCSTR))aSyscall[27].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "GetSystemInfo",           (SYSCALL)GetSystemInfo,           0 },
@@ -30347,11 +30659,11 @@ static struct win_syscall {
   { "GetSystemInfo",           (SYSCALL)0,                       0 },
 #endif
 
-#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[27].pCurrent)
+#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent)
 
   { "GetSystemTime",           (SYSCALL)GetSystemTime,           0 },
 
-#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[28].pCurrent)
+#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent)
 
 #if !SQLITE_OS_WINCE
   { "GetSystemTimeAsFileTime", (SYSCALL)GetSystemTimeAsFileTime, 0 },
@@ -30360,7 +30672,7 @@ static struct win_syscall {
 #endif
 
 #define osGetSystemTimeAsFileTime ((VOID(WINAPI*)( \
-        LPFILETIME))aSyscall[29].pCurrent)
+        LPFILETIME))aSyscall[30].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_ANSI)
   { "GetTempPathA",            (SYSCALL)GetTempPathA,            0 },
@@ -30368,7 +30680,7 @@ static struct win_syscall {
   { "GetTempPathA",            (SYSCALL)0,                       0 },
 #endif
 
-#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[30].pCurrent)
+#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent)
 
 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
   { "GetTempPathW",            (SYSCALL)GetTempPathW,            0 },
@@ -30376,7 +30688,7 @@ static struct win_syscall {
   { "GetTempPathW",            (SYSCALL)0,                       0 },
 #endif
 
-#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[31].pCurrent)
+#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "GetTickCount",            (SYSCALL)GetTickCount,            0 },
@@ -30384,7 +30696,7 @@ static struct win_syscall {
   { "GetTickCount",            (SYSCALL)0,                       0 },
 #endif
 
-#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[32].pCurrent)
+#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_ANSI)
   { "GetVersionExA",           (SYSCALL)GetVersionExA,           0 },
@@ -30393,12 +30705,12 @@ static struct win_syscall {
 #endif
 
 #define osGetVersionExA ((BOOL(WINAPI*)( \
-        LPOSVERSIONINFOA))aSyscall[33].pCurrent)
+        LPOSVERSIONINFOA))aSyscall[34].pCurrent)
 
   { "HeapAlloc",               (SYSCALL)HeapAlloc,               0 },
 
 #define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \
-        SIZE_T))aSyscall[34].pCurrent)
+        SIZE_T))aSyscall[35].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "HeapCreate",              (SYSCALL)HeapCreate,              0 },
@@ -30407,7 +30719,7 @@ static struct win_syscall {
 #endif
 
 #define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \
-        SIZE_T))aSyscall[35].pCurrent)
+        SIZE_T))aSyscall[36].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "HeapDestroy",             (SYSCALL)HeapDestroy,             0 },
@@ -30415,21 +30727,21 @@ static struct win_syscall {
   { "HeapDestroy",             (SYSCALL)0,                       0 },
 #endif
 
-#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[36].pCurrent)
+#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[37].pCurrent)
 
   { "HeapFree",                (SYSCALL)HeapFree,                0 },
 
-#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[37].pCurrent)
+#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[38].pCurrent)
 
   { "HeapReAlloc",             (SYSCALL)HeapReAlloc,             0 },
 
 #define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \
-        SIZE_T))aSyscall[38].pCurrent)
+        SIZE_T))aSyscall[39].pCurrent)
 
   { "HeapSize",                (SYSCALL)HeapSize,                0 },
 
 #define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \
-        LPCVOID))aSyscall[39].pCurrent)
+        LPCVOID))aSyscall[40].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "HeapValidate",            (SYSCALL)HeapValidate,            0 },
@@ -30438,23 +30750,24 @@ static struct win_syscall {
 #endif
 
 #define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
-        LPCVOID))aSyscall[40].pCurrent)
+        LPCVOID))aSyscall[41].pCurrent)
 
-#if defined(SQLITE_WIN32_HAS_ANSI)
+#if defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
   { "LoadLibraryA",            (SYSCALL)LoadLibraryA,            0 },
 #else
   { "LoadLibraryA",            (SYSCALL)0,                       0 },
 #endif
 
-#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[41].pCurrent)
+#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[42].pCurrent)
 
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
+        !defined(SQLITE_OMIT_LOAD_EXTENSION)
   { "LoadLibraryW",            (SYSCALL)LoadLibraryW,            0 },
 #else
   { "LoadLibraryW",            (SYSCALL)0,                       0 },
 #endif
 
-#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[42].pCurrent)
+#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[43].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "LocalFree",               (SYSCALL)LocalFree,               0 },
@@ -30462,7 +30775,7 @@ static struct win_syscall {
   { "LocalFree",               (SYSCALL)0,                       0 },
 #endif
 
-#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[43].pCurrent)
+#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[44].pCurrent)
 
 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
   { "LockFile",                (SYSCALL)LockFile,                0 },
@@ -30472,7 +30785,7 @@ static struct win_syscall {
 
 #ifndef osLockFile
 #define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-        DWORD))aSyscall[44].pCurrent)
+        DWORD))aSyscall[45].pCurrent)
 #endif
 
 #if !SQLITE_OS_WINCE
@@ -30483,7 +30796,7 @@ static struct win_syscall {
 
 #ifndef osLockFileEx
 #define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \
-        LPOVERLAPPED))aSyscall[45].pCurrent)
+        LPOVERLAPPED))aSyscall[46].pCurrent)
 #endif
 
 #if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL))
@@ -30493,26 +30806,26 @@ static struct win_syscall {
 #endif
 
 #define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-        SIZE_T))aSyscall[46].pCurrent)
+        SIZE_T))aSyscall[47].pCurrent)
 
   { "MultiByteToWideChar",     (SYSCALL)MultiByteToWideChar,     0 },
 
 #define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \
-        int))aSyscall[47].pCurrent)
+        int))aSyscall[48].pCurrent)
 
   { "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 },
 
 #define osQueryPerformanceCounter ((BOOL(WINAPI*)( \
-        LARGE_INTEGER*))aSyscall[48].pCurrent)
+        LARGE_INTEGER*))aSyscall[49].pCurrent)
 
   { "ReadFile",                (SYSCALL)ReadFile,                0 },
 
 #define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \
-        LPOVERLAPPED))aSyscall[49].pCurrent)
+        LPOVERLAPPED))aSyscall[50].pCurrent)
 
   { "SetEndOfFile",            (SYSCALL)SetEndOfFile,            0 },
 
-#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[50].pCurrent)
+#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[51].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "SetFilePointer",          (SYSCALL)SetFilePointer,          0 },
@@ -30521,7 +30834,7 @@ static struct win_syscall {
 #endif
 
 #define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \
-        DWORD))aSyscall[51].pCurrent)
+        DWORD))aSyscall[52].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "Sleep",                   (SYSCALL)Sleep,                   0 },
@@ -30529,12 +30842,12 @@ static struct win_syscall {
   { "Sleep",                   (SYSCALL)0,                       0 },
 #endif
 
-#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[52].pCurrent)
+#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[53].pCurrent)
 
   { "SystemTimeToFileTime",    (SYSCALL)SystemTimeToFileTime,    0 },
 
 #define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \
-        LPFILETIME))aSyscall[53].pCurrent)
+        LPFILETIME))aSyscall[54].pCurrent)
 
 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
   { "UnlockFile",              (SYSCALL)UnlockFile,              0 },
@@ -30544,7 +30857,7 @@ static struct win_syscall {
 
 #ifndef osUnlockFile
 #define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-        DWORD))aSyscall[54].pCurrent)
+        DWORD))aSyscall[55].pCurrent)
 #endif
 
 #if !SQLITE_OS_WINCE
@@ -30554,7 +30867,7 @@ static struct win_syscall {
 #endif
 
 #define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-        LPOVERLAPPED))aSyscall[55].pCurrent)
+        LPOVERLAPPED))aSyscall[56].pCurrent)
 
 #if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL)
   { "UnmapViewOfFile",         (SYSCALL)UnmapViewOfFile,         0 },
@@ -30562,17 +30875,17 @@ static struct win_syscall {
   { "UnmapViewOfFile",         (SYSCALL)0,                       0 },
 #endif
 
-#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[56].pCurrent)
+#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[57].pCurrent)
 
   { "WideCharToMultiByte",     (SYSCALL)WideCharToMultiByte,     0 },
 
 #define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \
-        LPCSTR,LPBOOL))aSyscall[57].pCurrent)
+        LPCSTR,LPBOOL))aSyscall[58].pCurrent)
 
   { "WriteFile",               (SYSCALL)WriteFile,               0 },
 
 #define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
-        LPOVERLAPPED))aSyscall[58].pCurrent)
+        LPOVERLAPPED))aSyscall[59].pCurrent)
 
 #if SQLITE_OS_WINRT
   { "CreateEventExW",          (SYSCALL)CreateEventExW,          0 },
@@ -30581,7 +30894,7 @@ static struct win_syscall {
 #endif
 
 #define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
-        DWORD,DWORD))aSyscall[59].pCurrent)
+        DWORD,DWORD))aSyscall[60].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "WaitForSingleObject",     (SYSCALL)WaitForSingleObject,     0 },
@@ -30590,7 +30903,7 @@ static struct win_syscall {
 #endif
 
 #define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
-        DWORD))aSyscall[60].pCurrent)
+        DWORD))aSyscall[61].pCurrent)
 
 #if SQLITE_OS_WINRT
   { "WaitForSingleObjectEx",   (SYSCALL)WaitForSingleObjectEx,   0 },
@@ -30599,7 +30912,7 @@ static struct win_syscall {
 #endif
 
 #define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
-        BOOL))aSyscall[61].pCurrent)
+        BOOL))aSyscall[62].pCurrent)
 
 #if SQLITE_OS_WINRT
   { "SetFilePointerEx",        (SYSCALL)SetFilePointerEx,        0 },
@@ -30608,7 +30921,7 @@ static struct win_syscall {
 #endif
 
 #define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
-        PLARGE_INTEGER,DWORD))aSyscall[62].pCurrent)
+        PLARGE_INTEGER,DWORD))aSyscall[63].pCurrent)
 
 #if SQLITE_OS_WINRT
   { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
@@ -30617,7 +30930,7 @@ static struct win_syscall {
 #endif
 
 #define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
-        FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[63].pCurrent)
+        FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[64].pCurrent)
 
 #if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
   { "MapViewOfFileFromApp",    (SYSCALL)MapViewOfFileFromApp,    0 },
@@ -30626,7 +30939,7 @@ static struct win_syscall {
 #endif
 
 #define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \
-        SIZE_T))aSyscall[64].pCurrent)
+        SIZE_T))aSyscall[65].pCurrent)
 
 #if SQLITE_OS_WINRT
   { "CreateFile2",             (SYSCALL)CreateFile2,             0 },
@@ -30635,16 +30948,16 @@ static struct win_syscall {
 #endif
 
 #define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \
-        LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[65].pCurrent)
+        LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[66].pCurrent)
 
-#if SQLITE_OS_WINRT
+#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION)
   { "LoadPackagedLibrary",     (SYSCALL)LoadPackagedLibrary,     0 },
 #else
   { "LoadPackagedLibrary",     (SYSCALL)0,                       0 },
 #endif
 
 #define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \
-        DWORD))aSyscall[66].pCurrent)
+        DWORD))aSyscall[67].pCurrent)
 
 #if SQLITE_OS_WINRT
   { "GetTickCount64",          (SYSCALL)GetTickCount64,          0 },
@@ -30652,7 +30965,7 @@ static struct win_syscall {
   { "GetTickCount64",          (SYSCALL)0,                       0 },
 #endif
 
-#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[67].pCurrent)
+#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[68].pCurrent)
 
 #if SQLITE_OS_WINRT
   { "GetNativeSystemInfo",     (SYSCALL)GetNativeSystemInfo,     0 },
@@ -30661,7 +30974,7 @@ static struct win_syscall {
 #endif
 
 #define osGetNativeSystemInfo ((VOID(WINAPI*)( \
-        LPSYSTEM_INFO))aSyscall[68].pCurrent)
+        LPSYSTEM_INFO))aSyscall[69].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_ANSI)
   { "OutputDebugStringA",      (SYSCALL)OutputDebugStringA,      0 },
@@ -30669,7 +30982,7 @@ static struct win_syscall {
   { "OutputDebugStringA",      (SYSCALL)0,                       0 },
 #endif
 
-#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[69].pCurrent)
+#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[70].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_WIDE)
   { "OutputDebugStringW",      (SYSCALL)OutputDebugStringW,      0 },
@@ -30677,11 +30990,11 @@ static struct win_syscall {
   { "OutputDebugStringW",      (SYSCALL)0,                       0 },
 #endif
 
-#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[70].pCurrent)
+#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[71].pCurrent)
 
   { "GetProcessHeap",          (SYSCALL)GetProcessHeap,          0 },
 
-#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[71].pCurrent)
+#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[72].pCurrent)
 
 #if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
   { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 },
@@ -30690,7 +31003,7 @@ static struct win_syscall {
 #endif
 
 #define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
-        LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[72].pCurrent)
+        LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[73].pCurrent)
 
 }; /* End of the overrideable system calls */
 
@@ -30848,6 +31161,8 @@ SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){
 */
 #if SQLITE_OS_WINCE || SQLITE_OS_WINRT
 # define isNT()  (1)
+#elif !defined(SQLITE_WIN32_HAS_WIDE)
+# define isNT()  (0)
 #else
   static int isNT(void){
     if( sqlite3_os_type==0 ){
@@ -30858,7 +31173,7 @@ SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){
     }
     return sqlite3_os_type==2;
   }
-#endif /* SQLITE_OS_WINCE */
+#endif
 
 #ifdef SQLITE_WIN32_MALLOC
 /*
@@ -31068,7 +31383,7 @@ static LPWSTR utf8ToUnicode(const char *zFilename){
   if( nChar==0 ){
     return 0;
   }
-  zWideFilename = sqlite3_malloc( nChar*sizeof(zWideFilename[0]) );
+  zWideFilename = sqlite3MallocZero( nChar*sizeof(zWideFilename[0]) );
   if( zWideFilename==0 ){
     return 0;
   }
@@ -31093,7 +31408,7 @@ static char *unicodeToUtf8(LPCWSTR zWideFilename){
   if( nByte == 0 ){
     return 0;
   }
-  zFilename = sqlite3_malloc( nByte );
+  zFilename = sqlite3MallocZero( nByte );
   if( zFilename==0 ){
     return 0;
   }
@@ -31123,7 +31438,7 @@ static LPWSTR mbcsToUnicode(const char *zFilename){
   if( nByte==0 ){
     return 0;
   }
-  zMbcsFilename = sqlite3_malloc( nByte*sizeof(zMbcsFilename[0]) );
+  zMbcsFilename = sqlite3MallocZero( nByte*sizeof(zMbcsFilename[0]) );
   if( zMbcsFilename==0 ){
     return 0;
   }
@@ -31152,7 +31467,7 @@ static char *unicodeToMbcs(LPCWSTR zWideFilename){
   if( nByte == 0 ){
     return 0;
   }
-  zFilename = sqlite3_malloc( nByte );
+  zFilename = sqlite3MallocZero( nByte );
   if( zFilename==0 ){
     return 0;
   }
@@ -31984,7 +32299,8 @@ static int winWrite(
         if( retryIoerr(&nRetry, &lastErrno) ) continue;
         break;
       }
-      if( nWrite<=0 ){
+      assert( nWrite==0 || nWrite<=(DWORD)nRem );
+      if( nWrite==0 || nWrite>(DWORD)nRem ){
         lastErrno = osGetLastError();
         break;
       }
@@ -32482,6 +32798,9 @@ static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){
   }
 }
 
+/* Forward declaration */
+static int getTempname(int nBuf, char *zBuf);
+
 /*
 ** Control and query of the open file handle.
 */
@@ -32542,6 +32861,14 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
       }
       return SQLITE_OK;
     }
+    case SQLITE_FCNTL_TEMPFILENAME: {
+      char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
+      if( zTFile ){
+        getTempname(pFile->pVfs->mxPathname, zTFile);
+        *(char**)pArg = zTFile;
+      }
+      return SQLITE_OK;
+    }
   }
   return SQLITE_NOTFOUND;
 }
@@ -32799,16 +33126,14 @@ static int winOpenSharedMemory(winFile *pDbFd){
   /* Allocate space for the new sqlite3_shm object.  Also speculatively
   ** allocate space for a new winShmNode and filename.
   */
-  p = sqlite3_malloc( sizeof(*p) );
+  p = sqlite3MallocZero( sizeof(*p) );
   if( p==0 ) return SQLITE_IOERR_NOMEM;
-  memset(p, 0, sizeof(*p));
   nName = sqlite3Strlen30(pDbFd->zPath);
-  pNew = sqlite3_malloc( sizeof(*pShmNode) + nName + 17 );
+  pNew = sqlite3MallocZero( sizeof(*pShmNode) + nName + 17 );
   if( pNew==0 ){
     sqlite3_free(p);
     return SQLITE_IOERR_NOMEM;
   }
-  memset(pNew, 0, sizeof(*pNew) + nName + 17);
   pNew->zFilename = (char*)&pNew[1];
   sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
   sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename); 
@@ -33145,17 +33470,21 @@ static int winShmMap(
     pShmNode->aRegion = apNew;
 
     while( pShmNode->nRegion<=iRegion ){
-      HANDLE hMap;                /* file-mapping handle */
+      HANDLE hMap = NULL;         /* file-mapping handle */
       void *pMap = 0;             /* Mapped memory region */
      
 #if SQLITE_OS_WINRT
       hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
           NULL, PAGE_READWRITE, nByte, NULL
       );
-#else
+#elif defined(SQLITE_WIN32_HAS_WIDE)
       hMap = osCreateFileMappingW(pShmNode->hFile.h, 
           NULL, PAGE_READWRITE, 0, nByte, NULL
       );
+#elif defined(SQLITE_WIN32_HAS_ANSI)
+      hMap = osCreateFileMappingA(pShmNode->hFile.h, 
+          NULL, PAGE_READWRITE, 0, nByte, NULL
+      );
 #endif
       OSTRACE(("SHM-MAP pid-%d create region=%d nbyte=%d %s\n",
                (int)osGetCurrentProcessId(), pShmNode->nRegion, nByte,
@@ -33677,14 +34006,24 @@ static int winDelete(
                                   &sAttrData) ){
         attr = sAttrData.dwFileAttributes;
       }else{
-        rc = SQLITE_OK; /* Already gone? */
+        lastErrno = osGetLastError();
+        if( lastErrno==ERROR_FILE_NOT_FOUND || lastErrno==ERROR_PATH_NOT_FOUND ){
+          rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
+        }else{
+          rc = SQLITE_ERROR;
+        }
         break;
       }
 #else
       attr = osGetFileAttributesW(zConverted);
 #endif
       if ( attr==INVALID_FILE_ATTRIBUTES ){
-        rc = SQLITE_OK; /* Already gone? */
+        lastErrno = osGetLastError();
+        if( lastErrno==ERROR_FILE_NOT_FOUND || lastErrno==ERROR_PATH_NOT_FOUND ){
+          rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
+        }else{
+          rc = SQLITE_ERROR;
+        }
         break;
       }
       if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
@@ -33706,7 +34045,12 @@ static int winDelete(
     do {
       attr = osGetFileAttributesA(zConverted);
       if ( attr==INVALID_FILE_ATTRIBUTES ){
-        rc = SQLITE_OK; /* Already gone? */
+        lastErrno = osGetLastError();
+        if( lastErrno==ERROR_FILE_NOT_FOUND || lastErrno==ERROR_PATH_NOT_FOUND ){
+          rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
+        }else{
+          rc = SQLITE_ERROR;
+        }
         break;
       }
       if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
@@ -33724,7 +34068,7 @@ static int winDelete(
     } while(1);
   }
 #endif
-  if( rc ){
+  if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){
     rc = winLogError(SQLITE_IOERR_DELETE, lastErrno,
              "winDelete", zFilename);
   }else{
@@ -33904,7 +34248,7 @@ static int winFullPathname(
 #endif
 
 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__)
-  int nByte;
+  DWORD nByte;
   void *zConverted;
   char *zOut;
 
@@ -33938,13 +34282,27 @@ static int winFullPathname(
   }
   if( isNT() ){
     LPWSTR zTemp;
-    nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0) + 3;
-    zTemp = sqlite3_malloc( nByte*sizeof(zTemp[0]) );
+    nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0);
+    if( nByte==0 ){
+      winLogError(SQLITE_ERROR, osGetLastError(),
+                  "GetFullPathNameW1", zConverted);
+      sqlite3_free(zConverted);
+      return SQLITE_CANTOPEN_FULLPATH;
+    }
+    nByte += 3;
+    zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
     if( zTemp==0 ){
       sqlite3_free(zConverted);
       return SQLITE_IOERR_NOMEM;
     }
-    osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0);
+    nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0);
+    if( nByte==0 ){
+      winLogError(SQLITE_ERROR, osGetLastError(),
+                  "GetFullPathNameW2", zConverted);
+      sqlite3_free(zConverted);
+      sqlite3_free(zTemp);
+      return SQLITE_CANTOPEN_FULLPATH;
+    }
     sqlite3_free(zConverted);
     zOut = unicodeToUtf8(zTemp);
     sqlite3_free(zTemp);
@@ -33952,13 +34310,27 @@ static int winFullPathname(
 #ifdef SQLITE_WIN32_HAS_ANSI
   else{
     char *zTemp;
-    nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0) + 3;
-    zTemp = sqlite3_malloc( nByte*sizeof(zTemp[0]) );
+    nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0);
+    if( nByte==0 ){
+      winLogError(SQLITE_ERROR, osGetLastError(),
+                  "GetFullPathNameA1", zConverted);
+      sqlite3_free(zConverted);
+      return SQLITE_CANTOPEN_FULLPATH;
+    }
+    nByte += 3;
+    zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
     if( zTemp==0 ){
       sqlite3_free(zConverted);
       return SQLITE_IOERR_NOMEM;
     }
-    osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
+    nByte = osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
+    if( nByte==0 ){
+      winLogError(SQLITE_ERROR, osGetLastError(),
+                  "GetFullPathNameA2", zConverted);
+      sqlite3_free(zConverted);
+      sqlite3_free(zTemp);
+      return SQLITE_CANTOPEN_FULLPATH;
+    }
     sqlite3_free(zConverted);
     zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
     sqlite3_free(zTemp);
@@ -34216,7 +34588,7 @@ SQLITE_API int sqlite3_os_init(void){
 
   /* Double-check that the aSyscall[] array has been constructed
   ** correctly.  See ticket [bb3a86e890c8e96ab] */
-  assert( ArraySize(aSyscall)==73 );
+  assert( ArraySize(aSyscall)==74 );
 
 #ifndef SQLITE_OMIT_WAL
   /* get memory map allocation granularity */
@@ -34235,7 +34607,7 @@ SQLITE_API int sqlite3_os_init(void){
 
 SQLITE_API int sqlite3_os_end(void){ 
 #if SQLITE_OS_WINRT
-  if( sleepObj != NULL ){
+  if( sleepObj!=NULL ){
     osCloseHandle(sleepObj);
     sleepObj = NULL;
   }
@@ -38890,12 +39262,13 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
       ** file should be closed and deleted. If this connection writes to
       ** the database file, it will do so using an in-memory journal. 
       */
+      int bDelete = (!pPager->tempFile && sqlite3JournalExists(pPager->jfd));
       assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE 
            || pPager->journalMode==PAGER_JOURNALMODE_MEMORY 
            || pPager->journalMode==PAGER_JOURNALMODE_WAL 
       );
       sqlite3OsClose(pPager->jfd);
-      if( !pPager->tempFile ){
+      if( bDelete ){
         rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
       }
     }
@@ -39458,6 +39831,21 @@ static int pager_truncate(Pager *pPager, Pgno nPage){
   return rc;
 }
 
+/*
+** Return a sanitized version of the sector-size of OS file pFile. The
+** return value is guaranteed to lie between 32 and MAX_SECTOR_SIZE.
+*/
+SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *pFile){
+  int iRet = sqlite3OsSectorSize(pFile);
+  if( iRet<32 ){
+    iRet = 512;
+  }else if( iRet>MAX_SECTOR_SIZE ){
+    assert( MAX_SECTOR_SIZE>=512 );
+    iRet = MAX_SECTOR_SIZE;
+  }
+  return iRet;
+}
+
 /*
 ** Set the value of the Pager.sectorSize variable for the given
 ** pager based on the value returned by the xSectorSize method
@@ -39493,14 +39881,7 @@ static void setSectorSize(Pager *pPager){
     ** call will segfault. */
     pPager->sectorSize = 512;
   }else{
-    pPager->sectorSize = sqlite3OsSectorSize(pPager->fd);
-    if( pPager->sectorSize<32 ){
-      pPager->sectorSize = 512;
-    }
-    if( pPager->sectorSize>MAX_SECTOR_SIZE ){
-      assert( MAX_SECTOR_SIZE>=512 );
-      pPager->sectorSize = MAX_SECTOR_SIZE;
-    }
+    pPager->sectorSize = sqlite3SectorSize(pPager->fd);
   }
 }
 
@@ -40100,6 +40481,7 @@ static int pagerOpenWalIfPresent(Pager *pPager){
     if( rc ) return rc;
     if( nPage==0 ){
       rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
+      if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK;
       isWal = 0;
     }else{
       rc = sqlite3OsAccess(
@@ -40417,9 +40799,16 @@ SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(
   Pager *pPager,                       /* Pager object */
   int (*xBusyHandler)(void *),         /* Pointer to busy-handler function */
   void *pBusyHandlerArg                /* Argument to pass to xBusyHandler */
-){  
+){
   pPager->xBusyHandler = xBusyHandler;
   pPager->pBusyHandlerArg = pBusyHandlerArg;
+
+  if( isOpen(pPager->fd) ){
+    void **ap = (void **)&pPager->xBusyHandler;
+    assert( ((int(*)(void *))(ap[0]))==xBusyHandler );
+    assert( ap[1]==pBusyHandlerArg );
+    sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap);
+  }
 }
 
 /*
@@ -41397,7 +41786,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
     memcpy(pPager->zFilename, zPathname, nPathname);
     if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
     memcpy(pPager->zJournal, zPathname, nPathname);
-    memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+1);
+    memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+2);
     sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal);
 #ifndef SQLITE_OMIT_WAL
     pPager->zWal = &pPager->zJournal[nPathname+8+1];
@@ -42599,7 +42988,7 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
 # define DIRECT_MODE isDirectMode
 #endif
 
-  if( !pPager->changeCountDone && pPager->dbSize>0 ){
+  if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){
     PgHdr *pPgHdr;                /* Reference to page 1 */
 
     assert( !pPager->tempFile && isOpen(pPager->fd) );
@@ -42819,7 +43208,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
   
       /* If this transaction has made the database smaller, then all pages
       ** being discarded by the truncation must be written to the journal
-      ** file. This can only happen in auto-vacuum mode.
+      ** file.
       **
       ** Before reading the pages with page numbers larger than the 
       ** current value of Pager.dbSize, set dbSize back to the value
@@ -42827,7 +43216,6 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
       ** calls to sqlite3PagerGet() return zeroed pages instead of 
       ** reading data from the database file.
       */
-  #ifndef SQLITE_OMIT_AUTOVACUUM
       if( pPager->dbSize<pPager->dbOrigSize 
        && pPager->journalMode!=PAGER_JOURNALMODE_OFF
       ){
@@ -42847,7 +43235,6 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
         }
         pPager->dbSize = dbSize;
       } 
-  #endif
   
       /* Write the master journal name into the journal file. If a master 
       ** journal file name has already been written to the journal file, 
@@ -43850,6 +44237,8 @@ SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){
   return rc;
 }
 
+#endif /* !SQLITE_OMIT_WAL */
+
 #ifdef SQLITE_ENABLE_ZIPVFS
 /*
 ** A read-lock must be held on the pager when this function is called. If
@@ -43879,8 +44268,6 @@ SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){
 }
 #endif /* SQLITE_HAS_CODEC */
 
-#endif /* !SQLITE_OMIT_WAL */
-
 #endif /* SQLITE_OMIT_DISKIO */
 
 /************** End of pager.c ***********************************************/
@@ -46404,7 +46791,7 @@ SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *p
       assert( walFramePgno(pWal, iFrame)!=1 );
       rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame));
     }
-    walCleanupHash(pWal);
+    if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal);
   }
   assert( rc==SQLITE_OK );
   return rc;
@@ -46714,7 +47101,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
   */
   if( isCommit && (sync_flags & WAL_SYNC_TRANSACTIONS)!=0 ){
     if( pWal->padToSectorBoundary ){
-      int sectorSize = sqlite3OsSectorSize(pWal->pWalFd);
+      int sectorSize = sqlite3SectorSize(pWal->pWalFd);
       w.iSyncPoint = ((iOffset+sectorSize-1)/sectorSize)*sectorSize;
       while( iOffset<w.iSyncPoint ){
         rc = walWriteOneFrame(&w, pLast, nTruncate, iOffset);
@@ -50127,6 +50514,24 @@ SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree *p){
   return p->pBt->pageSize;
 }
 
+#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_DEBUG)
+/*
+** This function is similar to sqlite3BtreeGetReserve(), except that it
+** may only be called if it is guaranteed that the b-tree mutex is already
+** held.
+**
+** This is useful in one special case in the backup API code where it is
+** known that the shared b-tree mutex is held, but the mutex on the 
+** database handle that owns *p is not. In this case if sqlite3BtreeEnter()
+** were to be called, it might collide with some other operation on the
+** database handle that owns *p, causing undefined behaviour.
+*/
+SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p){
+  assert( sqlite3_mutex_held(p->pBt->mutex) );
+  return p->pBt->pageSize - p->pBt->usableSize;
+}
+#endif /* SQLITE_HAS_CODEC || SQLITE_DEBUG */
+
 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM)
 /*
 ** Return the number of bytes of space at the end of every page that
@@ -50440,6 +50845,20 @@ static int newDatabase(BtShared *pBt){
   return SQLITE_OK;
 }
 
+/*
+** Initialize the first page of the database file (creating a database
+** consisting of a single page and no schema objects). Return SQLITE_OK
+** if successful, or an SQLite error code otherwise.
+*/
+SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p){
+  int rc;
+  sqlite3BtreeEnter(p);
+  p->pBt->nPage = 0;
+  rc = newDatabase(p->pBt);
+  sqlite3BtreeLeave(p);
+  return rc;
+}
+
 /*
 ** Attempt to start a new transaction. A write-transaction
 ** is started if the second argument is nonzero, otherwise a read-
@@ -53183,7 +53602,7 @@ static int clearCell(MemPage *pPage, unsigned char *pCell){
     return SQLITE_OK;  /* No overflow pages. Return without doing anything */
   }
   if( pCell+info.iOverflow+3 > pPage->aData+pPage->maskPage ){
-    return SQLITE_CORRUPT;  /* Cell extends past end of page */
+    return SQLITE_CORRUPT_BKPT;  /* Cell extends past end of page */
   }
   ovflPgno = get4byte(&pCell[info.iOverflow]);
   assert( pBt->usableSize > 4 );
@@ -53639,7 +54058,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
   assert( pPage->nOverflow==1 );
 
   /* This error condition is now caught prior to reaching this function */
-  if( pPage->nCell<=0 ) return SQLITE_CORRUPT_BKPT;
+  if( pPage->nCell==0 ) return SQLITE_CORRUPT_BKPT;
 
   /* Allocate a new page. This page will become the right-sibling of 
   ** pPage. Make the parent page writable, so that the new divider cell
@@ -56463,13 +56882,16 @@ static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){
   const int nCopy = MIN(nSrcPgsz, nDestPgsz);
   const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
 #ifdef SQLITE_HAS_CODEC
-  int nSrcReserve = sqlite3BtreeGetReserve(p->pSrc);
+  /* Use BtreeGetReserveNoMutex() for the source b-tree, as although it is
+  ** guaranteed that the shared-mutex is held by this thread, handle
+  ** p->pSrc may not actually be the owner.  */
+  int nSrcReserve = sqlite3BtreeGetReserveNoMutex(p->pSrc);
   int nDestReserve = sqlite3BtreeGetReserve(p->pDest);
 #endif
-
   int rc = SQLITE_OK;
   i64 iOff;
 
+  assert( sqlite3BtreeGetReserveNoMutex(p->pSrc)>=0 );
   assert( p->bDestLocked );
   assert( !isFatalError(p->rc) );
   assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) );
@@ -56654,7 +57076,13 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
     ** same schema version.
     */
     if( rc==SQLITE_DONE ){
-      rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
+      if( nSrcPage==0 ){
+        rc = sqlite3BtreeNewDb(p->pDest);
+        nSrcPage = 1;
+      }
+      if( rc==SQLITE_OK || rc==SQLITE_DONE ){
+        rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
+      }
       if( rc==SQLITE_OK ){
         if( p->pDestDb ){
           sqlite3ResetAllSchemasOfConnection(p->pDestDb);
@@ -56688,6 +57116,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
         }else{
           nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
         }
+        assert( nDestTruncate>0 );
         sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
 
         if( pgszSrc<pgszDest ){
@@ -56706,7 +57135,8 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
           i64 iEnd;
 
           assert( pFile );
-          assert( (i64)nDestTruncate*(i64)pgszDest >= iSize || (
+          assert( nDestTruncate==0 
+              || (i64)nDestTruncate*(i64)pgszDest >= iSize || (
                 nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
              && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
           ));
@@ -58176,7 +58606,7 @@ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3 *db){
 SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){
   assert( isPrepareV2==1 || isPrepareV2==0 );
   if( p==0 ) return;
-#ifdef SQLITE_OMIT_TRACE
+#if defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_ENABLE_SQLLOG)
   if( !isPrepareV2 ) return;
 #endif
   assert( p->zSql==0 );
@@ -58846,6 +59276,7 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int
     addr = p->nOp - 1;
   }
   pOp = &p->aOp[addr];
+  assert( pOp->p4type==P4_NOTUSED || pOp->p4type==P4_INT32 );
   freeP4(db, pOp->p4type, pOp->p4.p);
   pOp->p4.p = 0;
   if( n==P4_INT32 ){
@@ -58868,10 +59299,9 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int
       u8 *aSortOrder;
       memcpy((char*)pKeyInfo, zP4, nByte - nField);
       aSortOrder = pKeyInfo->aSortOrder;
-      if( aSortOrder ){
-        pKeyInfo->aSortOrder = (unsigned char*)&pKeyInfo->aColl[nField];
-        memcpy(pKeyInfo->aSortOrder, aSortOrder, nField);
-      }
+      assert( aSortOrder!=0 );
+      pKeyInfo->aSortOrder = (unsigned char*)&pKeyInfo->aColl[nField];
+      memcpy(pKeyInfo->aSortOrder, aSortOrder, nField);
       pOp->p4type = P4_KEYINFO;
     }else{
       p->db->mallocFailed = 1;
@@ -58984,26 +59414,23 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
     case P4_KEYINFO: {
       int i, j;
       KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
+      assert( pKeyInfo->aSortOrder!=0 );
       sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField);
       i = sqlite3Strlen30(zTemp);
       for(j=0; j<pKeyInfo->nField; j++){
         CollSeq *pColl = pKeyInfo->aColl[j];
-        if( pColl ){
-          int n = sqlite3Strlen30(pColl->zName);
-          if( i+n>nTemp-6 ){
-            memcpy(&zTemp[i],",...",4);
-            break;
-          }
-          zTemp[i++] = ',';
-          if( pKeyInfo->aSortOrder && pKeyInfo->aSortOrder[j] ){
-            zTemp[i++] = '-';
-          }
-          memcpy(&zTemp[i], pColl->zName,n+1);
-          i += n;
-        }else if( i+4<nTemp-6 ){
-          memcpy(&zTemp[i],",nil",4);
-          i += 4;
+        const char *zColl = pColl ? pColl->zName : "nil";
+        int n = sqlite3Strlen30(zColl);
+        if( i+n>nTemp-6 ){
+          memcpy(&zTemp[i],",...",4);
+          break;
+        }
+        zTemp[i++] = ',';
+        if( pKeyInfo->aSortOrder[j] ){
+          zTemp[i++] = '-';
         }
+        memcpy(&zTemp[i], zColl, n+1);
+        i += n;
       }
       zTemp[i++] = ')';
       zTemp[i] = 0;
@@ -59893,7 +60320,9 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
     if( sqlite3BtreeIsInTrans(pBt) ){
       needXcommit = 1;
       if( i!=1 ) nTrans++;
+      sqlite3BtreeEnter(pBt);
       rc = sqlite3PagerExclusiveLock(sqlite3BtreePager(pBt));
+      sqlite3BtreeLeave(pBt);
     }
   }
   if( rc!=SQLITE_OK ){
@@ -60447,6 +60876,27 @@ SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){
   return rc;
 }
 
+#ifdef SQLITE_ENABLE_SQLLOG
+/*
+** If an SQLITE_CONFIG_SQLLOG hook is registered and the VM has been run, 
+** invoke it.
+*/
+static void vdbeInvokeSqllog(Vdbe *v){
+  if( sqlite3GlobalConfig.xSqllog && v->rc==SQLITE_OK && v->zSql && v->pc>=0 ){
+    char *zExpanded = sqlite3VdbeExpandSql(v, v->zSql);
+    assert( v->db->init.busy==0 );
+    if( zExpanded ){
+      sqlite3GlobalConfig.xSqllog(
+          sqlite3GlobalConfig.pSqllogArg, v->db, zExpanded, 1
+      );
+      sqlite3DbFree(v->db, zExpanded);
+    }
+  }
+}
+#else
+# define vdbeInvokeSqllog(x)
+#endif
+
 /*
 ** Clean up a VDBE after execution but do not delete the VDBE just yet.
 ** Write any error messages into *pzErrMsg.  Return the result code.
@@ -60474,6 +60924,7 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
   ** instructions yet, leave the main database error information unchanged.
   */
   if( p->pc>=0 ){
+    vdbeInvokeSqllog(p);
     sqlite3VdbeTransferError(p);
     sqlite3DbFree(db, p->zErrMsg);
     p->zErrMsg = 0;
@@ -60555,12 +61006,14 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){
 }
 
 /*
-** Free all memory associated with the Vdbe passed as the second argument.
+** Free all memory associated with the Vdbe passed as the second argument,
+** except for object itself, which is preserved.
+**
 ** The difference between this function and sqlite3VdbeDelete() is that
 ** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with
-** the database connection.
+** the database connection and frees the object itself.
 */
-SQLITE_PRIVATE void sqlite3VdbeDeleteObject(sqlite3 *db, Vdbe *p){
+SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
   SubProgram *pSub, *pNext;
   int i;
   assert( p->db==0 || p->db==db );
@@ -60578,10 +61031,9 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteObject(sqlite3 *db, Vdbe *p){
   sqlite3DbFree(db, p->zSql);
   sqlite3DbFree(db, p->pFree);
 #if defined(SQLITE_ENABLE_TREE_EXPLAIN)
-  sqlite3DbFree(db, p->zExplain);
+  sqlite3_free(p->zExplain);
   sqlite3DbFree(db, p->pExplain);
 #endif
-  sqlite3DbFree(db, p);
 }
 
 /*
@@ -60593,6 +61045,7 @@ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
   if( NEVER(p==0) ) return;
   db = p->db;
   assert( sqlite3_mutex_held(db->mutex) );
+  sqlite3VdbeClearObject(db, p);
   if( p->pPrev ){
     p->pPrev->pNext = p->pNext;
   }else{
@@ -60604,7 +61057,7 @@ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
   }
   p->magic = VDBE_MAGIC_DEAD;
   p->db = 0;
-  sqlite3VdbeDeleteObject(db, p);
+  sqlite3DbFree(db, p);
 }
 
 /*
@@ -60706,9 +61159,6 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
 #   define MAX_6BYTE ((((i64)0x00008000)<<32)-1)
     i64 i = pMem->u.i;
     u64 u;
-    if( file_format>=4 && (i&1)==i ){
-      return 8+(u32)i;
-    }
     if( i<0 ){
       if( i<(-MAX_6BYTE) ) return 6;
       /* Previous test prevents:  u = -(-9223372036854775808) */
@@ -60716,7 +61166,9 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
     }else{
       u = i;
     }
-    if( u<=127 ) return 1;
+    if( u<=127 ){
+      return ((i&1)==i && file_format>=4) ? 8+(u32)u : 1;
+    }
     if( u<=32767 ) return 2;
     if( u<=8388607 ) return 3;
     if( u<=2147483647 ) return 4;
@@ -61001,6 +61453,7 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
   }
 
   p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
+  assert( pKeyInfo->aSortOrder!=0 );
   p->pKeyInfo = pKeyInfo;
   p->nField = pKeyInfo->nField + 1;
   return p;
@@ -61094,6 +61547,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
   idx1 = getVarint32(aKey1, szHdr1);
   d1 = szHdr1;
   nField = pKeyInfo->nField;
+  assert( pKeyInfo->aSortOrder!=0 );
   while( idx1<szHdr1 && i<pPKey2->nField ){
     u32 serial_type1;
 
@@ -61113,7 +61567,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
       assert( mem1.zMalloc==0 );  /* See comment below */
 
       /* Invert the result if we are using DESC sort order. */
-      if( pKeyInfo->aSortOrder && i<nField && pKeyInfo->aSortOrder[i] ){
+      if( i<nField && pKeyInfo->aSortOrder[i] ){
         rc = -rc;
       }
     
@@ -61839,10 +62293,12 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
   }
   db = v->db;
   sqlite3_mutex_enter(db->mutex);
+  v->doingRerun = 0;
   while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
          && cnt++ < SQLITE_MAX_SCHEMA_RETRY
          && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
     sqlite3_reset(pStmt);
+    v->doingRerun = 1;
     assert( v->expired==0 );
   }
   if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
@@ -63364,7 +63820,9 @@ SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
 ** Print the value of a register for tracing purposes:
 */
 static void memTracePrint(FILE *out, Mem *p){
-  if( p->flags & MEM_Null ){
+  if( p->flags & MEM_Invalid ){
+    fprintf(out, " undefined");
+  }else if( p->flags & MEM_Null ){
     fprintf(out, " NULL");
   }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
     fprintf(out, " si:%lld", p->u.i);
@@ -63615,6 +64073,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
     } aa;
     struct OP_Null_stack_vars {
       int cnt;
+      u16 nullFlag;
     } ab;
     struct OP_Variable_stack_vars {
       Mem *pVar;       /* Value being transferred */
@@ -63625,39 +64084,43 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       int p1;          /* Register to copy from */
       int p2;          /* Register to copy to */
     } ad;
+    struct OP_Copy_stack_vars {
+      int n;
+    } ae;
     struct OP_ResultRow_stack_vars {
       Mem *pMem;
       int i;
-    } ae;
+    } af;
     struct OP_Concat_stack_vars {
       i64 nByte;
-    } af;
+    } ag;
     struct OP_Remainder_stack_vars {
+      char bIntint;   /* Started out as two integer operands */
       int flags;      /* Combined MEM_* flags from both inputs */
       i64 iA;         /* Integer value of left operand */
       i64 iB;         /* Integer value of right operand */
       double rA;      /* Real value of left operand */
       double rB;      /* Real value of right operand */
-    } ag;
+    } ah;
     struct OP_Function_stack_vars {
       int i;
       Mem *pArg;
       sqlite3_context ctx;
       sqlite3_value **apVal;
       int n;
-    } ah;
+    } ai;
     struct OP_ShiftRight_stack_vars {
       i64 iA;
       u64 uA;
       i64 iB;
       u8 op;
-    } ai;
+    } aj;
     struct OP_Ge_stack_vars {
       int res;            /* Result of the comparison of pIn1 against pIn3 */
       char affinity;      /* Affinity to use for comparison */
       u16 flags1;         /* Copy of initial value of pIn1->flags */
       u16 flags3;         /* Copy of initial value of pIn3->flags */
-    } aj;
+    } ak;
     struct OP_Compare_stack_vars {
       int n;
       int i;
@@ -63667,14 +64130,14 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       int idx;
       CollSeq *pColl;    /* Collating sequence to use on this term */
       int bRev;          /* True for DESCENDING sort order */
-    } ak;
+    } al;
     struct OP_Or_stack_vars {
       int v1;    /* Left operand:  0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
       int v2;    /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
-    } al;
+    } am;
     struct OP_IfNot_stack_vars {
       int c;
-    } am;
+    } an;
     struct OP_Column_stack_vars {
       u32 payloadSize;   /* Number of bytes in the record */
       i64 payloadSize64; /* Number of bytes in the record */
@@ -63699,11 +64162,11 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       int avail;         /* Number of bytes of available data */
       u32 t;             /* A type code from the record header */
       Mem *pReg;         /* PseudoTable input register */
-    } an;
+    } ao;
     struct OP_Affinity_stack_vars {
       const char *zAffinity;   /* The affinity to be applied */
       char cAff;               /* A single character of affinity */
-    } ao;
+    } ap;
     struct OP_MakeRecord_stack_vars {
       u8 *zNewRecord;        /* A buffer to hold the data for the new record */
       Mem *pRec;             /* The new record */
@@ -63720,11 +64183,11 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       int file_format;       /* File format to use for encoding */
       int i;                 /* Space used in zNewRecord[] */
       int len;               /* Length of a field */
-    } ap;
+    } aq;
     struct OP_Count_stack_vars {
       i64 nEntry;
       BtCursor *pCrsr;
-    } aq;
+    } ar;
     struct OP_Savepoint_stack_vars {
       int p1;                         /* Value of P1 operand */
       char *zName;                    /* Name of savepoint */
@@ -63734,28 +64197,28 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       Savepoint *pTmp;
       int iSavepoint;
       int ii;
-    } ar;
+    } as;
     struct OP_AutoCommit_stack_vars {
       int desiredAutoCommit;
       int iRollback;
       int turnOnAC;
-    } as;
+    } at;
     struct OP_Transaction_stack_vars {
       Btree *pBt;
-    } at;
+    } au;
     struct OP_ReadCookie_stack_vars {
       int iMeta;
       int iDb;
       int iCookie;
-    } au;
+    } av;
     struct OP_SetCookie_stack_vars {
       Db *pDb;
-    } av;
+    } aw;
     struct OP_VerifyCookie_stack_vars {
       int iMeta;
       int iGen;
       Btree *pBt;
-    } aw;
+    } ax;
     struct OP_OpenWrite_stack_vars {
       int nField;
       KeyInfo *pKeyInfo;
@@ -63765,16 +64228,16 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       Btree *pX;
       VdbeCursor *pCur;
       Db *pDb;
-    } ax;
+    } ay;
     struct OP_OpenEphemeral_stack_vars {
       VdbeCursor *pCx;
-    } ay;
+    } az;
     struct OP_SorterOpen_stack_vars {
       VdbeCursor *pCx;
-    } az;
+    } ba;
     struct OP_OpenPseudo_stack_vars {
       VdbeCursor *pCx;
-    } ba;
+    } bb;
     struct OP_SeekGt_stack_vars {
       int res;
       int oc;
@@ -63782,10 +64245,10 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       UnpackedRecord r;
       int nField;
       i64 iKey;      /* The rowid we are to seek to */
-    } bb;
+    } bc;
     struct OP_Seek_stack_vars {
       VdbeCursor *pC;
-    } bc;
+    } bd;
     struct OP_Found_stack_vars {
       int alreadyExists;
       VdbeCursor *pC;
@@ -63794,7 +64257,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       UnpackedRecord *pIdxKey;
       UnpackedRecord r;
       char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
-    } bd;
+    } be;
     struct OP_IsUnique_stack_vars {
       u16 ii;
       VdbeCursor *pCx;
@@ -63803,13 +64266,13 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       Mem *aMx;
       UnpackedRecord r;                  /* B-Tree index search key */
       i64 R;                             /* Rowid stored in register P3 */
-    } be;
+    } bf;
     struct OP_NotExists_stack_vars {
       VdbeCursor *pC;
       BtCursor *pCrsr;
       int res;
       u64 iKey;
-    } bf;
+    } bg;
     struct OP_NewRowid_stack_vars {
       i64 v;                 /* The new rowid */
       VdbeCursor *pC;        /* Cursor of table to get the new rowid */
@@ -63817,7 +64280,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       int cnt;               /* Counter to limit the number of searches */
       Mem *pMem;             /* Register holding largest rowid for AUTOINCREMENT */
       VdbeFrame *pFrame;     /* Root frame of VDBE */
-    } bg;
+    } bh;
     struct OP_InsertInt_stack_vars {
       Mem *pData;       /* MEM cell holding data for the record to be inserted */
       Mem *pKey;        /* MEM cell holding key  for the record */
@@ -63828,89 +64291,89 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       const char *zDb;  /* database name - used by the update hook */
       const char *zTbl; /* Table name - used by the opdate hook */
       int op;           /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
-    } bh;
+    } bi;
     struct OP_Delete_stack_vars {
       i64 iKey;
       VdbeCursor *pC;
-    } bi;
+    } bj;
     struct OP_SorterCompare_stack_vars {
       VdbeCursor *pC;
       int res;
-    } bj;
+    } bk;
     struct OP_SorterData_stack_vars {
       VdbeCursor *pC;
-    } bk;
+    } bl;
     struct OP_RowData_stack_vars {
       VdbeCursor *pC;
       BtCursor *pCrsr;
       u32 n;
       i64 n64;
-    } bl;
+    } bm;
     struct OP_Rowid_stack_vars {
       VdbeCursor *pC;
       i64 v;
       sqlite3_vtab *pVtab;
       const sqlite3_module *pModule;
-    } bm;
+    } bn;
     struct OP_NullRow_stack_vars {
       VdbeCursor *pC;
-    } bn;
+    } bo;
     struct OP_Last_stack_vars {
       VdbeCursor *pC;
       BtCursor *pCrsr;
       int res;
-    } bo;
+    } bp;
     struct OP_Rewind_stack_vars {
       VdbeCursor *pC;
       BtCursor *pCrsr;
       int res;
-    } bp;
+    } bq;
     struct OP_Next_stack_vars {
       VdbeCursor *pC;
       int res;
-    } bq;
+    } br;
     struct OP_IdxInsert_stack_vars {
       VdbeCursor *pC;
       BtCursor *pCrsr;
       int nKey;
       const char *zKey;
-    } br;
+    } bs;
     struct OP_IdxDelete_stack_vars {
       VdbeCursor *pC;
       BtCursor *pCrsr;
       int res;
       UnpackedRecord r;
-    } bs;
+    } bt;
     struct OP_IdxRowid_stack_vars {
       BtCursor *pCrsr;
       VdbeCursor *pC;
       i64 rowid;
-    } bt;
+    } bu;
     struct OP_IdxGE_stack_vars {
       VdbeCursor *pC;
       int res;
       UnpackedRecord r;
-    } bu;
+    } bv;
     struct OP_Destroy_stack_vars {
       int iMoved;
       int iCnt;
       Vdbe *pVdbe;
       int iDb;
-    } bv;
+    } bw;
     struct OP_Clear_stack_vars {
       int nChange;
-    } bw;
+    } bx;
     struct OP_CreateTable_stack_vars {
       int pgno;
       int flags;
       Db *pDb;
-    } bx;
+    } by;
     struct OP_ParseSchema_stack_vars {
       int iDb;
       const char *zMaster;
       char *zSql;
       InitData initData;
-    } by;
+    } bz;
     struct OP_IntegrityCk_stack_vars {
       int nRoot;      /* Number of tables to check.  (Number of root pages.) */
       int *aRoot;     /* Array of rootpage numbers for tables to be checked */
@@ -63918,14 +64381,14 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       int nErr;       /* Number of errors reported */
       char *z;        /* Text of the error report */
       Mem *pnErr;     /* Register keeping track of errors remaining */
-    } bz;
+    } ca;
     struct OP_RowSetRead_stack_vars {
       i64 val;
-    } ca;
+    } cb;
     struct OP_RowSetTest_stack_vars {
       int iSet;
       int exists;
-    } cb;
+    } cc;
     struct OP_Program_stack_vars {
       int nMem;               /* Number of memory registers for sub-program */
       int nByte;              /* Bytes of runtime space required for sub-program */
@@ -63935,15 +64398,15 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       VdbeFrame *pFrame;      /* New vdbe frame to execute in */
       SubProgram *pProgram;   /* Sub-program to execute */
       void *t;                /* Token identifying trigger */
-    } cc;
+    } cd;
     struct OP_Param_stack_vars {
       VdbeFrame *pFrame;
       Mem *pIn;
-    } cd;
+    } ce;
     struct OP_MemMax_stack_vars {
       Mem *pIn1;
       VdbeFrame *pFrame;
-    } ce;
+    } cf;
     struct OP_AggStep_stack_vars {
       int n;
       int i;
@@ -63951,34 +64414,36 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       Mem *pRec;
       sqlite3_context ctx;
       sqlite3_value **apVal;
-    } cf;
+    } cg;
     struct OP_AggFinal_stack_vars {
       Mem *pMem;
-    } cg;
+    } ch;
     struct OP_Checkpoint_stack_vars {
       int i;                          /* Loop counter */
       int aRes[3];                    /* Results */
       Mem *pMem;                      /* Write results here */
-    } ch;
+    } ci;
     struct OP_JournalMode_stack_vars {
       Btree *pBt;                     /* Btree to change journal mode of */
       Pager *pPager;                  /* Pager associated with pBt */
       int eNew;                       /* New journal mode */
       int eOld;                       /* The old journal mode */
+#ifndef SQLITE_OMIT_WAL
       const char *zFilename;          /* Name of database file for pPager */
-    } ci;
+#endif
+    } cj;
     struct OP_IncrVacuum_stack_vars {
       Btree *pBt;
-    } cj;
+    } ck;
     struct OP_VBegin_stack_vars {
       VTable *pVTab;
-    } ck;
+    } cl;
     struct OP_VOpen_stack_vars {
       VdbeCursor *pCur;
       sqlite3_vtab_cursor *pVtabCursor;
       sqlite3_vtab *pVtab;
       sqlite3_module *pModule;
-    } cl;
+    } cm;
     struct OP_VFilter_stack_vars {
       int nArg;
       int iQuery;
@@ -63991,23 +64456,23 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       int res;
       int i;
       Mem **apArg;
-    } cm;
+    } cn;
     struct OP_VColumn_stack_vars {
       sqlite3_vtab *pVtab;
       const sqlite3_module *pModule;
       Mem *pDest;
       sqlite3_context sContext;
-    } cn;
+    } co;
     struct OP_VNext_stack_vars {
       sqlite3_vtab *pVtab;
       const sqlite3_module *pModule;
       int res;
       VdbeCursor *pCur;
-    } co;
+    } cp;
     struct OP_VRename_stack_vars {
       sqlite3_vtab *pVtab;
       Mem *pName;
-    } cp;
+    } cq;
     struct OP_VUpdate_stack_vars {
       sqlite3_vtab *pVtab;
       sqlite3_module *pModule;
@@ -64016,11 +64481,11 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
       sqlite_int64 rowid;
       Mem **apArg;
       Mem *pX;
-    } cq;
+    } cr;
     struct OP_Trace_stack_vars {
       char *zTrace;
       char *z;
-    } cr;
+    } cs;
   } u;
   /* End automatically generated code
   ********************************************************************/
@@ -64411,25 +64876,30 @@ case OP_String: {          /* out2-prerelease */
   break;
 }
 
-/* Opcode: Null * P2 P3 * *
+/* Opcode: Null P1 P2 P3 * *
 **
 ** Write a NULL into registers P2.  If P3 greater than P2, then also write
-** NULL into register P3 and ever register in between P2 and P3.  If P3
+** NULL into register P3 and every register in between P2 and P3.  If P3
 ** is less than P2 (typically P3 is zero) then only register P2 is
-** set to NULL
+** set to NULL.
+**
+** If the P1 value is non-zero, then also set the MEM_Cleared flag so that
+** NULL values will not compare equal even if SQLITE_NULLEQ is set on
+** OP_Ne or OP_Eq.
 */
 case OP_Null: {           /* out2-prerelease */
 #if 0  /* local variables moved into u.ab */
   int cnt;
+  u16 nullFlag;
 #endif /* local variables moved into u.ab */
   u.ab.cnt = pOp->p3-pOp->p2;
   assert( pOp->p3<=p->nMem );
-  pOut->flags = MEM_Null;
+  pOut->flags = u.ab.nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
   while( u.ab.cnt>0 ){
     pOut++;
     memAboutToChange(p, pOut);
     VdbeMemRelease(pOut);
-    pOut->flags = MEM_Null;
+    pOut->flags = u.ab.nullFlag;
     u.ab.cnt--;
   }
   break;
@@ -64474,10 +64944,10 @@ case OP_Variable: {            /* out2-prerelease */
 
 /* Opcode: Move P1 P2 P3 * *
 **
-** Move the values in register P1..P1+P3-1 over into
-** registers P2..P2+P3-1.  Registers P1..P1+P1-1 are
+** Move the values in register P1..P1+P3 over into
+** registers P2..P2+P3.  Registers P1..P1+P3 are
 ** left holding a NULL.  It is an error for register ranges
-** P1..P1+P3-1 and P2..P2+P3-1 to overlap.
+** P1..P1+P3 and P2..P2+P3 to overlap.
 */
 case OP_Move: {
 #if 0  /* local variables moved into u.ad */
@@ -64487,7 +64957,7 @@ case OP_Move: {
   int p2;          /* Register to copy to */
 #endif /* local variables moved into u.ad */
 
-  u.ad.n = pOp->p3;
+  u.ad.n = pOp->p3 + 1;
   u.ad.p1 = pOp->p1;
   u.ad.p2 = pOp->p2;
   assert( u.ad.n>0 && u.ad.p1>0 && u.ad.p2>0 );
@@ -64516,20 +64986,33 @@ case OP_Move: {
   break;
 }
 
-/* Opcode: Copy P1 P2 * * *
+/* Opcode: Copy P1 P2 P3 * *
 **
-** Make a copy of register P1 into register P2.
+** Make a copy of registers P1..P1+P3 into registers P2..P2+P3.
 **
 ** This instruction makes a deep copy of the value.  A duplicate
 ** is made of any string or blob constant.  See also OP_SCopy.
 */
-case OP_Copy: {             /* in1, out2 */
+case OP_Copy: {
+#if 0  /* local variables moved into u.ae */
+  int n;
+#endif /* local variables moved into u.ae */
+
+  u.ae.n = pOp->p3;
   pIn1 = &aMem[pOp->p1];
   pOut = &aMem[pOp->p2];
   assert( pOut!=pIn1 );
-  sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
-  Deephemeralize(pOut);
-  REGISTER_TRACE(pOp->p2, pOut);
+  while( 1 ){
+    sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
+    Deephemeralize(pOut);
+#ifdef SQLITE_DEBUG
+    pOut->pScopyFrom = 0;
+#endif
+    REGISTER_TRACE(pOp->p2+pOp->p3-u.ae.n, pOut);
+    if( (u.ae.n--)==0 ) break;
+    pOut++;
+    pIn1++;
+  }
   break;
 }
 
@@ -64566,10 +65049,10 @@ case OP_SCopy: {            /* in1, out2 */
 ** row.
 */
 case OP_ResultRow: {
-#if 0  /* local variables moved into u.ae */
+#if 0  /* local variables moved into u.af */
   Mem *pMem;
   int i;
-#endif /* local variables moved into u.ae */
+#endif /* local variables moved into u.af */
   assert( p->nResColumn==pOp->p2 );
   assert( pOp->p1>0 );
   assert( pOp->p1+pOp->p2<=p->nMem+1 );
@@ -64611,15 +65094,15 @@ case OP_ResultRow: {
   ** and have an assigned type.  The results are de-ephemeralized as
   ** a side effect.
   */
-  u.ae.pMem = p->pResultSet = &aMem[pOp->p1];
-  for(u.ae.i=0; u.ae.i<pOp->p2; u.ae.i++){
-    assert( memIsValid(&u.ae.pMem[u.ae.i]) );
-    Deephemeralize(&u.ae.pMem[u.ae.i]);
-    assert( (u.ae.pMem[u.ae.i].flags & MEM_Ephem)==0
-            || (u.ae.pMem[u.ae.i].flags & (MEM_Str|MEM_Blob))==0 );
-    sqlite3VdbeMemNulTerminate(&u.ae.pMem[u.ae.i]);
-    sqlite3VdbeMemStoreType(&u.ae.pMem[u.ae.i]);
-    REGISTER_TRACE(pOp->p1+u.ae.i, &u.ae.pMem[u.ae.i]);
+  u.af.pMem = p->pResultSet = &aMem[pOp->p1];
+  for(u.af.i=0; u.af.i<pOp->p2; u.af.i++){
+    assert( memIsValid(&u.af.pMem[u.af.i]) );
+    Deephemeralize(&u.af.pMem[u.af.i]);
+    assert( (u.af.pMem[u.af.i].flags & MEM_Ephem)==0
+            || (u.af.pMem[u.af.i].flags & (MEM_Str|MEM_Blob))==0 );
+    sqlite3VdbeMemNulTerminate(&u.af.pMem[u.af.i]);
+    sqlite3VdbeMemStoreType(&u.af.pMem[u.af.i]);
+    REGISTER_TRACE(pOp->p1+u.af.i, &u.af.pMem[u.af.i]);
   }
   if( db->mallocFailed ) goto no_mem;
 
@@ -64643,9 +65126,9 @@ case OP_ResultRow: {
 ** to avoid a memcpy().
 */
 case OP_Concat: {           /* same as TK_CONCAT, in1, in2, out3 */
-#if 0  /* local variables moved into u.af */
+#if 0  /* local variables moved into u.ag */
   i64 nByte;
-#endif /* local variables moved into u.af */
+#endif /* local variables moved into u.ag */
 
   pIn1 = &aMem[pOp->p1];
   pIn2 = &aMem[pOp->p2];
@@ -64658,22 +65141,22 @@ case OP_Concat: {           /* same as TK_CONCAT, in1, in2, out3 */
   if( ExpandBlob(pIn1) || ExpandBlob(pIn2) ) goto no_mem;
   Stringify(pIn1, encoding);
   Stringify(pIn2, encoding);
-  u.af.nByte = pIn1->n + pIn2->n;
-  if( u.af.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+  u.ag.nByte = pIn1->n + pIn2->n;
+  if( u.ag.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
     goto too_big;
   }
   MemSetTypeFlag(pOut, MEM_Str);
-  if( sqlite3VdbeMemGrow(pOut, (int)u.af.nByte+2, pOut==pIn2) ){
+  if( sqlite3VdbeMemGrow(pOut, (int)u.ag.nByte+2, pOut==pIn2) ){
     goto no_mem;
   }
   if( pOut!=pIn2 ){
     memcpy(pOut->z, pIn2->z, pIn2->n);
   }
   memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
-  pOut->z[u.af.nByte] = 0;
-  pOut->z[u.af.nByte+1] = 0;
+  pOut->z[u.ag.nByte] = 0;
+  pOut->z[u.ag.nByte+1] = 0;
   pOut->flags |= MEM_Term;
-  pOut->n = (int)u.af.nByte;
+  pOut->n = (int)u.ag.nByte;
   pOut->enc = encoding;
   UPDATE_MAX_BLOBSIZE(pOut);
   break;
@@ -64717,76 +65200,79 @@ case OP_Subtract:              /* same as TK_MINUS, in1, in2, out3 */
 case OP_Multiply:              /* same as TK_STAR, in1, in2, out3 */
 case OP_Divide:                /* same as TK_SLASH, in1, in2, out3 */
 case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
-#if 0  /* local variables moved into u.ag */
+#if 0  /* local variables moved into u.ah */
+  char bIntint;   /* Started out as two integer operands */
   int flags;      /* Combined MEM_* flags from both inputs */
   i64 iA;         /* Integer value of left operand */
   i64 iB;         /* Integer value of right operand */
   double rA;      /* Real value of left operand */
   double rB;      /* Real value of right operand */
-#endif /* local variables moved into u.ag */
+#endif /* local variables moved into u.ah */
 
   pIn1 = &aMem[pOp->p1];
   applyNumericAffinity(pIn1);
   pIn2 = &aMem[pOp->p2];
   applyNumericAffinity(pIn2);
   pOut = &aMem[pOp->p3];
-  u.ag.flags = pIn1->flags | pIn2->flags;
-  if( (u.ag.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
+  u.ah.flags = pIn1->flags | pIn2->flags;
+  if( (u.ah.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
   if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){
-    u.ag.iA = pIn1->u.i;
-    u.ag.iB = pIn2->u.i;
+    u.ah.iA = pIn1->u.i;
+    u.ah.iB = pIn2->u.i;
+    u.ah.bIntint = 1;
     switch( pOp->opcode ){
-      case OP_Add:       if( sqlite3AddInt64(&u.ag.iB,u.ag.iA) ) goto fp_math;  break;
-      case OP_Subtract:  if( sqlite3SubInt64(&u.ag.iB,u.ag.iA) ) goto fp_math;  break;
-      case OP_Multiply:  if( sqlite3MulInt64(&u.ag.iB,u.ag.iA) ) goto fp_math;  break;
+      case OP_Add:       if( sqlite3AddInt64(&u.ah.iB,u.ah.iA) ) goto fp_math;  break;
+      case OP_Subtract:  if( sqlite3SubInt64(&u.ah.iB,u.ah.iA) ) goto fp_math;  break;
+      case OP_Multiply:  if( sqlite3MulInt64(&u.ah.iB,u.ah.iA) ) goto fp_math;  break;
       case OP_Divide: {
-        if( u.ag.iA==0 ) goto arithmetic_result_is_null;
-        if( u.ag.iA==-1 && u.ag.iB==SMALLEST_INT64 ) goto fp_math;
-        u.ag.iB /= u.ag.iA;
+        if( u.ah.iA==0 ) goto arithmetic_result_is_null;
+        if( u.ah.iA==-1 && u.ah.iB==SMALLEST_INT64 ) goto fp_math;
+        u.ah.iB /= u.ah.iA;
         break;
       }
       default: {
-        if( u.ag.iA==0 ) goto arithmetic_result_is_null;
-        if( u.ag.iA==-1 ) u.ag.iA = 1;
-        u.ag.iB %= u.ag.iA;
+        if( u.ah.iA==0 ) goto arithmetic_result_is_null;
+        if( u.ah.iA==-1 ) u.ah.iA = 1;
+        u.ah.iB %= u.ah.iA;
         break;
       }
     }
-    pOut->u.i = u.ag.iB;
+    pOut->u.i = u.ah.iB;
     MemSetTypeFlag(pOut, MEM_Int);
   }else{
+    u.ah.bIntint = 0;
 fp_math:
-    u.ag.rA = sqlite3VdbeRealValue(pIn1);
-    u.ag.rB = sqlite3VdbeRealValue(pIn2);
+    u.ah.rA = sqlite3VdbeRealValue(pIn1);
+    u.ah.rB = sqlite3VdbeRealValue(pIn2);
     switch( pOp->opcode ){
-      case OP_Add:         u.ag.rB += u.ag.rA;       break;
-      case OP_Subtract:    u.ag.rB -= u.ag.rA;       break;
-      case OP_Multiply:    u.ag.rB *= u.ag.rA;       break;
+      case OP_Add:         u.ah.rB += u.ah.rA;       break;
+      case OP_Subtract:    u.ah.rB -= u.ah.rA;       break;
+      case OP_Multiply:    u.ah.rB *= u.ah.rA;       break;
       case OP_Divide: {
         /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
-        if( u.ag.rA==(double)0 ) goto arithmetic_result_is_null;
-        u.ag.rB /= u.ag.rA;
+        if( u.ah.rA==(double)0 ) goto arithmetic_result_is_null;
+        u.ah.rB /= u.ah.rA;
         break;
       }
       default: {
-        u.ag.iA = (i64)u.ag.rA;
-        u.ag.iB = (i64)u.ag.rB;
-        if( u.ag.iA==0 ) goto arithmetic_result_is_null;
-        if( u.ag.iA==-1 ) u.ag.iA = 1;
-        u.ag.rB = (double)(u.ag.iB % u.ag.iA);
+        u.ah.iA = (i64)u.ah.rA;
+        u.ah.iB = (i64)u.ah.rB;
+        if( u.ah.iA==0 ) goto arithmetic_result_is_null;
+        if( u.ah.iA==-1 ) u.ah.iA = 1;
+        u.ah.rB = (double)(u.ah.iB % u.ah.iA);
         break;
       }
     }
 #ifdef SQLITE_OMIT_FLOATING_POINT
-    pOut->u.i = u.ag.rB;
+    pOut->u.i = u.ah.rB;
     MemSetTypeFlag(pOut, MEM_Int);
 #else
-    if( sqlite3IsNaN(u.ag.rB) ){
+    if( sqlite3IsNaN(u.ah.rB) ){
       goto arithmetic_result_is_null;
     }
-    pOut->r = u.ag.rB;
+    pOut->r = u.ah.rB;
     MemSetTypeFlag(pOut, MEM_Real);
-    if( (u.ag.flags & MEM_Real)==0 ){
+    if( (u.ah.flags & MEM_Real)==0 && !u.ah.bIntint ){
       sqlite3VdbeIntegerAffinity(pOut);
     }
 #endif
@@ -64838,70 +65324,70 @@ case OP_CollSeq: {
 ** See also: AggStep and AggFinal
 */
 case OP_Function: {
-#if 0  /* local variables moved into u.ah */
+#if 0  /* local variables moved into u.ai */
   int i;
   Mem *pArg;
   sqlite3_context ctx;
   sqlite3_value **apVal;
   int n;
-#endif /* local variables moved into u.ah */
+#endif /* local variables moved into u.ai */
 
-  u.ah.n = pOp->p5;
-  u.ah.apVal = p->apArg;
-  assert( u.ah.apVal || u.ah.n==0 );
+  u.ai.n = pOp->p5;
+  u.ai.apVal = p->apArg;
+  assert( u.ai.apVal || u.ai.n==0 );
   assert( pOp->p3>0 && pOp->p3<=p->nMem );
   pOut = &aMem[pOp->p3];
   memAboutToChange(p, pOut);
 
-  assert( u.ah.n==0 || (pOp->p2>0 && pOp->p2+u.ah.n<=p->nMem+1) );
-  assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+u.ah.n );
-  u.ah.pArg = &aMem[pOp->p2];
-  for(u.ah.i=0; u.ah.i<u.ah.n; u.ah.i++, u.ah.pArg++){
-    assert( memIsValid(u.ah.pArg) );
-    u.ah.apVal[u.ah.i] = u.ah.pArg;
-    Deephemeralize(u.ah.pArg);
-    sqlite3VdbeMemStoreType(u.ah.pArg);
-    REGISTER_TRACE(pOp->p2+u.ah.i, u.ah.pArg);
+  assert( u.ai.n==0 || (pOp->p2>0 && pOp->p2+u.ai.n<=p->nMem+1) );
+  assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+u.ai.n );
+  u.ai.pArg = &aMem[pOp->p2];
+  for(u.ai.i=0; u.ai.i<u.ai.n; u.ai.i++, u.ai.pArg++){
+    assert( memIsValid(u.ai.pArg) );
+    u.ai.apVal[u.ai.i] = u.ai.pArg;
+    Deephemeralize(u.ai.pArg);
+    sqlite3VdbeMemStoreType(u.ai.pArg);
+    REGISTER_TRACE(pOp->p2+u.ai.i, u.ai.pArg);
   }
 
   assert( pOp->p4type==P4_FUNCDEF || pOp->p4type==P4_VDBEFUNC );
   if( pOp->p4type==P4_FUNCDEF ){
-    u.ah.ctx.pFunc = pOp->p4.pFunc;
-    u.ah.ctx.pVdbeFunc = 0;
+    u.ai.ctx.pFunc = pOp->p4.pFunc;
+    u.ai.ctx.pVdbeFunc = 0;
   }else{
-    u.ah.ctx.pVdbeFunc = (VdbeFunc*)pOp->p4.pVdbeFunc;
-    u.ah.ctx.pFunc = u.ah.ctx.pVdbeFunc->pFunc;
+    u.ai.ctx.pVdbeFunc = (VdbeFunc*)pOp->p4.pVdbeFunc;
+    u.ai.ctx.pFunc = u.ai.ctx.pVdbeFunc->pFunc;
   }
 
-  u.ah.ctx.s.flags = MEM_Null;
-  u.ah.ctx.s.db = db;
-  u.ah.ctx.s.xDel = 0;
-  u.ah.ctx.s.zMalloc = 0;
+  u.ai.ctx.s.flags = MEM_Null;
+  u.ai.ctx.s.db = db;
+  u.ai.ctx.s.xDel = 0;
+  u.ai.ctx.s.zMalloc = 0;
 
   /* The output cell may already have a buffer allocated. Move
-  ** the pointer to u.ah.ctx.s so in case the user-function can use
+  ** the pointer to u.ai.ctx.s so in case the user-function can use
   ** the already allocated buffer instead of allocating a new one.
   */
-  sqlite3VdbeMemMove(&u.ah.ctx.s, pOut);
-  MemSetTypeFlag(&u.ah.ctx.s, MEM_Null);
+  sqlite3VdbeMemMove(&u.ai.ctx.s, pOut);
+  MemSetTypeFlag(&u.ai.ctx.s, MEM_Null);
 
-  u.ah.ctx.isError = 0;
-  if( u.ah.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
+  u.ai.ctx.isError = 0;
+  if( u.ai.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
     assert( pOp>aOp );
     assert( pOp[-1].p4type==P4_COLLSEQ );
     assert( pOp[-1].opcode==OP_CollSeq );
-    u.ah.ctx.pColl = pOp[-1].p4.pColl;
+    u.ai.ctx.pColl = pOp[-1].p4.pColl;
   }
   db->lastRowid = lastRowid;
-  (*u.ah.ctx.pFunc->xFunc)(&u.ah.ctx, u.ah.n, u.ah.apVal); /* IMP: R-24505-23230 */
+  (*u.ai.ctx.pFunc->xFunc)(&u.ai.ctx, u.ai.n, u.ai.apVal); /* IMP: R-24505-23230 */
   lastRowid = db->lastRowid;
 
   /* If any auxiliary data functions have been called by this user function,
   ** immediately call the destructor for any non-static values.
   */
-  if( u.ah.ctx.pVdbeFunc ){
-    sqlite3VdbeDeleteAuxData(u.ah.ctx.pVdbeFunc, pOp->p1);
-    pOp->p4.pVdbeFunc = u.ah.ctx.pVdbeFunc;
+  if( u.ai.ctx.pVdbeFunc ){
+    sqlite3VdbeDeleteAuxData(u.ai.ctx.pVdbeFunc, pOp->p1);
+    pOp->p4.pVdbeFunc = u.ai.ctx.pVdbeFunc;
     pOp->p4type = P4_VDBEFUNC;
   }
 
@@ -64911,19 +65397,19 @@ case OP_Function: {
     ** to return a value. The following call releases any resources
     ** associated with such a value.
     */
-    sqlite3VdbeMemRelease(&u.ah.ctx.s);
+    sqlite3VdbeMemRelease(&u.ai.ctx.s);
     goto no_mem;
   }
 
   /* If the function returned an error, throw an exception */
-  if( u.ah.ctx.isError ){
-    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ah.ctx.s));
-    rc = u.ah.ctx.isError;
+  if( u.ai.ctx.isError ){
+    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ai.ctx.s));
+    rc = u.ai.ctx.isError;
   }
 
   /* Copy the result of the function into register P3 */
-  sqlite3VdbeChangeEncoding(&u.ah.ctx.s, encoding);
-  sqlite3VdbeMemMove(pOut, &u.ah.ctx.s);
+  sqlite3VdbeChangeEncoding(&u.ai.ctx.s, encoding);
+  sqlite3VdbeMemMove(pOut, &u.ai.ctx.s);
   if( sqlite3VdbeMemTooBig(pOut) ){
     goto too_big;
   }
@@ -64971,12 +65457,12 @@ case OP_BitAnd:                 /* same as TK_BITAND, in1, in2, out3 */
 case OP_BitOr:                  /* same as TK_BITOR, in1, in2, out3 */
 case OP_ShiftLeft:              /* same as TK_LSHIFT, in1, in2, out3 */
 case OP_ShiftRight: {           /* same as TK_RSHIFT, in1, in2, out3 */
-#if 0  /* local variables moved into u.ai */
+#if 0  /* local variables moved into u.aj */
   i64 iA;
   u64 uA;
   i64 iB;
   u8 op;
-#endif /* local variables moved into u.ai */
+#endif /* local variables moved into u.aj */
 
   pIn1 = &aMem[pOp->p1];
   pIn2 = &aMem[pOp->p2];
@@ -64985,38 +65471,38 @@ case OP_ShiftRight: {           /* same as TK_RSHIFT, in1, in2, out3 */
     sqlite3VdbeMemSetNull(pOut);
     break;
   }
-  u.ai.iA = sqlite3VdbeIntValue(pIn2);
-  u.ai.iB = sqlite3VdbeIntValue(pIn1);
-  u.ai.op = pOp->opcode;
-  if( u.ai.op==OP_BitAnd ){
-    u.ai.iA &= u.ai.iB;
-  }else if( u.ai.op==OP_BitOr ){
-    u.ai.iA |= u.ai.iB;
-  }else if( u.ai.iB!=0 ){
-    assert( u.ai.op==OP_ShiftRight || u.ai.op==OP_ShiftLeft );
+  u.aj.iA = sqlite3VdbeIntValue(pIn2);
+  u.aj.iB = sqlite3VdbeIntValue(pIn1);
+  u.aj.op = pOp->opcode;
+  if( u.aj.op==OP_BitAnd ){
+    u.aj.iA &= u.aj.iB;
+  }else if( u.aj.op==OP_BitOr ){
+    u.aj.iA |= u.aj.iB;
+  }else if( u.aj.iB!=0 ){
+    assert( u.aj.op==OP_ShiftRight || u.aj.op==OP_ShiftLeft );
 
     /* If shifting by a negative amount, shift in the other direction */
-    if( u.ai.iB<0 ){
+    if( u.aj.iB<0 ){
       assert( OP_ShiftRight==OP_ShiftLeft+1 );
-      u.ai.op = 2*OP_ShiftLeft + 1 - u.ai.op;
-      u.ai.iB = u.ai.iB>(-64) ? -u.ai.iB : 64;
+      u.aj.op = 2*OP_ShiftLeft + 1 - u.aj.op;
+      u.aj.iB = u.aj.iB>(-64) ? -u.aj.iB : 64;
     }
 
-    if( u.ai.iB>=64 ){
-      u.ai.iA = (u.ai.iA>=0 || u.ai.op==OP_ShiftLeft) ? 0 : -1;
+    if( u.aj.iB>=64 ){
+      u.aj.iA = (u.aj.iA>=0 || u.aj.op==OP_ShiftLeft) ? 0 : -1;
     }else{
-      memcpy(&u.ai.uA, &u.ai.iA, sizeof(u.ai.uA));
-      if( u.ai.op==OP_ShiftLeft ){
-        u.ai.uA <<= u.ai.iB;
+      memcpy(&u.aj.uA, &u.aj.iA, sizeof(u.aj.uA));
+      if( u.aj.op==OP_ShiftLeft ){
+        u.aj.uA <<= u.aj.iB;
       }else{
-        u.ai.uA >>= u.ai.iB;
+        u.aj.uA >>= u.aj.iB;
         /* Sign-extend on a right shift of a negative number */
-        if( u.ai.iA<0 ) u.ai.uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-u.ai.iB);
+        if( u.aj.iA<0 ) u.aj.uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-u.aj.iB);
       }
-      memcpy(&u.ai.iA, &u.ai.uA, sizeof(u.ai.iA));
+      memcpy(&u.aj.iA, &u.aj.uA, sizeof(u.aj.iA));
     }
   }
-  pOut->u.i = u.ai.iA;
+  pOut->u.i = u.aj.iA;
   MemSetTypeFlag(pOut, MEM_Int);
   break;
 }
@@ -65208,6 +65694,10 @@ case OP_ToReal: {                  /* same as TK_TO_REAL, in1 */
 **
 ** If the SQLITE_STOREP2 bit of P5 is set, then do not jump.  Instead,
 ** store a boolean result (either 0, or 1, or NULL) in register P2.
+**
+** If the SQLITE_NULLEQ bit is set in P5, then NULL values are considered
+** equal to one another, provided that they do not have their MEM_Cleared
+** bit set.
 */
 /* Opcode: Ne P1 P2 P3 P4 P5
 **
@@ -65257,18 +65747,18 @@ case OP_Lt:               /* same as TK_LT, jump, in1, in3 */
 case OP_Le:               /* same as TK_LE, jump, in1, in3 */
 case OP_Gt:               /* same as TK_GT, jump, in1, in3 */
 case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
-#if 0  /* local variables moved into u.aj */
+#if 0  /* local variables moved into u.ak */
   int res;            /* Result of the comparison of pIn1 against pIn3 */
   char affinity;      /* Affinity to use for comparison */
   u16 flags1;         /* Copy of initial value of pIn1->flags */
   u16 flags3;         /* Copy of initial value of pIn3->flags */
-#endif /* local variables moved into u.aj */
+#endif /* local variables moved into u.ak */
 
   pIn1 = &aMem[pOp->p1];
   pIn3 = &aMem[pOp->p3];
-  u.aj.flags1 = pIn1->flags;
-  u.aj.flags3 = pIn3->flags;
-  if( (u.aj.flags1 | u.aj.flags3)&MEM_Null ){
+  u.ak.flags1 = pIn1->flags;
+  u.ak.flags3 = pIn3->flags;
+  if( (u.ak.flags1 | u.ak.flags3)&MEM_Null ){
     /* One or both operands are NULL */
     if( pOp->p5 & SQLITE_NULLEQ ){
       /* If SQLITE_NULLEQ is set (which will only happen if the operator is
@@ -65276,7 +65766,15 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
       ** or not both operands are null.
       */
       assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
-      u.aj.res = (u.aj.flags1 & u.aj.flags3 & MEM_Null)==0;
+      assert( (u.ak.flags1 & MEM_Cleared)==0 );
+      if( (u.ak.flags1&MEM_Null)!=0
+       && (u.ak.flags3&MEM_Null)!=0
+       && (u.ak.flags3&MEM_Cleared)==0
+      ){
+        u.ak.res = 0;  /* Results are equal */
+      }else{
+        u.ak.res = 1;  /* Results are not equal */
+      }
     }else{
       /* SQLITE_NULLEQ is clear and at least one operand is NULL,
       ** then the result is always NULL.
@@ -65293,40 +65791,40 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
     }
   }else{
     /* Neither operand is NULL.  Do a comparison. */
-    u.aj.affinity = pOp->p5 & SQLITE_AFF_MASK;
-    if( u.aj.affinity ){
-      applyAffinity(pIn1, u.aj.affinity, encoding);
-      applyAffinity(pIn3, u.aj.affinity, encoding);
+    u.ak.affinity = pOp->p5 & SQLITE_AFF_MASK;
+    if( u.ak.affinity ){
+      applyAffinity(pIn1, u.ak.affinity, encoding);
+      applyAffinity(pIn3, u.ak.affinity, encoding);
       if( db->mallocFailed ) goto no_mem;
     }
 
     assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
     ExpandBlob(pIn1);
     ExpandBlob(pIn3);
-    u.aj.res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
+    u.ak.res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
   }
   switch( pOp->opcode ){
-    case OP_Eq:    u.aj.res = u.aj.res==0;     break;
-    case OP_Ne:    u.aj.res = u.aj.res!=0;     break;
-    case OP_Lt:    u.aj.res = u.aj.res<0;      break;
-    case OP_Le:    u.aj.res = u.aj.res<=0;     break;
-    case OP_Gt:    u.aj.res = u.aj.res>0;      break;
-    default:       u.aj.res = u.aj.res>=0;     break;
+    case OP_Eq:    u.ak.res = u.ak.res==0;     break;
+    case OP_Ne:    u.ak.res = u.ak.res!=0;     break;
+    case OP_Lt:    u.ak.res = u.ak.res<0;      break;
+    case OP_Le:    u.ak.res = u.ak.res<=0;     break;
+    case OP_Gt:    u.ak.res = u.ak.res>0;      break;
+    default:       u.ak.res = u.ak.res>=0;     break;
   }
 
   if( pOp->p5 & SQLITE_STOREP2 ){
     pOut = &aMem[pOp->p2];
     memAboutToChange(p, pOut);
     MemSetTypeFlag(pOut, MEM_Int);
-    pOut->u.i = u.aj.res;
+    pOut->u.i = u.ak.res;
     REGISTER_TRACE(pOp->p2, pOut);
-  }else if( u.aj.res ){
+  }else if( u.ak.res ){
     pc = pOp->p2-1;
   }
 
   /* Undo any changes made by applyAffinity() to the input registers. */
-  pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (u.aj.flags1&MEM_TypeMask);
-  pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (u.aj.flags3&MEM_TypeMask);
+  pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (u.ak.flags1&MEM_TypeMask);
+  pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (u.ak.flags3&MEM_TypeMask);
   break;
 }
 
@@ -65335,9 +65833,9 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
 ** Set the permutation used by the OP_Compare operator to be the array
 ** of integers in P4.
 **
-** The permutation is only valid until the next OP_Permutation, OP_Compare,
-** OP_Halt, or OP_ResultRow.  Typically the OP_Permutation should occur
-** immediately prior to the OP_Compare.
+** The permutation is only valid until the next OP_Compare that has
+** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should 
+** occur immediately prior to the OP_Compare.
 */
 case OP_Permutation: {
   assert( pOp->p4type==P4_INTARRAY );
@@ -65346,12 +65844,17 @@ case OP_Permutation: {
   break;
 }
 
-/* Opcode: Compare P1 P2 P3 P4 *
+/* Opcode: Compare P1 P2 P3 P4 P5
 **
 ** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this
 ** vector "A") and in reg(P2)..reg(P2+P3-1) ("B").  Save the result of
 ** the comparison for use by the next OP_Jump instruct.
 **
+** If P5 has the OPFLAG_PERMUTE bit set, then the order of comparison is
+** determined by the most recent OP_Permutation operator.  If the
+** OPFLAG_PERMUTE bit is clear, then register are compared in sequential
+** order.
+**
 ** P4 is a KeyInfo structure that defines collating sequences and sort
 ** orders for the comparison.  The permutation applies to registers
 ** only.  The KeyInfo elements are used sequentially.
@@ -65361,7 +65864,7 @@ case OP_Permutation: {
 ** and strings are less than blobs.
 */
 case OP_Compare: {
-#if 0  /* local variables moved into u.ak */
+#if 0  /* local variables moved into u.al */
   int n;
   int i;
   int p1;
@@ -65370,37 +65873,38 @@ case OP_Compare: {
   int idx;
   CollSeq *pColl;    /* Collating sequence to use on this term */
   int bRev;          /* True for DESCENDING sort order */
-#endif /* local variables moved into u.ak */
+#endif /* local variables moved into u.al */
 
-  u.ak.n = pOp->p3;
-  u.ak.pKeyInfo = pOp->p4.pKeyInfo;
-  assert( u.ak.n>0 );
-  assert( u.ak.pKeyInfo!=0 );
-  u.ak.p1 = pOp->p1;
-  u.ak.p2 = pOp->p2;
+  if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0;
+  u.al.n = pOp->p3;
+  u.al.pKeyInfo = pOp->p4.pKeyInfo;
+  assert( u.al.n>0 );
+  assert( u.al.pKeyInfo!=0 );
+  u.al.p1 = pOp->p1;
+  u.al.p2 = pOp->p2;
 #if SQLITE_DEBUG
   if( aPermute ){
     int k, mx = 0;
-    for(k=0; k<u.ak.n; k++) if( aPermute[k]>mx ) mx = aPermute[k];
-    assert( u.ak.p1>0 && u.ak.p1+mx<=p->nMem+1 );
-    assert( u.ak.p2>0 && u.ak.p2+mx<=p->nMem+1 );
+    for(k=0; k<u.al.n; k++) if( aPermute[k]>mx ) mx = aPermute[k];
+    assert( u.al.p1>0 && u.al.p1+mx<=p->nMem+1 );
+    assert( u.al.p2>0 && u.al.p2+mx<=p->nMem+1 );
   }else{
-    assert( u.ak.p1>0 && u.ak.p1+u.ak.n<=p->nMem+1 );
-    assert( u.ak.p2>0 && u.ak.p2+u.ak.n<=p->nMem+1 );
+    assert( u.al.p1>0 && u.al.p1+u.al.n<=p->nMem+1 );
+    assert( u.al.p2>0 && u.al.p2+u.al.n<=p->nMem+1 );
   }
 #endif /* SQLITE_DEBUG */
-  for(u.ak.i=0; u.ak.i<u.ak.n; u.ak.i++){
-    u.ak.idx = aPermute ? aPermute[u.ak.i] : u.ak.i;
-    assert( memIsValid(&aMem[u.ak.p1+u.ak.idx]) );
-    assert( memIsValid(&aMem[u.ak.p2+u.ak.idx]) );
-    REGISTER_TRACE(u.ak.p1+u.ak.idx, &aMem[u.ak.p1+u.ak.idx]);
-    REGISTER_TRACE(u.ak.p2+u.ak.idx, &aMem[u.ak.p2+u.ak.idx]);
-    assert( u.ak.i<u.ak.pKeyInfo->nField );
-    u.ak.pColl = u.ak.pKeyInfo->aColl[u.ak.i];
-    u.ak.bRev = u.ak.pKeyInfo->aSortOrder[u.ak.i];
-    iCompare = sqlite3MemCompare(&aMem[u.ak.p1+u.ak.idx], &aMem[u.ak.p2+u.ak.idx], u.ak.pColl);
+  for(u.al.i=0; u.al.i<u.al.n; u.al.i++){
+    u.al.idx = aPermute ? aPermute[u.al.i] : u.al.i;
+    assert( memIsValid(&aMem[u.al.p1+u.al.idx]) );
+    assert( memIsValid(&aMem[u.al.p2+u.al.idx]) );
+    REGISTER_TRACE(u.al.p1+u.al.idx, &aMem[u.al.p1+u.al.idx]);
+    REGISTER_TRACE(u.al.p2+u.al.idx, &aMem[u.al.p2+u.al.idx]);
+    assert( u.al.i<u.al.pKeyInfo->nField );
+    u.al.pColl = u.al.pKeyInfo->aColl[u.al.i];
+    u.al.bRev = u.al.pKeyInfo->aSortOrder[u.al.i];
+    iCompare = sqlite3MemCompare(&aMem[u.al.p1+u.al.idx], &aMem[u.al.p2+u.al.idx], u.al.pColl);
     if( iCompare ){
-      if( u.ak.bRev ) iCompare = -iCompare;
+      if( u.al.bRev ) iCompare = -iCompare;
       break;
     }
   }
@@ -65445,35 +65949,35 @@ case OP_Jump: {             /* jump */
 */
 case OP_And:              /* same as TK_AND, in1, in2, out3 */
 case OP_Or: {             /* same as TK_OR, in1, in2, out3 */
-#if 0  /* local variables moved into u.al */
+#if 0  /* local variables moved into u.am */
   int v1;    /* Left operand:  0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
   int v2;    /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
-#endif /* local variables moved into u.al */
+#endif /* local variables moved into u.am */
 
   pIn1 = &aMem[pOp->p1];
   if( pIn1->flags & MEM_Null ){
-    u.al.v1 = 2;
+    u.am.v1 = 2;
   }else{
-    u.al.v1 = sqlite3VdbeIntValue(pIn1)!=0;
+    u.am.v1 = sqlite3VdbeIntValue(pIn1)!=0;
   }
   pIn2 = &aMem[pOp->p2];
   if( pIn2->flags & MEM_Null ){
-    u.al.v2 = 2;
+    u.am.v2 = 2;
   }else{
-    u.al.v2 = sqlite3VdbeIntValue(pIn2)!=0;
+    u.am.v2 = sqlite3VdbeIntValue(pIn2)!=0;
   }
   if( pOp->opcode==OP_And ){
     static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 };
-    u.al.v1 = and_logic[u.al.v1*3+u.al.v2];
+    u.am.v1 = and_logic[u.am.v1*3+u.am.v2];
   }else{
     static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 };
-    u.al.v1 = or_logic[u.al.v1*3+u.al.v2];
+    u.am.v1 = or_logic[u.am.v1*3+u.am.v2];
   }
   pOut = &aMem[pOp->p3];
-  if( u.al.v1==2 ){
+  if( u.am.v1==2 ){
     MemSetTypeFlag(pOut, MEM_Null);
   }else{
-    pOut->u.i = u.al.v1;
+    pOut->u.i = u.am.v1;
     MemSetTypeFlag(pOut, MEM_Int);
   }
   break;
@@ -65517,8 +66021,6 @@ case OP_BitNot: {             /* same as TK_BITNOT, in1, out2 */
 **
 ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise,
 ** set the flag and fall through to the next instruction.
-**
-** See also: JumpOnce
 */
 case OP_Once: {             /* jump */
   assert( pOp->p1<p->nOnceFlag );
@@ -65544,21 +66046,21 @@ case OP_Once: {             /* jump */
 */
 case OP_If:                 /* jump, in1 */
 case OP_IfNot: {            /* jump, in1 */
-#if 0  /* local variables moved into u.am */
+#if 0  /* local variables moved into u.an */
   int c;
-#endif /* local variables moved into u.am */
+#endif /* local variables moved into u.an */
   pIn1 = &aMem[pOp->p1];
   if( pIn1->flags & MEM_Null ){
-    u.am.c = pOp->p3;
+    u.an.c = pOp->p3;
   }else{
 #ifdef SQLITE_OMIT_FLOATING_POINT
-    u.am.c = sqlite3VdbeIntValue(pIn1)!=0;
+    u.an.c = sqlite3VdbeIntValue(pIn1)!=0;
 #else
-    u.am.c = sqlite3VdbeRealValue(pIn1)!=0.0;
+    u.an.c = sqlite3VdbeRealValue(pIn1)!=0.0;
 #endif
-    if( pOp->opcode==OP_IfNot ) u.am.c = !u.am.c;
+    if( pOp->opcode==OP_IfNot ) u.an.c = !u.an.c;
   }
-  if( u.am.c ){
+  if( u.an.c ){
     pc = pOp->p2-1;
   }
   break;
@@ -65613,7 +66115,7 @@ case OP_NotNull: {            /* same as TK_NOTNULL, jump, in1 */
 ** skipped for length() and all content loading can be skipped for typeof().
 */
 case OP_Column: {
-#if 0  /* local variables moved into u.an */
+#if 0  /* local variables moved into u.ao */
   u32 payloadSize;   /* Number of bytes in the record */
   i64 payloadSize64; /* Number of bytes in the record */
   int p1;            /* P1 value of the opcode */
@@ -65637,126 +66139,131 @@ case OP_Column: {
   int avail;         /* Number of bytes of available data */
   u32 t;             /* A type code from the record header */
   Mem *pReg;         /* PseudoTable input register */
-#endif /* local variables moved into u.an */
+#endif /* local variables moved into u.ao */
 
 
-  u.an.p1 = pOp->p1;
-  u.an.p2 = pOp->p2;
-  u.an.pC = 0;
-  memset(&u.an.sMem, 0, sizeof(u.an.sMem));
-  assert( u.an.p1<p->nCursor );
+  u.ao.p1 = pOp->p1;
+  u.ao.p2 = pOp->p2;
+  u.ao.pC = 0;
+  memset(&u.ao.sMem, 0, sizeof(u.ao.sMem));
+  assert( u.ao.p1<p->nCursor );
   assert( pOp->p3>0 && pOp->p3<=p->nMem );
-  u.an.pDest = &aMem[pOp->p3];
-  memAboutToChange(p, u.an.pDest);
-  u.an.zRec = 0;
+  u.ao.pDest = &aMem[pOp->p3];
+  memAboutToChange(p, u.ao.pDest);
+  u.ao.zRec = 0;
 
-  /* This block sets the variable u.an.payloadSize to be the total number of
+  /* This block sets the variable u.ao.payloadSize to be the total number of
   ** bytes in the record.
   **
-  ** u.an.zRec is set to be the complete text of the record if it is available.
+  ** u.ao.zRec is set to be the complete text of the record if it is available.
   ** The complete record text is always available for pseudo-tables
   ** If the record is stored in a cursor, the complete record text
-  ** might be available in the  u.an.pC->aRow cache.  Or it might not be.
-  ** If the data is unavailable,  u.an.zRec is set to NULL.
+  ** might be available in the  u.ao.pC->aRow cache.  Or it might not be.
+  ** If the data is unavailable,  u.ao.zRec is set to NULL.
   **
   ** We also compute the number of columns in the record.  For cursors,
   ** the number of columns is stored in the VdbeCursor.nField element.
   */
-  u.an.pC = p->apCsr[u.an.p1];
-  assert( u.an.pC!=0 );
+  u.ao.pC = p->apCsr[u.ao.p1];
+  assert( u.ao.pC!=0 );
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  assert( u.an.pC->pVtabCursor==0 );
+  assert( u.ao.pC->pVtabCursor==0 );
 #endif
-  u.an.pCrsr = u.an.pC->pCursor;
-  if( u.an.pCrsr!=0 ){
+  u.ao.pCrsr = u.ao.pC->pCursor;
+  if( u.ao.pCrsr!=0 ){
     /* The record is stored in a B-Tree */
-    rc = sqlite3VdbeCursorMoveto(u.an.pC);
+    rc = sqlite3VdbeCursorMoveto(u.ao.pC);
     if( rc ) goto abort_due_to_error;
-    if( u.an.pC->nullRow ){
-      u.an.payloadSize = 0;
-    }else if( u.an.pC->cacheStatus==p->cacheCtr ){
-      u.an.payloadSize = u.an.pC->payloadSize;
-      u.an.zRec = (char*)u.an.pC->aRow;
-    }else if( u.an.pC->isIndex ){
-      assert( sqlite3BtreeCursorIsValid(u.an.pCrsr) );
-      VVA_ONLY(rc =) sqlite3BtreeKeySize(u.an.pCrsr, &u.an.payloadSize64);
+    if( u.ao.pC->nullRow ){
+      u.ao.payloadSize = 0;
+    }else if( u.ao.pC->cacheStatus==p->cacheCtr ){
+      u.ao.payloadSize = u.ao.pC->payloadSize;
+      u.ao.zRec = (char*)u.ao.pC->aRow;
+    }else if( u.ao.pC->isIndex ){
+      assert( sqlite3BtreeCursorIsValid(u.ao.pCrsr) );
+      VVA_ONLY(rc =) sqlite3BtreeKeySize(u.ao.pCrsr, &u.ao.payloadSize64);
       assert( rc==SQLITE_OK );   /* True because of CursorMoveto() call above */
       /* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the
-      ** payload size, so it is impossible for u.an.payloadSize64 to be
+      ** payload size, so it is impossible for u.ao.payloadSize64 to be
       ** larger than 32 bits. */
-      assert( (u.an.payloadSize64 & SQLITE_MAX_U32)==(u64)u.an.payloadSize64 );
-      u.an.payloadSize = (u32)u.an.payloadSize64;
+      assert( (u.ao.payloadSize64 & SQLITE_MAX_U32)==(u64)u.ao.payloadSize64 );
+      u.ao.payloadSize = (u32)u.ao.payloadSize64;
     }else{
-      assert( sqlite3BtreeCursorIsValid(u.an.pCrsr) );
-      VVA_ONLY(rc =) sqlite3BtreeDataSize(u.an.pCrsr, &u.an.payloadSize);
+      assert( sqlite3BtreeCursorIsValid(u.ao.pCrsr) );
+      VVA_ONLY(rc =) sqlite3BtreeDataSize(u.ao.pCrsr, &u.ao.payloadSize);
       assert( rc==SQLITE_OK );   /* DataSize() cannot fail */
     }
-  }else if( ALWAYS(u.an.pC->pseudoTableReg>0) ){
-    u.an.pReg = &aMem[u.an.pC->pseudoTableReg];
-    assert( u.an.pReg->flags & MEM_Blob );
-    assert( memIsValid(u.an.pReg) );
-    u.an.payloadSize = u.an.pReg->n;
-    u.an.zRec = u.an.pReg->z;
-    u.an.pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr;
-    assert( u.an.payloadSize==0 || u.an.zRec!=0 );
+  }else if( ALWAYS(u.ao.pC->pseudoTableReg>0) ){
+    u.ao.pReg = &aMem[u.ao.pC->pseudoTableReg];
+    if( u.ao.pC->multiPseudo ){
+      sqlite3VdbeMemShallowCopy(u.ao.pDest, u.ao.pReg+u.ao.p2, MEM_Ephem);
+      Deephemeralize(u.ao.pDest);
+      goto op_column_out;
+    }
+    assert( u.ao.pReg->flags & MEM_Blob );
+    assert( memIsValid(u.ao.pReg) );
+    u.ao.payloadSize = u.ao.pReg->n;
+    u.ao.zRec = u.ao.pReg->z;
+    u.ao.pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr;
+    assert( u.ao.payloadSize==0 || u.ao.zRec!=0 );
   }else{
     /* Consider the row to be NULL */
-    u.an.payloadSize = 0;
+    u.ao.payloadSize = 0;
   }
 
-  /* If u.an.payloadSize is 0, then just store a NULL.  This can happen because of
+  /* If u.ao.payloadSize is 0, then just store a NULL.  This can happen because of
   ** nullRow or because of a corrupt database. */
-  if( u.an.payloadSize==0 ){
-    MemSetTypeFlag(u.an.pDest, MEM_Null);
+  if( u.ao.payloadSize==0 ){
+    MemSetTypeFlag(u.ao.pDest, MEM_Null);
     goto op_column_out;
   }
   assert( db->aLimit[SQLITE_LIMIT_LENGTH]>=0 );
-  if( u.an.payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
+  if( u.ao.payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
     goto too_big;
   }
 
-  u.an.nField = u.an.pC->nField;
-  assert( u.an.p2<u.an.nField );
+  u.ao.nField = u.ao.pC->nField;
+  assert( u.ao.p2<u.ao.nField );
 
   /* Read and parse the table header.  Store the results of the parse
   ** into the record header cache fields of the cursor.
   */
-  u.an.aType = u.an.pC->aType;
-  if( u.an.pC->cacheStatus==p->cacheCtr ){
-    u.an.aOffset = u.an.pC->aOffset;
+  u.ao.aType = u.ao.pC->aType;
+  if( u.ao.pC->cacheStatus==p->cacheCtr ){
+    u.ao.aOffset = u.ao.pC->aOffset;
   }else{
-    assert(u.an.aType);
-    u.an.avail = 0;
-    u.an.pC->aOffset = u.an.aOffset = &u.an.aType[u.an.nField];
-    u.an.pC->payloadSize = u.an.payloadSize;
-    u.an.pC->cacheStatus = p->cacheCtr;
+    assert(u.ao.aType);
+    u.ao.avail = 0;
+    u.ao.pC->aOffset = u.ao.aOffset = &u.ao.aType[u.ao.nField];
+    u.ao.pC->payloadSize = u.ao.payloadSize;
+    u.ao.pC->cacheStatus = p->cacheCtr;
 
     /* Figure out how many bytes are in the header */
-    if( u.an.zRec ){
-      u.an.zData = u.an.zRec;
+    if( u.ao.zRec ){
+      u.ao.zData = u.ao.zRec;
     }else{
-      if( u.an.pC->isIndex ){
-        u.an.zData = (char*)sqlite3BtreeKeyFetch(u.an.pCrsr, &u.an.avail);
+      if( u.ao.pC->isIndex ){
+        u.ao.zData = (char*)sqlite3BtreeKeyFetch(u.ao.pCrsr, &u.ao.avail);
       }else{
-        u.an.zData = (char*)sqlite3BtreeDataFetch(u.an.pCrsr, &u.an.avail);
+        u.ao.zData = (char*)sqlite3BtreeDataFetch(u.ao.pCrsr, &u.ao.avail);
       }
       /* If KeyFetch()/DataFetch() managed to get the entire payload,
-      ** save the payload in the u.an.pC->aRow cache.  That will save us from
+      ** save the payload in the u.ao.pC->aRow cache.  That will save us from
       ** having to make additional calls to fetch the content portion of
       ** the record.
       */
-      assert( u.an.avail>=0 );
-      if( u.an.payloadSize <= (u32)u.an.avail ){
-        u.an.zRec = u.an.zData;
-        u.an.pC->aRow = (u8*)u.an.zData;
+      assert( u.ao.avail>=0 );
+      if( u.ao.payloadSize <= (u32)u.ao.avail ){
+        u.ao.zRec = u.ao.zData;
+        u.ao.pC->aRow = (u8*)u.ao.zData;
       }else{
-        u.an.pC->aRow = 0;
+        u.ao.pC->aRow = 0;
       }
     }
     /* The following assert is true in all cases except when
     ** the database file has been corrupted externally.
-    **    assert( u.an.zRec!=0 || u.an.avail>=u.an.payloadSize || u.an.avail>=9 ); */
-    u.an.szHdr = getVarint32((u8*)u.an.zData, u.an.offset);
+    **    assert( u.ao.zRec!=0 || u.ao.avail>=u.ao.payloadSize || u.ao.avail>=9 ); */
+    u.ao.szHdr = getVarint32((u8*)u.ao.zData, u.ao.offset);
 
     /* Make sure a corrupt database has not given us an oversize header.
     ** Do this now to avoid an oversize memory allocation.
@@ -65767,26 +66274,26 @@ case OP_Column: {
     ** 3-byte type for each of the maximum of 32768 columns plus three
     ** extra bytes for the header length itself.  32768*3 + 3 = 98307.
     */
-    if( u.an.offset > 98307 ){
+    if( u.ao.offset > 98307 ){
       rc = SQLITE_CORRUPT_BKPT;
       goto op_column_out;
     }
 
-    /* Compute in u.an.len the number of bytes of data we need to read in order
-    ** to get u.an.nField type values.  u.an.offset is an upper bound on this.  But
-    ** u.an.nField might be significantly less than the true number of columns
-    ** in the table, and in that case, 5*u.an.nField+3 might be smaller than u.an.offset.
-    ** We want to minimize u.an.len in order to limit the size of the memory
-    ** allocation, especially if a corrupt database file has caused u.an.offset
+    /* Compute in u.ao.len the number of bytes of data we need to read in order
+    ** to get u.ao.nField type values.  u.ao.offset is an upper bound on this.  But
+    ** u.ao.nField might be significantly less than the true number of columns
+    ** in the table, and in that case, 5*u.ao.nField+3 might be smaller than u.ao.offset.
+    ** We want to minimize u.ao.len in order to limit the size of the memory
+    ** allocation, especially if a corrupt database file has caused u.ao.offset
     ** to be oversized. Offset is limited to 98307 above.  But 98307 might
     ** still exceed Robson memory allocation limits on some configurations.
-    ** On systems that cannot tolerate large memory allocations, u.an.nField*5+3
-    ** will likely be much smaller since u.an.nField will likely be less than
+    ** On systems that cannot tolerate large memory allocations, u.ao.nField*5+3
+    ** will likely be much smaller since u.ao.nField will likely be less than
     ** 20 or so.  This insures that Robson memory allocation limits are
     ** not exceeded even for corrupt database files.
     */
-    u.an.len = u.an.nField*5 + 3;
-    if( u.an.len > (int)u.an.offset ) u.an.len = (int)u.an.offset;
+    u.ao.len = u.ao.nField*5 + 3;
+    if( u.ao.len > (int)u.ao.offset ) u.ao.len = (int)u.ao.offset;
 
     /* The KeyFetch() or DataFetch() above are fast and will get the entire
     ** record header in most cases.  But they will fail to get the complete
@@ -65794,51 +66301,51 @@ case OP_Column: {
     ** in the B-Tree.  When that happens, use sqlite3VdbeMemFromBtree() to
     ** acquire the complete header text.
     */
-    if( !u.an.zRec && u.an.avail<u.an.len ){
-      u.an.sMem.flags = 0;
-      u.an.sMem.db = 0;
-      rc = sqlite3VdbeMemFromBtree(u.an.pCrsr, 0, u.an.len, u.an.pC->isIndex, &u.an.sMem);
+    if( !u.ao.zRec && u.ao.avail<u.ao.len ){
+      u.ao.sMem.flags = 0;
+      u.ao.sMem.db = 0;
+      rc = sqlite3VdbeMemFromBtree(u.ao.pCrsr, 0, u.ao.len, u.ao.pC->isIndex, &u.ao.sMem);
       if( rc!=SQLITE_OK ){
         goto op_column_out;
       }
-      u.an.zData = u.an.sMem.z;
+      u.ao.zData = u.ao.sMem.z;
     }
-    u.an.zEndHdr = (u8 *)&u.an.zData[u.an.len];
-    u.an.zIdx = (u8 *)&u.an.zData[u.an.szHdr];
+    u.ao.zEndHdr = (u8 *)&u.ao.zData[u.ao.len];
+    u.ao.zIdx = (u8 *)&u.ao.zData[u.ao.szHdr];
 
-    /* Scan the header and use it to fill in the u.an.aType[] and u.an.aOffset[]
-    ** arrays.  u.an.aType[u.an.i] will contain the type integer for the u.an.i-th
-    ** column and u.an.aOffset[u.an.i] will contain the u.an.offset from the beginning
-    ** of the record to the start of the data for the u.an.i-th column
+    /* Scan the header and use it to fill in the u.ao.aType[] and u.ao.aOffset[]
+    ** arrays.  u.ao.aType[u.ao.i] will contain the type integer for the u.ao.i-th
+    ** column and u.ao.aOffset[u.ao.i] will contain the u.ao.offset from the beginning
+    ** of the record to the start of the data for the u.ao.i-th column
     */
-    for(u.an.i=0; u.an.i<u.an.nField; u.an.i++){
-      if( u.an.zIdx<u.an.zEndHdr ){
-        u.an.aOffset[u.an.i] = u.an.offset;
-        if( u.an.zIdx[0]<0x80 ){
-          u.an.t = u.an.zIdx[0];
-          u.an.zIdx++;
+    for(u.ao.i=0; u.ao.i<u.ao.nField; u.ao.i++){
+      if( u.ao.zIdx<u.ao.zEndHdr ){
+        u.ao.aOffset[u.ao.i] = u.ao.offset;
+        if( u.ao.zIdx[0]<0x80 ){
+          u.ao.t = u.ao.zIdx[0];
+          u.ao.zIdx++;
         }else{
-          u.an.zIdx += sqlite3GetVarint32(u.an.zIdx, &u.an.t);
+          u.ao.zIdx += sqlite3GetVarint32(u.ao.zIdx, &u.ao.t);
         }
-        u.an.aType[u.an.i] = u.an.t;
-        u.an.szField = sqlite3VdbeSerialTypeLen(u.an.t);
-        u.an.offset += u.an.szField;
-        if( u.an.offset<u.an.szField ){  /* True if u.an.offset overflows */
-          u.an.zIdx = &u.an.zEndHdr[1];  /* Forces SQLITE_CORRUPT return below */
+        u.ao.aType[u.ao.i] = u.ao.t;
+        u.ao.szField = sqlite3VdbeSerialTypeLen(u.ao.t);
+        u.ao.offset += u.ao.szField;
+        if( u.ao.offset<u.ao.szField ){  /* True if u.ao.offset overflows */
+          u.ao.zIdx = &u.ao.zEndHdr[1];  /* Forces SQLITE_CORRUPT return below */
           break;
         }
       }else{
-        /* If u.an.i is less that u.an.nField, then there are fewer fields in this
+        /* If u.ao.i is less that u.ao.nField, then there are fewer fields in this
         ** record than SetNumColumns indicated there are columns in the
-        ** table. Set the u.an.offset for any extra columns not present in
+        ** table. Set the u.ao.offset for any extra columns not present in
         ** the record to 0. This tells code below to store the default value
         ** for the column instead of deserializing a value from the record.
         */
-        u.an.aOffset[u.an.i] = 0;
+        u.ao.aOffset[u.ao.i] = 0;
       }
     }
-    sqlite3VdbeMemRelease(&u.an.sMem);
-    u.an.sMem.flags = MEM_Null;
+    sqlite3VdbeMemRelease(&u.ao.sMem);
+    u.ao.sMem.flags = MEM_Null;
 
     /* If we have read more header data than was contained in the header,
     ** or if the end of the last field appears to be past the end of the
@@ -65846,78 +66353,78 @@ case OP_Column: {
     ** of the record (when all fields present), then we must be dealing
     ** with a corrupt database.
     */
-    if( (u.an.zIdx > u.an.zEndHdr) || (u.an.offset > u.an.payloadSize)
-         || (u.an.zIdx==u.an.zEndHdr && u.an.offset!=u.an.payloadSize) ){
+    if( (u.ao.zIdx > u.ao.zEndHdr) || (u.ao.offset > u.ao.payloadSize)
+         || (u.ao.zIdx==u.ao.zEndHdr && u.ao.offset!=u.ao.payloadSize) ){
       rc = SQLITE_CORRUPT_BKPT;
       goto op_column_out;
     }
   }
 
-  /* Get the column information. If u.an.aOffset[u.an.p2] is non-zero, then
-  ** deserialize the value from the record. If u.an.aOffset[u.an.p2] is zero,
+  /* Get the column information. If u.ao.aOffset[u.ao.p2] is non-zero, then
+  ** deserialize the value from the record. If u.ao.aOffset[u.ao.p2] is zero,
   ** then there are not enough fields in the record to satisfy the
   ** request.  In this case, set the value NULL or to P4 if P4 is
   ** a pointer to a Mem object.
   */
-  if( u.an.aOffset[u.an.p2] ){
+  if( u.ao.aOffset[u.ao.p2] ){
     assert( rc==SQLITE_OK );
-    if( u.an.zRec ){
+    if( u.ao.zRec ){
       /* This is the common case where the whole row fits on a single page */
-      VdbeMemRelease(u.an.pDest);
-      sqlite3VdbeSerialGet((u8 *)&u.an.zRec[u.an.aOffset[u.an.p2]], u.an.aType[u.an.p2], u.an.pDest);
+      VdbeMemRelease(u.ao.pDest);
+      sqlite3VdbeSerialGet((u8 *)&u.ao.zRec[u.ao.aOffset[u.ao.p2]], u.ao.aType[u.ao.p2], u.ao.pDest);
     }else{
       /* This branch happens only when the row overflows onto multiple pages */
-      u.an.t = u.an.aType[u.an.p2];
+      u.ao.t = u.ao.aType[u.ao.p2];
       if( (pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
-       && ((u.an.t>=12 && (u.an.t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)
+       && ((u.ao.t>=12 && (u.ao.t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)
       ){
         /* Content is irrelevant for the typeof() function and for
         ** the length(X) function if X is a blob.  So we might as well use
         ** bogus content rather than reading content from disk.  NULL works
-        ** for text and blob and whatever is in the u.an.payloadSize64 variable
+        ** for text and blob and whatever is in the u.ao.payloadSize64 variable
         ** will work for everything else. */
-        u.an.zData = u.an.t<12 ? (char*)&u.an.payloadSize64 : 0;
+        u.ao.zData = u.ao.t<12 ? (char*)&u.ao.payloadSize64 : 0;
       }else{
-        u.an.len = sqlite3VdbeSerialTypeLen(u.an.t);
-        sqlite3VdbeMemMove(&u.an.sMem, u.an.pDest);
-        rc = sqlite3VdbeMemFromBtree(u.an.pCrsr, u.an.aOffset[u.an.p2], u.an.len,  u.an.pC->isIndex,
-                                     &u.an.sMem);
+        u.ao.len = sqlite3VdbeSerialTypeLen(u.ao.t);
+        sqlite3VdbeMemMove(&u.ao.sMem, u.ao.pDest);
+        rc = sqlite3VdbeMemFromBtree(u.ao.pCrsr, u.ao.aOffset[u.ao.p2], u.ao.len,  u.ao.pC->isIndex,
+                                     &u.ao.sMem);
         if( rc!=SQLITE_OK ){
           goto op_column_out;
         }
-        u.an.zData = u.an.sMem.z;
+        u.ao.zData = u.ao.sMem.z;
       }
-      sqlite3VdbeSerialGet((u8*)u.an.zData, u.an.t, u.an.pDest);
+      sqlite3VdbeSerialGet((u8*)u.ao.zData, u.ao.t, u.ao.pDest);
     }
-    u.an.pDest->enc = encoding;
+    u.ao.pDest->enc = encoding;
   }else{
     if( pOp->p4type==P4_MEM ){
-      sqlite3VdbeMemShallowCopy(u.an.pDest, pOp->p4.pMem, MEM_Static);
+      sqlite3VdbeMemShallowCopy(u.ao.pDest, pOp->p4.pMem, MEM_Static);
     }else{
-      MemSetTypeFlag(u.an.pDest, MEM_Null);
+      MemSetTypeFlag(u.ao.pDest, MEM_Null);
     }
   }
 
   /* If we dynamically allocated space to hold the data (in the
   ** sqlite3VdbeMemFromBtree() call above) then transfer control of that
-  ** dynamically allocated space over to the u.an.pDest structure.
+  ** dynamically allocated space over to the u.ao.pDest structure.
   ** This prevents a memory copy.
   */
-  if( u.an.sMem.zMalloc ){
-    assert( u.an.sMem.z==u.an.sMem.zMalloc );
-    assert( !(u.an.pDest->flags & MEM_Dyn) );
-    assert( !(u.an.pDest->flags & (MEM_Blob|MEM_Str)) || u.an.pDest->z==u.an.sMem.z );
-    u.an.pDest->flags &= ~(MEM_Ephem|MEM_Static);
-    u.an.pDest->flags |= MEM_Term;
-    u.an.pDest->z = u.an.sMem.z;
-    u.an.pDest->zMalloc = u.an.sMem.zMalloc;
+  if( u.ao.sMem.zMalloc ){
+    assert( u.ao.sMem.z==u.ao.sMem.zMalloc );
+    assert( !(u.ao.pDest->flags & MEM_Dyn) );
+    assert( !(u.ao.pDest->flags & (MEM_Blob|MEM_Str)) || u.ao.pDest->z==u.ao.sMem.z );
+    u.ao.pDest->flags &= ~(MEM_Ephem|MEM_Static);
+    u.ao.pDest->flags |= MEM_Term;
+    u.ao.pDest->z = u.ao.sMem.z;
+    u.ao.pDest->zMalloc = u.ao.sMem.zMalloc;
   }
 
-  rc = sqlite3VdbeMemMakeWriteable(u.an.pDest);
+  rc = sqlite3VdbeMemMakeWriteable(u.ao.pDest);
 
 op_column_out:
-  UPDATE_MAX_BLOBSIZE(u.an.pDest);
-  REGISTER_TRACE(pOp->p3, u.an.pDest);
+  UPDATE_MAX_BLOBSIZE(u.ao.pDest);
+  REGISTER_TRACE(pOp->p3, u.ao.pDest);
   break;
 }
 
@@ -65930,20 +66437,20 @@ op_column_out:
 ** memory cell in the range.
 */
 case OP_Affinity: {
-#if 0  /* local variables moved into u.ao */
+#if 0  /* local variables moved into u.ap */
   const char *zAffinity;   /* The affinity to be applied */
   char cAff;               /* A single character of affinity */
-#endif /* local variables moved into u.ao */
+#endif /* local variables moved into u.ap */
 
-  u.ao.zAffinity = pOp->p4.z;
-  assert( u.ao.zAffinity!=0 );
-  assert( u.ao.zAffinity[pOp->p2]==0 );
+  u.ap.zAffinity = pOp->p4.z;
+  assert( u.ap.zAffinity!=0 );
+  assert( u.ap.zAffinity[pOp->p2]==0 );
   pIn1 = &aMem[pOp->p1];
-  while( (u.ao.cAff = *(u.ao.zAffinity++))!=0 ){
+  while( (u.ap.cAff = *(u.ap.zAffinity++))!=0 ){
     assert( pIn1 <= &p->aMem[p->nMem] );
     assert( memIsValid(pIn1) );
     ExpandBlob(pIn1);
-    applyAffinity(pIn1, u.ao.cAff, encoding);
+    applyAffinity(pIn1, u.ap.cAff, encoding);
     pIn1++;
   }
   break;
@@ -65965,7 +66472,7 @@ case OP_Affinity: {
 ** If P4 is NULL then all index fields have the affinity NONE.
 */
 case OP_MakeRecord: {
-#if 0  /* local variables moved into u.ap */
+#if 0  /* local variables moved into u.aq */
   u8 *zNewRecord;        /* A buffer to hold the data for the new record */
   Mem *pRec;             /* The new record */
   u64 nData;             /* Number of bytes of data space */
@@ -65981,7 +66488,7 @@ case OP_MakeRecord: {
   int file_format;       /* File format to use for encoding */
   int i;                 /* Space used in zNewRecord[] */
   int len;               /* Length of a field */
-#endif /* local variables moved into u.ap */
+#endif /* local variables moved into u.aq */
 
   /* Assuming the record contains N fields, the record format looks
   ** like this:
@@ -65998,16 +66505,16 @@ case OP_MakeRecord: {
   ** hdr-size field is also a varint which is the offset from the beginning
   ** of the record to data0.
   */
-  u.ap.nData = 0;         /* Number of bytes of data space */
-  u.ap.nHdr = 0;          /* Number of bytes of header space */
-  u.ap.nZero = 0;         /* Number of zero bytes at the end of the record */
-  u.ap.nField = pOp->p1;
-  u.ap.zAffinity = pOp->p4.z;
-  assert( u.ap.nField>0 && pOp->p2>0 && pOp->p2+u.ap.nField<=p->nMem+1 );
-  u.ap.pData0 = &aMem[u.ap.nField];
-  u.ap.nField = pOp->p2;
-  u.ap.pLast = &u.ap.pData0[u.ap.nField-1];
-  u.ap.file_format = p->minWriteFileFormat;
+  u.aq.nData = 0;         /* Number of bytes of data space */
+  u.aq.nHdr = 0;          /* Number of bytes of header space */
+  u.aq.nZero = 0;         /* Number of zero bytes at the end of the record */
+  u.aq.nField = pOp->p1;
+  u.aq.zAffinity = pOp->p4.z;
+  assert( u.aq.nField>0 && pOp->p2>0 && pOp->p2+u.aq.nField<=p->nMem+1 );
+  u.aq.pData0 = &aMem[u.aq.nField];
+  u.aq.nField = pOp->p2;
+  u.aq.pLast = &u.aq.pData0[u.aq.nField-1];
+  u.aq.file_format = p->minWriteFileFormat;
 
   /* Identify the output register */
   assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 );
@@ -66017,34 +66524,34 @@ case OP_MakeRecord: {
   /* Loop through the elements that will make up the record to figure
   ** out how much space is required for the new record.
   */
-  for(u.ap.pRec=u.ap.pData0; u.ap.pRec<=u.ap.pLast; u.ap.pRec++){
-    assert( memIsValid(u.ap.pRec) );
-    if( u.ap.zAffinity ){
-      applyAffinity(u.ap.pRec, u.ap.zAffinity[u.ap.pRec-u.ap.pData0], encoding);
+  for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){
+    assert( memIsValid(u.aq.pRec) );
+    if( u.aq.zAffinity ){
+      applyAffinity(u.aq.pRec, u.aq.zAffinity[u.aq.pRec-u.aq.pData0], encoding);
     }
-    if( u.ap.pRec->flags&MEM_Zero && u.ap.pRec->n>0 ){
-      sqlite3VdbeMemExpandBlob(u.ap.pRec);
+    if( u.aq.pRec->flags&MEM_Zero && u.aq.pRec->n>0 ){
+      sqlite3VdbeMemExpandBlob(u.aq.pRec);
     }
-    u.ap.serial_type = sqlite3VdbeSerialType(u.ap.pRec, u.ap.file_format);
-    u.ap.len = sqlite3VdbeSerialTypeLen(u.ap.serial_type);
-    u.ap.nData += u.ap.len;
-    u.ap.nHdr += sqlite3VarintLen(u.ap.serial_type);
-    if( u.ap.pRec->flags & MEM_Zero ){
+    u.aq.serial_type = sqlite3VdbeSerialType(u.aq.pRec, u.aq.file_format);
+    u.aq.len = sqlite3VdbeSerialTypeLen(u.aq.serial_type);
+    u.aq.nData += u.aq.len;
+    u.aq.nHdr += sqlite3VarintLen(u.aq.serial_type);
+    if( u.aq.pRec->flags & MEM_Zero ){
       /* Only pure zero-filled BLOBs can be input to this Opcode.
       ** We do not allow blobs with a prefix and a zero-filled tail. */
-      u.ap.nZero += u.ap.pRec->u.nZero;
-    }else if( u.ap.len ){
-      u.ap.nZero = 0;
+      u.aq.nZero += u.aq.pRec->u.nZero;
+    }else if( u.aq.len ){
+      u.aq.nZero = 0;
     }
   }
 
   /* Add the initial header varint and total the size */
-  u.ap.nHdr += u.ap.nVarint = sqlite3VarintLen(u.ap.nHdr);
-  if( u.ap.nVarint<sqlite3VarintLen(u.ap.nHdr) ){
-    u.ap.nHdr++;
+  u.aq.nHdr += u.aq.nVarint = sqlite3VarintLen(u.aq.nHdr);
+  if( u.aq.nVarint<sqlite3VarintLen(u.aq.nHdr) ){
+    u.aq.nHdr++;
   }
-  u.ap.nByte = u.ap.nHdr+u.ap.nData-u.ap.nZero;
-  if( u.ap.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+  u.aq.nByte = u.aq.nHdr+u.aq.nData-u.aq.nZero;
+  if( u.aq.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
     goto too_big;
   }
 
@@ -66053,28 +66560,28 @@ case OP_MakeRecord: {
   ** be one of the input registers (because the following call to
   ** sqlite3VdbeMemGrow() could clobber the value before it is used).
   */
-  if( sqlite3VdbeMemGrow(pOut, (int)u.ap.nByte, 0) ){
+  if( sqlite3VdbeMemGrow(pOut, (int)u.aq.nByte, 0) ){
     goto no_mem;
   }
-  u.ap.zNewRecord = (u8 *)pOut->z;
+  u.aq.zNewRecord = (u8 *)pOut->z;
 
   /* Write the record */
-  u.ap.i = putVarint32(u.ap.zNewRecord, u.ap.nHdr);
-  for(u.ap.pRec=u.ap.pData0; u.ap.pRec<=u.ap.pLast; u.ap.pRec++){
-    u.ap.serial_type = sqlite3VdbeSerialType(u.ap.pRec, u.ap.file_format);
-    u.ap.i += putVarint32(&u.ap.zNewRecord[u.ap.i], u.ap.serial_type);      /* serial type */
+  u.aq.i = putVarint32(u.aq.zNewRecord, u.aq.nHdr);
+  for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){
+    u.aq.serial_type = sqlite3VdbeSerialType(u.aq.pRec, u.aq.file_format);
+    u.aq.i += putVarint32(&u.aq.zNewRecord[u.aq.i], u.aq.serial_type);      /* serial type */
   }
-  for(u.ap.pRec=u.ap.pData0; u.ap.pRec<=u.ap.pLast; u.ap.pRec++){  /* serial data */
-    u.ap.i += sqlite3VdbeSerialPut(&u.ap.zNewRecord[u.ap.i], (int)(u.ap.nByte-u.ap.i), u.ap.pRec,u.ap.file_format);
+  for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){  /* serial data */
+    u.aq.i += sqlite3VdbeSerialPut(&u.aq.zNewRecord[u.aq.i], (int)(u.aq.nByte-u.aq.i), u.aq.pRec,u.aq.file_format);
   }
-  assert( u.ap.i==u.ap.nByte );
+  assert( u.aq.i==u.aq.nByte );
 
   assert( pOp->p3>0 && pOp->p3<=p->nMem );
-  pOut->n = (int)u.ap.nByte;
+  pOut->n = (int)u.aq.nByte;
   pOut->flags = MEM_Blob | MEM_Dyn;
   pOut->xDel = 0;
-  if( u.ap.nZero ){
-    pOut->u.nZero = u.ap.nZero;
+  if( u.aq.nZero ){
+    pOut->u.nZero = u.aq.nZero;
     pOut->flags |= MEM_Zero;
   }
   pOut->enc = SQLITE_UTF8;  /* In case the blob is ever converted to text */
@@ -66090,18 +66597,18 @@ case OP_MakeRecord: {
 */
 #ifndef SQLITE_OMIT_BTREECOUNT
 case OP_Count: {         /* out2-prerelease */
-#if 0  /* local variables moved into u.aq */
+#if 0  /* local variables moved into u.ar */
   i64 nEntry;
   BtCursor *pCrsr;
-#endif /* local variables moved into u.aq */
+#endif /* local variables moved into u.ar */
 
-  u.aq.pCrsr = p->apCsr[pOp->p1]->pCursor;
-  if( ALWAYS(u.aq.pCrsr) ){
-    rc = sqlite3BtreeCount(u.aq.pCrsr, &u.aq.nEntry);
+  u.ar.pCrsr = p->apCsr[pOp->p1]->pCursor;
+  if( ALWAYS(u.ar.pCrsr) ){
+    rc = sqlite3BtreeCount(u.ar.pCrsr, &u.ar.nEntry);
   }else{
-    u.aq.nEntry = 0;
+    u.ar.nEntry = 0;
   }
-  pOut->u.i = u.aq.nEntry;
+  pOut->u.i = u.ar.nEntry;
   break;
 }
 #endif
@@ -66113,7 +66620,7 @@ case OP_Count: {         /* out2-prerelease */
 ** existing savepoint, P1==1, or to rollback an existing savepoint P1==2.
 */
 case OP_Savepoint: {
-#if 0  /* local variables moved into u.ar */
+#if 0  /* local variables moved into u.as */
   int p1;                         /* Value of P1 operand */
   char *zName;                    /* Name of savepoint */
   int nName;
@@ -66122,20 +66629,20 @@ case OP_Savepoint: {
   Savepoint *pTmp;
   int iSavepoint;
   int ii;
-#endif /* local variables moved into u.ar */
+#endif /* local variables moved into u.as */
 
-  u.ar.p1 = pOp->p1;
-  u.ar.zName = pOp->p4.z;
+  u.as.p1 = pOp->p1;
+  u.as.zName = pOp->p4.z;
 
-  /* Assert that the u.ar.p1 parameter is valid. Also that if there is no open
+  /* Assert that the u.as.p1 parameter is valid. Also that if there is no open
   ** transaction, then there cannot be any savepoints.
   */
   assert( db->pSavepoint==0 || db->autoCommit==0 );
-  assert( u.ar.p1==SAVEPOINT_BEGIN||u.ar.p1==SAVEPOINT_RELEASE||u.ar.p1==SAVEPOINT_ROLLBACK );
+  assert( u.as.p1==SAVEPOINT_BEGIN||u.as.p1==SAVEPOINT_RELEASE||u.as.p1==SAVEPOINT_ROLLBACK );
   assert( db->pSavepoint || db->isTransactionSavepoint==0 );
   assert( checkSavepointCount(db) );
 
-  if( u.ar.p1==SAVEPOINT_BEGIN ){
+  if( u.as.p1==SAVEPOINT_BEGIN ){
     if( db->writeVdbeCnt>0 ){
       /* A new savepoint cannot be created if there are active write
       ** statements (i.e. open read/write incremental blob handles).
@@ -66144,7 +66651,7 @@ case OP_Savepoint: {
         "SQL statements in progress");
       rc = SQLITE_BUSY;
     }else{
-      u.ar.nName = sqlite3Strlen30(u.ar.zName);
+      u.as.nName = sqlite3Strlen30(u.as.zName);
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
       /* This call is Ok even if this savepoint is actually a transaction
@@ -66158,10 +66665,10 @@ case OP_Savepoint: {
 #endif
 
       /* Create a new savepoint structure. */
-      u.ar.pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+u.ar.nName+1);
-      if( u.ar.pNew ){
-        u.ar.pNew->zName = (char *)&u.ar.pNew[1];
-        memcpy(u.ar.pNew->zName, u.ar.zName, u.ar.nName+1);
+      u.as.pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+u.as.nName+1);
+      if( u.as.pNew ){
+        u.as.pNew->zName = (char *)&u.as.pNew[1];
+        memcpy(u.as.pNew->zName, u.as.zName, u.as.nName+1);
 
         /* If there is no open transaction, then mark this as a special
         ** "transaction savepoint". */
@@ -66173,27 +66680,27 @@ case OP_Savepoint: {
         }
 
         /* Link the new savepoint into the database handle's list. */
-        u.ar.pNew->pNext = db->pSavepoint;
-        db->pSavepoint = u.ar.pNew;
-        u.ar.pNew->nDeferredCons = db->nDeferredCons;
+        u.as.pNew->pNext = db->pSavepoint;
+        db->pSavepoint = u.as.pNew;
+        u.as.pNew->nDeferredCons = db->nDeferredCons;
       }
     }
   }else{
-    u.ar.iSavepoint = 0;
+    u.as.iSavepoint = 0;
 
     /* Find the named savepoint. If there is no such savepoint, then an
     ** an error is returned to the user.  */
     for(
-      u.ar.pSavepoint = db->pSavepoint;
-      u.ar.pSavepoint && sqlite3StrICmp(u.ar.pSavepoint->zName, u.ar.zName);
-      u.ar.pSavepoint = u.ar.pSavepoint->pNext
+      u.as.pSavepoint = db->pSavepoint;
+      u.as.pSavepoint && sqlite3StrICmp(u.as.pSavepoint->zName, u.as.zName);
+      u.as.pSavepoint = u.as.pSavepoint->pNext
     ){
-      u.ar.iSavepoint++;
+      u.as.iSavepoint++;
     }
-    if( !u.ar.pSavepoint ){
-      sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.ar.zName);
+    if( !u.as.pSavepoint ){
+      sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.as.zName);
       rc = SQLITE_ERROR;
-    }else if( db->writeVdbeCnt>0 && u.ar.p1==SAVEPOINT_RELEASE ){
+    }else if( db->writeVdbeCnt>0 && u.as.p1==SAVEPOINT_RELEASE ){
       /* It is not possible to release (commit) a savepoint if there are
       ** active write statements.
       */
@@ -66207,8 +66714,8 @@ case OP_Savepoint: {
       ** and this is a RELEASE command, then the current transaction
       ** is committed.
       */
-      int isTransaction = u.ar.pSavepoint->pNext==0 && db->isTransactionSavepoint;
-      if( isTransaction && u.ar.p1==SAVEPOINT_RELEASE ){
+      int isTransaction = u.as.pSavepoint->pNext==0 && db->isTransactionSavepoint;
+      if( isTransaction && u.as.p1==SAVEPOINT_RELEASE ){
         if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
           goto vdbe_return;
         }
@@ -66222,19 +66729,19 @@ case OP_Savepoint: {
         db->isTransactionSavepoint = 0;
         rc = p->rc;
       }else{
-        u.ar.iSavepoint = db->nSavepoint - u.ar.iSavepoint - 1;
-        if( u.ar.p1==SAVEPOINT_ROLLBACK ){
-          for(u.ar.ii=0; u.ar.ii<db->nDb; u.ar.ii++){
-            sqlite3BtreeTripAllCursors(db->aDb[u.ar.ii].pBt, SQLITE_ABORT);
+        u.as.iSavepoint = db->nSavepoint - u.as.iSavepoint - 1;
+        if( u.as.p1==SAVEPOINT_ROLLBACK ){
+          for(u.as.ii=0; u.as.ii<db->nDb; u.as.ii++){
+            sqlite3BtreeTripAllCursors(db->aDb[u.as.ii].pBt, SQLITE_ABORT);
           }
         }
-        for(u.ar.ii=0; u.ar.ii<db->nDb; u.ar.ii++){
-          rc = sqlite3BtreeSavepoint(db->aDb[u.ar.ii].pBt, u.ar.p1, u.ar.iSavepoint);
+        for(u.as.ii=0; u.as.ii<db->nDb; u.as.ii++){
+          rc = sqlite3BtreeSavepoint(db->aDb[u.as.ii].pBt, u.as.p1, u.as.iSavepoint);
           if( rc!=SQLITE_OK ){
             goto abort_due_to_error;
           }
         }
-        if( u.ar.p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
+        if( u.as.p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
           sqlite3ExpirePreparedStatements(db);
           sqlite3ResetAllSchemasOfConnection(db);
           db->flags = (db->flags | SQLITE_InternChanges);
@@ -66243,10 +66750,10 @@ case OP_Savepoint: {
 
       /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all
       ** savepoints nested inside of the savepoint being operated on. */
-      while( db->pSavepoint!=u.ar.pSavepoint ){
-        u.ar.pTmp = db->pSavepoint;
-        db->pSavepoint = u.ar.pTmp->pNext;
-        sqlite3DbFree(db, u.ar.pTmp);
+      while( db->pSavepoint!=u.as.pSavepoint ){
+        u.as.pTmp = db->pSavepoint;
+        db->pSavepoint = u.as.pTmp->pNext;
+        sqlite3DbFree(db, u.as.pTmp);
         db->nSavepoint--;
       }
 
@@ -66254,19 +66761,19 @@ case OP_Savepoint: {
       ** too. If it is a ROLLBACK TO, then set the number of deferred
       ** constraint violations present in the database to the value stored
       ** when the savepoint was created.  */
-      if( u.ar.p1==SAVEPOINT_RELEASE ){
-        assert( u.ar.pSavepoint==db->pSavepoint );
-        db->pSavepoint = u.ar.pSavepoint->pNext;
-        sqlite3DbFree(db, u.ar.pSavepoint);
+      if( u.as.p1==SAVEPOINT_RELEASE ){
+        assert( u.as.pSavepoint==db->pSavepoint );
+        db->pSavepoint = u.as.pSavepoint->pNext;
+        sqlite3DbFree(db, u.as.pSavepoint);
         if( !isTransaction ){
           db->nSavepoint--;
         }
       }else{
-        db->nDeferredCons = u.ar.pSavepoint->nDeferredCons;
+        db->nDeferredCons = u.as.pSavepoint->nDeferredCons;
       }
 
       if( !isTransaction ){
-        rc = sqlite3VtabSavepoint(db, u.ar.p1, u.ar.iSavepoint);
+        rc = sqlite3VtabSavepoint(db, u.as.p1, u.as.iSavepoint);
         if( rc!=SQLITE_OK ) goto abort_due_to_error;
       }
     }
@@ -66285,21 +66792,21 @@ case OP_Savepoint: {
 ** This instruction causes the VM to halt.
 */
 case OP_AutoCommit: {
-#if 0  /* local variables moved into u.as */
+#if 0  /* local variables moved into u.at */
   int desiredAutoCommit;
   int iRollback;
   int turnOnAC;
-#endif /* local variables moved into u.as */
+#endif /* local variables moved into u.at */
 
-  u.as.desiredAutoCommit = pOp->p1;
-  u.as.iRollback = pOp->p2;
-  u.as.turnOnAC = u.as.desiredAutoCommit && !db->autoCommit;
-  assert( u.as.desiredAutoCommit==1 || u.as.desiredAutoCommit==0 );
-  assert( u.as.desiredAutoCommit==1 || u.as.iRollback==0 );
+  u.at.desiredAutoCommit = pOp->p1;
+  u.at.iRollback = pOp->p2;
+  u.at.turnOnAC = u.at.desiredAutoCommit && !db->autoCommit;
+  assert( u.at.desiredAutoCommit==1 || u.at.desiredAutoCommit==0 );
+  assert( u.at.desiredAutoCommit==1 || u.at.iRollback==0 );
   assert( db->activeVdbeCnt>0 );  /* At least this one VM is active */
 
 #if 0
-  if( u.as.turnOnAC && u.as.iRollback && db->activeVdbeCnt>1 ){
+  if( u.at.turnOnAC && u.at.iRollback && db->activeVdbeCnt>1 ){
     /* If this instruction implements a ROLLBACK and other VMs are
     ** still running, and a transaction is active, return an error indicating
     ** that the other VMs must complete first.
@@ -66309,25 +66816,25 @@ case OP_AutoCommit: {
     rc = SQLITE_BUSY;
   }else
 #endif
-  if( u.as.turnOnAC && !u.as.iRollback && db->writeVdbeCnt>0 ){
+  if( u.at.turnOnAC && !u.at.iRollback && db->writeVdbeCnt>0 ){
     /* If this instruction implements a COMMIT and other VMs are writing
     ** return an error indicating that the other VMs must complete first.
     */
     sqlite3SetString(&p->zErrMsg, db, "cannot commit transaction - "
         "SQL statements in progress");
     rc = SQLITE_BUSY;
-  }else if( u.as.desiredAutoCommit!=db->autoCommit ){
-    if( u.as.iRollback ){
-      assert( u.as.desiredAutoCommit==1 );
+  }else if( u.at.desiredAutoCommit!=db->autoCommit ){
+    if( u.at.iRollback ){
+      assert( u.at.desiredAutoCommit==1 );
       sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
       db->autoCommit = 1;
     }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
       goto vdbe_return;
     }else{
-      db->autoCommit = (u8)u.as.desiredAutoCommit;
+      db->autoCommit = (u8)u.at.desiredAutoCommit;
       if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
         p->pc = pc;
-        db->autoCommit = (u8)(1-u.as.desiredAutoCommit);
+        db->autoCommit = (u8)(1-u.at.desiredAutoCommit);
         p->rc = rc = SQLITE_BUSY;
         goto vdbe_return;
       }
@@ -66342,8 +66849,8 @@ case OP_AutoCommit: {
     goto vdbe_return;
   }else{
     sqlite3SetString(&p->zErrMsg, db,
-        (!u.as.desiredAutoCommit)?"cannot start a transaction within a transaction":(
-        (u.as.iRollback)?"cannot rollback - no transaction is active":
+        (!u.at.desiredAutoCommit)?"cannot start a transaction within a transaction":(
+        (u.at.iRollback)?"cannot rollback - no transaction is active":
                    "cannot commit - no transaction is active"));
 
     rc = SQLITE_ERROR;
@@ -66383,16 +66890,16 @@ case OP_AutoCommit: {
 ** If P2 is zero, then a read-lock is obtained on the database file.
 */
 case OP_Transaction: {
-#if 0  /* local variables moved into u.at */
+#if 0  /* local variables moved into u.au */
   Btree *pBt;
-#endif /* local variables moved into u.at */
+#endif /* local variables moved into u.au */
 
   assert( pOp->p1>=0 && pOp->p1<db->nDb );
   assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
-  u.at.pBt = db->aDb[pOp->p1].pBt;
+  u.au.pBt = db->aDb[pOp->p1].pBt;
 
-  if( u.at.pBt ){
-    rc = sqlite3BtreeBeginTrans(u.at.pBt, pOp->p2);
+  if( u.au.pBt ){
+    rc = sqlite3BtreeBeginTrans(u.au.pBt, pOp->p2);
     if( rc==SQLITE_BUSY ){
       p->pc = pc;
       p->rc = rc = SQLITE_BUSY;
@@ -66405,7 +66912,7 @@ case OP_Transaction: {
     if( pOp->p2 && p->usesStmtJournal
      && (db->autoCommit==0 || db->activeVdbeCnt>1)
     ){
-      assert( sqlite3BtreeIsInTrans(u.at.pBt) );
+      assert( sqlite3BtreeIsInTrans(u.au.pBt) );
       if( p->iStatement==0 ){
         assert( db->nStatement>=0 && db->nSavepoint>=0 );
         db->nStatement++;
@@ -66414,7 +66921,7 @@ case OP_Transaction: {
 
       rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement-1);
       if( rc==SQLITE_OK ){
-        rc = sqlite3BtreeBeginStmt(u.at.pBt, p->iStatement);
+        rc = sqlite3BtreeBeginStmt(u.au.pBt, p->iStatement);
       }
 
       /* Store the current value of the database handles deferred constraint
@@ -66439,21 +66946,21 @@ case OP_Transaction: {
 ** executing this instruction.
 */
 case OP_ReadCookie: {               /* out2-prerelease */
-#if 0  /* local variables moved into u.au */
+#if 0  /* local variables moved into u.av */
   int iMeta;
   int iDb;
   int iCookie;
-#endif /* local variables moved into u.au */
+#endif /* local variables moved into u.av */
 
-  u.au.iDb = pOp->p1;
-  u.au.iCookie = pOp->p3;
+  u.av.iDb = pOp->p1;
+  u.av.iCookie = pOp->p3;
   assert( pOp->p3<SQLITE_N_BTREE_META );
-  assert( u.au.iDb>=0 && u.au.iDb<db->nDb );
-  assert( db->aDb[u.au.iDb].pBt!=0 );
-  assert( (p->btreeMask & (((yDbMask)1)<<u.au.iDb))!=0 );
+  assert( u.av.iDb>=0 && u.av.iDb<db->nDb );
+  assert( db->aDb[u.av.iDb].pBt!=0 );
+  assert( (p->btreeMask & (((yDbMask)1)<<u.av.iDb))!=0 );
 
-  sqlite3BtreeGetMeta(db->aDb[u.au.iDb].pBt, u.au.iCookie, (u32 *)&u.au.iMeta);
-  pOut->u.i = u.au.iMeta;
+  sqlite3BtreeGetMeta(db->aDb[u.av.iDb].pBt, u.av.iCookie, (u32 *)&u.av.iMeta);
+  pOut->u.i = u.av.iMeta;
   break;
 }
 
@@ -66468,26 +66975,26 @@ case OP_ReadCookie: {               /* out2-prerelease */
 ** A transaction must be started before executing this opcode.
 */
 case OP_SetCookie: {       /* in3 */
-#if 0  /* local variables moved into u.av */
+#if 0  /* local variables moved into u.aw */
   Db *pDb;
-#endif /* local variables moved into u.av */
+#endif /* local variables moved into u.aw */
   assert( pOp->p2<SQLITE_N_BTREE_META );
   assert( pOp->p1>=0 && pOp->p1<db->nDb );
   assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
-  u.av.pDb = &db->aDb[pOp->p1];
-  assert( u.av.pDb->pBt!=0 );
+  u.aw.pDb = &db->aDb[pOp->p1];
+  assert( u.aw.pDb->pBt!=0 );
   assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
   pIn3 = &aMem[pOp->p3];
   sqlite3VdbeMemIntegerify(pIn3);
   /* See note about index shifting on OP_ReadCookie */
-  rc = sqlite3BtreeUpdateMeta(u.av.pDb->pBt, pOp->p2, (int)pIn3->u.i);
+  rc = sqlite3BtreeUpdateMeta(u.aw.pDb->pBt, pOp->p2, (int)pIn3->u.i);
   if( pOp->p2==BTREE_SCHEMA_VERSION ){
     /* When the schema cookie changes, record the new cookie internally */
-    u.av.pDb->pSchema->schema_cookie = (int)pIn3->u.i;
+    u.aw.pDb->pSchema->schema_cookie = (int)pIn3->u.i;
     db->flags |= SQLITE_InternChanges;
   }else if( pOp->p2==BTREE_FILE_FORMAT ){
     /* Record changes in the file format */
-    u.av.pDb->pSchema->file_format = (u8)pIn3->u.i;
+    u.aw.pDb->pSchema->file_format = (u8)pIn3->u.i;
   }
   if( pOp->p1==1 ){
     /* Invalidate all prepared statements whenever the TEMP database
@@ -66517,23 +67024,23 @@ case OP_SetCookie: {       /* in3 */
 ** invoked.
 */
 case OP_VerifyCookie: {
-#if 0  /* local variables moved into u.aw */
+#if 0  /* local variables moved into u.ax */
   int iMeta;
   int iGen;
   Btree *pBt;
-#endif /* local variables moved into u.aw */
+#endif /* local variables moved into u.ax */
 
   assert( pOp->p1>=0 && pOp->p1<db->nDb );
   assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
   assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
-  u.aw.pBt = db->aDb[pOp->p1].pBt;
-  if( u.aw.pBt ){
-    sqlite3BtreeGetMeta(u.aw.pBt, BTREE_SCHEMA_VERSION, (u32 *)&u.aw.iMeta);
-    u.aw.iGen = db->aDb[pOp->p1].pSchema->iGeneration;
+  u.ax.pBt = db->aDb[pOp->p1].pBt;
+  if( u.ax.pBt ){
+    sqlite3BtreeGetMeta(u.ax.pBt, BTREE_SCHEMA_VERSION, (u32 *)&u.ax.iMeta);
+    u.ax.iGen = db->aDb[pOp->p1].pSchema->iGeneration;
   }else{
-    u.aw.iGen = u.aw.iMeta = 0;
+    u.ax.iGen = u.ax.iMeta = 0;
   }
-  if( u.aw.iMeta!=pOp->p2 || u.aw.iGen!=pOp->p3 ){
+  if( u.ax.iMeta!=pOp->p2 || u.ax.iGen!=pOp->p3 ){
     sqlite3DbFree(db, p->zErrMsg);
     p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
     /* If the schema-cookie from the database file matches the cookie
@@ -66549,7 +67056,7 @@ case OP_VerifyCookie: {
     ** to be invalidated whenever sqlite3_step() is called from within
     ** a v-table method.
     */
-    if( db->aDb[pOp->p1].pSchema->schema_cookie!=u.aw.iMeta ){
+    if( db->aDb[pOp->p1].pSchema->schema_cookie!=u.ax.iMeta ){
       sqlite3ResetOneSchema(db, pOp->p1);
     }
 
@@ -66610,7 +67117,7 @@ case OP_VerifyCookie: {
 */
 case OP_OpenRead:
 case OP_OpenWrite: {
-#if 0  /* local variables moved into u.ax */
+#if 0  /* local variables moved into u.ay */
   int nField;
   KeyInfo *pKeyInfo;
   int p2;
@@ -66619,7 +67126,7 @@ case OP_OpenWrite: {
   Btree *pX;
   VdbeCursor *pCur;
   Db *pDb;
-#endif /* local variables moved into u.ax */
+#endif /* local variables moved into u.ay */
 
   assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 );
   assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 );
@@ -66629,57 +67136,57 @@ case OP_OpenWrite: {
     break;
   }
 
-  u.ax.nField = 0;
-  u.ax.pKeyInfo = 0;
-  u.ax.p2 = pOp->p2;
-  u.ax.iDb = pOp->p3;
-  assert( u.ax.iDb>=0 && u.ax.iDb<db->nDb );
-  assert( (p->btreeMask & (((yDbMask)1)<<u.ax.iDb))!=0 );
-  u.ax.pDb = &db->aDb[u.ax.iDb];
-  u.ax.pX = u.ax.pDb->pBt;
-  assert( u.ax.pX!=0 );
+  u.ay.nField = 0;
+  u.ay.pKeyInfo = 0;
+  u.ay.p2 = pOp->p2;
+  u.ay.iDb = pOp->p3;
+  assert( u.ay.iDb>=0 && u.ay.iDb<db->nDb );
+  assert( (p->btreeMask & (((yDbMask)1)<<u.ay.iDb))!=0 );
+  u.ay.pDb = &db->aDb[u.ay.iDb];
+  u.ay.pX = u.ay.pDb->pBt;
+  assert( u.ay.pX!=0 );
   if( pOp->opcode==OP_OpenWrite ){
-    u.ax.wrFlag = 1;
-    assert( sqlite3SchemaMutexHeld(db, u.ax.iDb, 0) );
-    if( u.ax.pDb->pSchema->file_format < p->minWriteFileFormat ){
-      p->minWriteFileFormat = u.ax.pDb->pSchema->file_format;
+    u.ay.wrFlag = 1;
+    assert( sqlite3SchemaMutexHeld(db, u.ay.iDb, 0) );
+    if( u.ay.pDb->pSchema->file_format < p->minWriteFileFormat ){
+      p->minWriteFileFormat = u.ay.pDb->pSchema->file_format;
     }
   }else{
-    u.ax.wrFlag = 0;
+    u.ay.wrFlag = 0;
   }
   if( pOp->p5 & OPFLAG_P2ISREG ){
-    assert( u.ax.p2>0 );
-    assert( u.ax.p2<=p->nMem );
-    pIn2 = &aMem[u.ax.p2];
+    assert( u.ay.p2>0 );
+    assert( u.ay.p2<=p->nMem );
+    pIn2 = &aMem[u.ay.p2];
     assert( memIsValid(pIn2) );
     assert( (pIn2->flags & MEM_Int)!=0 );
     sqlite3VdbeMemIntegerify(pIn2);
-    u.ax.p2 = (int)pIn2->u.i;
-    /* The u.ax.p2 value always comes from a prior OP_CreateTable opcode and
-    ** that opcode will always set the u.ax.p2 value to 2 or more or else fail.
+    u.ay.p2 = (int)pIn2->u.i;
+    /* The u.ay.p2 value always comes from a prior OP_CreateTable opcode and
+    ** that opcode will always set the u.ay.p2 value to 2 or more or else fail.
     ** If there were a failure, the prepared statement would have halted
     ** before reaching this instruction. */
-    if( NEVER(u.ax.p2<2) ) {
+    if( NEVER(u.ay.p2<2) ) {
       rc = SQLITE_CORRUPT_BKPT;
       goto abort_due_to_error;
     }
   }
   if( pOp->p4type==P4_KEYINFO ){
-    u.ax.pKeyInfo = pOp->p4.pKeyInfo;
-    u.ax.pKeyInfo->enc = ENC(p->db);
-    u.ax.nField = u.ax.pKeyInfo->nField+1;
+    u.ay.pKeyInfo = pOp->p4.pKeyInfo;
+    u.ay.pKeyInfo->enc = ENC(p->db);
+    u.ay.nField = u.ay.pKeyInfo->nField+1;
   }else if( pOp->p4type==P4_INT32 ){
-    u.ax.nField = pOp->p4.i;
+    u.ay.nField = pOp->p4.i;
   }
   assert( pOp->p1>=0 );
-  u.ax.pCur = allocateCursor(p, pOp->p1, u.ax.nField, u.ax.iDb, 1);
-  if( u.ax.pCur==0 ) goto no_mem;
-  u.ax.pCur->nullRow = 1;
-  u.ax.pCur->isOrdered = 1;
-  rc = sqlite3BtreeCursor(u.ax.pX, u.ax.p2, u.ax.wrFlag, u.ax.pKeyInfo, u.ax.pCur->pCursor);
-  u.ax.pCur->pKeyInfo = u.ax.pKeyInfo;
+  u.ay.pCur = allocateCursor(p, pOp->p1, u.ay.nField, u.ay.iDb, 1);
+  if( u.ay.pCur==0 ) goto no_mem;
+  u.ay.pCur->nullRow = 1;
+  u.ay.pCur->isOrdered = 1;
+  rc = sqlite3BtreeCursor(u.ay.pX, u.ay.p2, u.ay.wrFlag, u.ay.pKeyInfo, u.ay.pCur->pCursor);
+  u.ay.pCur->pKeyInfo = u.ay.pKeyInfo;
   assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
-  sqlite3BtreeCursorHints(u.ax.pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
+  sqlite3BtreeCursorHints(u.ay.pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
 
   /* Since it performs no memory allocation or IO, the only value that
   ** sqlite3BtreeCursor() may return is SQLITE_OK. */
@@ -66689,8 +67196,8 @@ case OP_OpenWrite: {
   ** SQLite used to check if the root-page flags were sane at this point
   ** and report database corruption if they were not, but this check has
   ** since moved into the btree layer.  */
-  u.ax.pCur->isTable = pOp->p4type!=P4_KEYINFO;
-  u.ax.pCur->isIndex = !u.ax.pCur->isTable;
+  u.ay.pCur->isTable = pOp->p4type!=P4_KEYINFO;
+  u.ay.pCur->isIndex = !u.ay.pCur->isTable;
   break;
 }
 
@@ -66726,9 +67233,9 @@ case OP_OpenWrite: {
 */
 case OP_OpenAutoindex: 
 case OP_OpenEphemeral: {
-#if 0  /* local variables moved into u.ay */
+#if 0  /* local variables moved into u.az */
   VdbeCursor *pCx;
-#endif /* local variables moved into u.ay */
+#endif /* local variables moved into u.az */
   static const int vfsFlags =
       SQLITE_OPEN_READWRITE |
       SQLITE_OPEN_CREATE |
@@ -66737,13 +67244,13 @@ case OP_OpenEphemeral: {
       SQLITE_OPEN_TRANSIENT_DB;
 
   assert( pOp->p1>=0 );
-  u.ay.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
-  if( u.ay.pCx==0 ) goto no_mem;
-  u.ay.pCx->nullRow = 1;
-  rc = sqlite3BtreeOpen(db->pVfs, 0, db, &u.ay.pCx->pBt,
+  u.az.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
+  if( u.az.pCx==0 ) goto no_mem;
+  u.az.pCx->nullRow = 1;
+  rc = sqlite3BtreeOpen(db->pVfs, 0, db, &u.az.pCx->pBt,
                         BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
   if( rc==SQLITE_OK ){
-    rc = sqlite3BtreeBeginTrans(u.ay.pCx->pBt, 1);
+    rc = sqlite3BtreeBeginTrans(u.az.pCx->pBt, 1);
   }
   if( rc==SQLITE_OK ){
     /* If a transient index is required, create it by calling
@@ -66754,42 +67261,43 @@ case OP_OpenEphemeral: {
     if( pOp->p4.pKeyInfo ){
       int pgno;
       assert( pOp->p4type==P4_KEYINFO );
-      rc = sqlite3BtreeCreateTable(u.ay.pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
+      rc = sqlite3BtreeCreateTable(u.az.pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
       if( rc==SQLITE_OK ){
         assert( pgno==MASTER_ROOT+1 );
-        rc = sqlite3BtreeCursor(u.ay.pCx->pBt, pgno, 1,
-                                (KeyInfo*)pOp->p4.z, u.ay.pCx->pCursor);
-        u.ay.pCx->pKeyInfo = pOp->p4.pKeyInfo;
-        u.ay.pCx->pKeyInfo->enc = ENC(p->db);
+        rc = sqlite3BtreeCursor(u.az.pCx->pBt, pgno, 1,
+                                (KeyInfo*)pOp->p4.z, u.az.pCx->pCursor);
+        u.az.pCx->pKeyInfo = pOp->p4.pKeyInfo;
+        u.az.pCx->pKeyInfo->enc = ENC(p->db);
       }
-      u.ay.pCx->isTable = 0;
+      u.az.pCx->isTable = 0;
     }else{
-      rc = sqlite3BtreeCursor(u.ay.pCx->pBt, MASTER_ROOT, 1, 0, u.ay.pCx->pCursor);
-      u.ay.pCx->isTable = 1;
+      rc = sqlite3BtreeCursor(u.az.pCx->pBt, MASTER_ROOT, 1, 0, u.az.pCx->pCursor);
+      u.az.pCx->isTable = 1;
     }
   }
-  u.ay.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
-  u.ay.pCx->isIndex = !u.ay.pCx->isTable;
+  u.az.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
+  u.az.pCx->isIndex = !u.az.pCx->isTable;
   break;
 }
 
-/* Opcode: OpenSorter P1 P2 * P4 *
+/* Opcode: SorterOpen P1 P2 * P4 *
 **
 ** This opcode works like OP_OpenEphemeral except that it opens
 ** a transient index that is specifically designed to sort large
 ** tables using an external merge-sort algorithm.
 */
 case OP_SorterOpen: {
-#if 0  /* local variables moved into u.az */
+#if 0  /* local variables moved into u.ba */
   VdbeCursor *pCx;
-#endif /* local variables moved into u.az */
+#endif /* local variables moved into u.ba */
+
 #ifndef SQLITE_OMIT_MERGE_SORT
-  u.az.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
-  if( u.az.pCx==0 ) goto no_mem;
-  u.az.pCx->pKeyInfo = pOp->p4.pKeyInfo;
-  u.az.pCx->pKeyInfo->enc = ENC(p->db);
-  u.az.pCx->isSorter = 1;
-  rc = sqlite3VdbeSorterInit(db, u.az.pCx);
+  u.ba.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
+  if( u.ba.pCx==0 ) goto no_mem;
+  u.ba.pCx->pKeyInfo = pOp->p4.pKeyInfo;
+  u.ba.pCx->pKeyInfo->enc = ENC(p->db);
+  u.ba.pCx->isSorter = 1;
+  rc = sqlite3VdbeSorterInit(db, u.ba.pCx);
 #else
   pOp->opcode = OP_OpenEphemeral;
   pc--;
@@ -66797,12 +67305,13 @@ case OP_SorterOpen: {
   break;
 }
 
-/* Opcode: OpenPseudo P1 P2 P3 * *
+/* Opcode: OpenPseudo P1 P2 P3 * P5
 **
 ** Open a new cursor that points to a fake table that contains a single
 ** row of data.  The content of that one row in the content of memory
-** register P2.  In other words, cursor P1 becomes an alias for the 
-** MEM_Blob content contained in register P2.
+** register P2 when P5==0.  In other words, cursor P1 becomes an alias for the 
+** MEM_Blob content contained in register P2.  When P5==1, then the
+** row is represented by P3 consecutive registers beginning with P2.
 **
 ** A pseudo-table created by this opcode is used to hold a single
 ** row output from the sorter so that the row can be decomposed into
@@ -66813,17 +67322,18 @@ case OP_SorterOpen: {
 ** the pseudo-table.
 */
 case OP_OpenPseudo: {
-#if 0  /* local variables moved into u.ba */
+#if 0  /* local variables moved into u.bb */
   VdbeCursor *pCx;
-#endif /* local variables moved into u.ba */
+#endif /* local variables moved into u.bb */
 
   assert( pOp->p1>=0 );
-  u.ba.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
-  if( u.ba.pCx==0 ) goto no_mem;
-  u.ba.pCx->nullRow = 1;
-  u.ba.pCx->pseudoTableReg = pOp->p2;
-  u.ba.pCx->isTable = 1;
-  u.ba.pCx->isIndex = 0;
+  u.bb.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
+  if( u.bb.pCx==0 ) goto no_mem;
+  u.bb.pCx->nullRow = 1;
+  u.bb.pCx->pseudoTableReg = pOp->p2;
+  u.bb.pCx->isTable = 1;
+  u.bb.pCx->isIndex = 0;
+  u.bb.pCx->multiPseudo = pOp->p5;
   break;
 }
 
@@ -66895,35 +67405,35 @@ case OP_SeekLt:         /* jump, in3 */
 case OP_SeekLe:         /* jump, in3 */
 case OP_SeekGe:         /* jump, in3 */
 case OP_SeekGt: {       /* jump, in3 */
-#if 0  /* local variables moved into u.bb */
+#if 0  /* local variables moved into u.bc */
   int res;
   int oc;
   VdbeCursor *pC;
   UnpackedRecord r;
   int nField;
   i64 iKey;      /* The rowid we are to seek to */
-#endif /* local variables moved into u.bb */
+#endif /* local variables moved into u.bc */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
   assert( pOp->p2!=0 );
-  u.bb.pC = p->apCsr[pOp->p1];
-  assert( u.bb.pC!=0 );
-  assert( u.bb.pC->pseudoTableReg==0 );
+  u.bc.pC = p->apCsr[pOp->p1];
+  assert( u.bc.pC!=0 );
+  assert( u.bc.pC->pseudoTableReg==0 );
   assert( OP_SeekLe == OP_SeekLt+1 );
   assert( OP_SeekGe == OP_SeekLt+2 );
   assert( OP_SeekGt == OP_SeekLt+3 );
-  assert( u.bb.pC->isOrdered );
-  if( ALWAYS(u.bb.pC->pCursor!=0) ){
-    u.bb.oc = pOp->opcode;
-    u.bb.pC->nullRow = 0;
-    if( u.bb.pC->isTable ){
+  assert( u.bc.pC->isOrdered );
+  if( ALWAYS(u.bc.pC->pCursor!=0) ){
+    u.bc.oc = pOp->opcode;
+    u.bc.pC->nullRow = 0;
+    if( u.bc.pC->isTable ){
       /* The input value in P3 might be of any type: integer, real, string,
       ** blob, or NULL.  But it needs to be an integer before we can do
       ** the seek, so covert it. */
       pIn3 = &aMem[pOp->p3];
       applyNumericAffinity(pIn3);
-      u.bb.iKey = sqlite3VdbeIntValue(pIn3);
-      u.bb.pC->rowidIsValid = 0;
+      u.bc.iKey = sqlite3VdbeIntValue(pIn3);
+      u.bc.pC->rowidIsValid = 0;
 
       /* If the P3 value could not be converted into an integer without
       ** loss of information, then special processing is required... */
@@ -66938,101 +67448,101 @@ case OP_SeekGt: {       /* jump, in3 */
         ** point number. */
         assert( (pIn3->flags & MEM_Real)!=0 );
 
-        if( u.bb.iKey==SMALLEST_INT64 && (pIn3->r<(double)u.bb.iKey || pIn3->r>0) ){
+        if( u.bc.iKey==SMALLEST_INT64 && (pIn3->r<(double)u.bc.iKey || pIn3->r>0) ){
           /* The P3 value is too large in magnitude to be expressed as an
           ** integer. */
-          u.bb.res = 1;
+          u.bc.res = 1;
           if( pIn3->r<0 ){
-            if( u.bb.oc>=OP_SeekGe ){  assert( u.bb.oc==OP_SeekGe || u.bb.oc==OP_SeekGt );
-              rc = sqlite3BtreeFirst(u.bb.pC->pCursor, &u.bb.res);
+            if( u.bc.oc>=OP_SeekGe ){  assert( u.bc.oc==OP_SeekGe || u.bc.oc==OP_SeekGt );
+              rc = sqlite3BtreeFirst(u.bc.pC->pCursor, &u.bc.res);
               if( rc!=SQLITE_OK ) goto abort_due_to_error;
             }
           }else{
-            if( u.bb.oc<=OP_SeekLe ){  assert( u.bb.oc==OP_SeekLt || u.bb.oc==OP_SeekLe );
-              rc = sqlite3BtreeLast(u.bb.pC->pCursor, &u.bb.res);
+            if( u.bc.oc<=OP_SeekLe ){  assert( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekLe );
+              rc = sqlite3BtreeLast(u.bc.pC->pCursor, &u.bc.res);
               if( rc!=SQLITE_OK ) goto abort_due_to_error;
             }
           }
-          if( u.bb.res ){
+          if( u.bc.res ){
             pc = pOp->p2 - 1;
           }
           break;
-        }else if( u.bb.oc==OP_SeekLt || u.bb.oc==OP_SeekGe ){
+        }else if( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekGe ){
           /* Use the ceiling() function to convert real->int */
-          if( pIn3->r > (double)u.bb.iKey ) u.bb.iKey++;
+          if( pIn3->r > (double)u.bc.iKey ) u.bc.iKey++;
         }else{
           /* Use the floor() function to convert real->int */
-          assert( u.bb.oc==OP_SeekLe || u.bb.oc==OP_SeekGt );
-          if( pIn3->r < (double)u.bb.iKey ) u.bb.iKey--;
+          assert( u.bc.oc==OP_SeekLe || u.bc.oc==OP_SeekGt );
+          if( pIn3->r < (double)u.bc.iKey ) u.bc.iKey--;
         }
       }
-      rc = sqlite3BtreeMovetoUnpacked(u.bb.pC->pCursor, 0, (u64)u.bb.iKey, 0, &u.bb.res);
+      rc = sqlite3BtreeMovetoUnpacked(u.bc.pC->pCursor, 0, (u64)u.bc.iKey, 0, &u.bc.res);
       if( rc!=SQLITE_OK ){
         goto abort_due_to_error;
       }
-      if( u.bb.res==0 ){
-        u.bb.pC->rowidIsValid = 1;
-        u.bb.pC->lastRowid = u.bb.iKey;
+      if( u.bc.res==0 ){
+        u.bc.pC->rowidIsValid = 1;
+        u.bc.pC->lastRowid = u.bc.iKey;
       }
     }else{
-      u.bb.nField = pOp->p4.i;
+      u.bc.nField = pOp->p4.i;
       assert( pOp->p4type==P4_INT32 );
-      assert( u.bb.nField>0 );
-      u.bb.r.pKeyInfo = u.bb.pC->pKeyInfo;
-      u.bb.r.nField = (u16)u.bb.nField;
+      assert( u.bc.nField>0 );
+      u.bc.r.pKeyInfo = u.bc.pC->pKeyInfo;
+      u.bc.r.nField = (u16)u.bc.nField;
 
       /* The next line of code computes as follows, only faster:
-      **   if( u.bb.oc==OP_SeekGt || u.bb.oc==OP_SeekLe ){
-      **     u.bb.r.flags = UNPACKED_INCRKEY;
+      **   if( u.bc.oc==OP_SeekGt || u.bc.oc==OP_SeekLe ){
+      **     u.bc.r.flags = UNPACKED_INCRKEY;
       **   }else{
-      **     u.bb.r.flags = 0;
+      **     u.bc.r.flags = 0;
       **   }
       */
-      u.bb.r.flags = (u16)(UNPACKED_INCRKEY * (1 & (u.bb.oc - OP_SeekLt)));
-      assert( u.bb.oc!=OP_SeekGt || u.bb.r.flags==UNPACKED_INCRKEY );
-      assert( u.bb.oc!=OP_SeekLe || u.bb.r.flags==UNPACKED_INCRKEY );
-      assert( u.bb.oc!=OP_SeekGe || u.bb.r.flags==0 );
-      assert( u.bb.oc!=OP_SeekLt || u.bb.r.flags==0 );
+      u.bc.r.flags = (u16)(UNPACKED_INCRKEY * (1 & (u.bc.oc - OP_SeekLt)));
+      assert( u.bc.oc!=OP_SeekGt || u.bc.r.flags==UNPACKED_INCRKEY );
+      assert( u.bc.oc!=OP_SeekLe || u.bc.r.flags==UNPACKED_INCRKEY );
+      assert( u.bc.oc!=OP_SeekGe || u.bc.r.flags==0 );
+      assert( u.bc.oc!=OP_SeekLt || u.bc.r.flags==0 );
 
-      u.bb.r.aMem = &aMem[pOp->p3];
+      u.bc.r.aMem = &aMem[pOp->p3];
 #ifdef SQLITE_DEBUG
-      { int i; for(i=0; i<u.bb.r.nField; i++) assert( memIsValid(&u.bb.r.aMem[i]) ); }
+      { int i; for(i=0; i<u.bc.r.nField; i++) assert( memIsValid(&u.bc.r.aMem[i]) ); }
 #endif
-      ExpandBlob(u.bb.r.aMem);
-      rc = sqlite3BtreeMovetoUnpacked(u.bb.pC->pCursor, &u.bb.r, 0, 0, &u.bb.res);
+      ExpandBlob(u.bc.r.aMem);
+      rc = sqlite3BtreeMovetoUnpacked(u.bc.pC->pCursor, &u.bc.r, 0, 0, &u.bc.res);
       if( rc!=SQLITE_OK ){
         goto abort_due_to_error;
       }
-      u.bb.pC->rowidIsValid = 0;
+      u.bc.pC->rowidIsValid = 0;
     }
-    u.bb.pC->deferredMoveto = 0;
-    u.bb.pC->cacheStatus = CACHE_STALE;
+    u.bc.pC->deferredMoveto = 0;
+    u.bc.pC->cacheStatus = CACHE_STALE;
 #ifdef SQLITE_TEST
     sqlite3_search_count++;
 #endif
-    if( u.bb.oc>=OP_SeekGe ){  assert( u.bb.oc==OP_SeekGe || u.bb.oc==OP_SeekGt );
-      if( u.bb.res<0 || (u.bb.res==0 && u.bb.oc==OP_SeekGt) ){
-        rc = sqlite3BtreeNext(u.bb.pC->pCursor, &u.bb.res);
+    if( u.bc.oc>=OP_SeekGe ){  assert( u.bc.oc==OP_SeekGe || u.bc.oc==OP_SeekGt );
+      if( u.bc.res<0 || (u.bc.res==0 && u.bc.oc==OP_SeekGt) ){
+        rc = sqlite3BtreeNext(u.bc.pC->pCursor, &u.bc.res);
         if( rc!=SQLITE_OK ) goto abort_due_to_error;
-        u.bb.pC->rowidIsValid = 0;
+        u.bc.pC->rowidIsValid = 0;
       }else{
-        u.bb.res = 0;
+        u.bc.res = 0;
       }
     }else{
-      assert( u.bb.oc==OP_SeekLt || u.bb.oc==OP_SeekLe );
-      if( u.bb.res>0 || (u.bb.res==0 && u.bb.oc==OP_SeekLt) ){
-        rc = sqlite3BtreePrevious(u.bb.pC->pCursor, &u.bb.res);
+      assert( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekLe );
+      if( u.bc.res>0 || (u.bc.res==0 && u.bc.oc==OP_SeekLt) ){
+        rc = sqlite3BtreePrevious(u.bc.pC->pCursor, &u.bc.res);
         if( rc!=SQLITE_OK ) goto abort_due_to_error;
-        u.bb.pC->rowidIsValid = 0;
+        u.bc.pC->rowidIsValid = 0;
       }else{
-        /* u.bb.res might be negative because the table is empty.  Check to
+        /* u.bc.res might be negative because the table is empty.  Check to
         ** see if this is the case.
         */
-        u.bb.res = sqlite3BtreeEof(u.bb.pC->pCursor);
+        u.bc.res = sqlite3BtreeEof(u.bc.pC->pCursor);
       }
     }
     assert( pOp->p2>0 );
-    if( u.bb.res ){
+    if( u.bc.res ){
       pc = pOp->p2 - 1;
     }
   }else{
@@ -67055,20 +67565,20 @@ case OP_SeekGt: {       /* jump, in3 */
 ** occur, no unnecessary I/O happens.
 */
 case OP_Seek: {    /* in2 */
-#if 0  /* local variables moved into u.bc */
+#if 0  /* local variables moved into u.bd */
   VdbeCursor *pC;
-#endif /* local variables moved into u.bc */
+#endif /* local variables moved into u.bd */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bc.pC = p->apCsr[pOp->p1];
-  assert( u.bc.pC!=0 );
-  if( ALWAYS(u.bc.pC->pCursor!=0) ){
-    assert( u.bc.pC->isTable );
-    u.bc.pC->nullRow = 0;
+  u.bd.pC = p->apCsr[pOp->p1];
+  assert( u.bd.pC!=0 );
+  if( ALWAYS(u.bd.pC->pCursor!=0) ){
+    assert( u.bd.pC->isTable );
+    u.bd.pC->nullRow = 0;
     pIn2 = &aMem[pOp->p2];
-    u.bc.pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
-    u.bc.pC->rowidIsValid = 0;
-    u.bc.pC->deferredMoveto = 1;
+    u.bd.pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
+    u.bd.pC->rowidIsValid = 0;
+    u.bd.pC->deferredMoveto = 1;
   }
   break;
 }
@@ -67100,7 +67610,7 @@ case OP_Seek: {    /* in2 */
 */
 case OP_NotFound:       /* jump, in3 */
 case OP_Found: {        /* jump, in3 */
-#if 0  /* local variables moved into u.bd */
+#if 0  /* local variables moved into u.be */
   int alreadyExists;
   VdbeCursor *pC;
   int res;
@@ -67108,55 +67618,55 @@ case OP_Found: {        /* jump, in3 */
   UnpackedRecord *pIdxKey;
   UnpackedRecord r;
   char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
-#endif /* local variables moved into u.bd */
+#endif /* local variables moved into u.be */
 
 #ifdef SQLITE_TEST
   sqlite3_found_count++;
 #endif
 
-  u.bd.alreadyExists = 0;
+  u.be.alreadyExists = 0;
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
   assert( pOp->p4type==P4_INT32 );
-  u.bd.pC = p->apCsr[pOp->p1];
-  assert( u.bd.pC!=0 );
+  u.be.pC = p->apCsr[pOp->p1];
+  assert( u.be.pC!=0 );
   pIn3 = &aMem[pOp->p3];
-  if( ALWAYS(u.bd.pC->pCursor!=0) ){
+  if( ALWAYS(u.be.pC->pCursor!=0) ){
 
-    assert( u.bd.pC->isTable==0 );
+    assert( u.be.pC->isTable==0 );
     if( pOp->p4.i>0 ){
-      u.bd.r.pKeyInfo = u.bd.pC->pKeyInfo;
-      u.bd.r.nField = (u16)pOp->p4.i;
-      u.bd.r.aMem = pIn3;
+      u.be.r.pKeyInfo = u.be.pC->pKeyInfo;
+      u.be.r.nField = (u16)pOp->p4.i;
+      u.be.r.aMem = pIn3;
 #ifdef SQLITE_DEBUG
-      { int i; for(i=0; i<u.bd.r.nField; i++) assert( memIsValid(&u.bd.r.aMem[i]) ); }
+      { int i; for(i=0; i<u.be.r.nField; i++) assert( memIsValid(&u.be.r.aMem[i]) ); }
 #endif
-      u.bd.r.flags = UNPACKED_PREFIX_MATCH;
-      u.bd.pIdxKey = &u.bd.r;
+      u.be.r.flags = UNPACKED_PREFIX_MATCH;
+      u.be.pIdxKey = &u.be.r;
     }else{
-      u.bd.pIdxKey = sqlite3VdbeAllocUnpackedRecord(
-          u.bd.pC->pKeyInfo, u.bd.aTempRec, sizeof(u.bd.aTempRec), &u.bd.pFree
+      u.be.pIdxKey = sqlite3VdbeAllocUnpackedRecord(
+          u.be.pC->pKeyInfo, u.be.aTempRec, sizeof(u.be.aTempRec), &u.be.pFree
       );
-      if( u.bd.pIdxKey==0 ) goto no_mem;
+      if( u.be.pIdxKey==0 ) goto no_mem;
       assert( pIn3->flags & MEM_Blob );
       assert( (pIn3->flags & MEM_Zero)==0 );  /* zeroblobs already expanded */
-      sqlite3VdbeRecordUnpack(u.bd.pC->pKeyInfo, pIn3->n, pIn3->z, u.bd.pIdxKey);
-      u.bd.pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
+      sqlite3VdbeRecordUnpack(u.be.pC->pKeyInfo, pIn3->n, pIn3->z, u.be.pIdxKey);
+      u.be.pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
     }
-    rc = sqlite3BtreeMovetoUnpacked(u.bd.pC->pCursor, u.bd.pIdxKey, 0, 0, &u.bd.res);
+    rc = sqlite3BtreeMovetoUnpacked(u.be.pC->pCursor, u.be.pIdxKey, 0, 0, &u.be.res);
     if( pOp->p4.i==0 ){
-      sqlite3DbFree(db, u.bd.pFree);
+      sqlite3DbFree(db, u.be.pFree);
     }
     if( rc!=SQLITE_OK ){
       break;
     }
-    u.bd.alreadyExists = (u.bd.res==0);
-    u.bd.pC->deferredMoveto = 0;
-    u.bd.pC->cacheStatus = CACHE_STALE;
+    u.be.alreadyExists = (u.be.res==0);
+    u.be.pC->deferredMoveto = 0;
+    u.be.pC->cacheStatus = CACHE_STALE;
   }
   if( pOp->opcode==OP_Found ){
-    if( u.bd.alreadyExists ) pc = pOp->p2 - 1;
+    if( u.be.alreadyExists ) pc = pOp->p2 - 1;
   }else{
-    if( !u.bd.alreadyExists ) pc = pOp->p2 - 1;
+    if( !u.be.alreadyExists ) pc = pOp->p2 - 1;
   }
   break;
 }
@@ -67188,7 +67698,7 @@ case OP_Found: {        /* jump, in3 */
 ** See also: NotFound, NotExists, Found
 */
 case OP_IsUnique: {        /* jump, in3 */
-#if 0  /* local variables moved into u.be */
+#if 0  /* local variables moved into u.bf */
   u16 ii;
   VdbeCursor *pCx;
   BtCursor *pCrsr;
@@ -67196,55 +67706,55 @@ case OP_IsUnique: {        /* jump, in3 */
   Mem *aMx;
   UnpackedRecord r;                  /* B-Tree index search key */
   i64 R;                             /* Rowid stored in register P3 */
-#endif /* local variables moved into u.be */
+#endif /* local variables moved into u.bf */
 
   pIn3 = &aMem[pOp->p3];
-  u.be.aMx = &aMem[pOp->p4.i];
+  u.bf.aMx = &aMem[pOp->p4.i];
   /* Assert that the values of parameters P1 and P4 are in range. */
   assert( pOp->p4type==P4_INT32 );
   assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem );
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
 
   /* Find the index cursor. */
-  u.be.pCx = p->apCsr[pOp->p1];
-  assert( u.be.pCx->deferredMoveto==0 );
-  u.be.pCx->seekResult = 0;
-  u.be.pCx->cacheStatus = CACHE_STALE;
-  u.be.pCrsr = u.be.pCx->pCursor;
+  u.bf.pCx = p->apCsr[pOp->p1];
+  assert( u.bf.pCx->deferredMoveto==0 );
+  u.bf.pCx->seekResult = 0;
+  u.bf.pCx->cacheStatus = CACHE_STALE;
+  u.bf.pCrsr = u.bf.pCx->pCursor;
 
   /* If any of the values are NULL, take the jump. */
-  u.be.nField = u.be.pCx->pKeyInfo->nField;
-  for(u.be.ii=0; u.be.ii<u.be.nField; u.be.ii++){
-    if( u.be.aMx[u.be.ii].flags & MEM_Null ){
+  u.bf.nField = u.bf.pCx->pKeyInfo->nField;
+  for(u.bf.ii=0; u.bf.ii<u.bf.nField; u.bf.ii++){
+    if( u.bf.aMx[u.bf.ii].flags & MEM_Null ){
       pc = pOp->p2 - 1;
-      u.be.pCrsr = 0;
+      u.bf.pCrsr = 0;
       break;
     }
   }
-  assert( (u.be.aMx[u.be.nField].flags & MEM_Null)==0 );
+  assert( (u.bf.aMx[u.bf.nField].flags & MEM_Null)==0 );
 
-  if( u.be.pCrsr!=0 ){
+  if( u.bf.pCrsr!=0 ){
     /* Populate the index search key. */
-    u.be.r.pKeyInfo = u.be.pCx->pKeyInfo;
-    u.be.r.nField = u.be.nField + 1;
-    u.be.r.flags = UNPACKED_PREFIX_SEARCH;
-    u.be.r.aMem = u.be.aMx;
+    u.bf.r.pKeyInfo = u.bf.pCx->pKeyInfo;
+    u.bf.r.nField = u.bf.nField + 1;
+    u.bf.r.flags = UNPACKED_PREFIX_SEARCH;
+    u.bf.r.aMem = u.bf.aMx;
 #ifdef SQLITE_DEBUG
-    { int i; for(i=0; i<u.be.r.nField; i++) assert( memIsValid(&u.be.r.aMem[i]) ); }
+    { int i; for(i=0; i<u.bf.r.nField; i++) assert( memIsValid(&u.bf.r.aMem[i]) ); }
 #endif
 
-    /* Extract the value of u.be.R from register P3. */
+    /* Extract the value of u.bf.R from register P3. */
     sqlite3VdbeMemIntegerify(pIn3);
-    u.be.R = pIn3->u.i;
+    u.bf.R = pIn3->u.i;
 
     /* Search the B-Tree index. If no conflicting record is found, jump
     ** to P2. Otherwise, copy the rowid of the conflicting record to
     ** register P3 and fall through to the next instruction.  */
-    rc = sqlite3BtreeMovetoUnpacked(u.be.pCrsr, &u.be.r, 0, 0, &u.be.pCx->seekResult);
-    if( (u.be.r.flags & UNPACKED_PREFIX_SEARCH) || u.be.r.rowid==u.be.R ){
+    rc = sqlite3BtreeMovetoUnpacked(u.bf.pCrsr, &u.bf.r, 0, 0, &u.bf.pCx->seekResult);
+    if( (u.bf.r.flags & UNPACKED_PREFIX_SEARCH) || u.bf.r.rowid==u.bf.R ){
       pc = pOp->p2 - 1;
     }else{
-      pIn3->u.i = u.be.r.rowid;
+      pIn3->u.i = u.bf.r.rowid;
     }
   }
   break;
@@ -67265,42 +67775,42 @@ case OP_IsUnique: {        /* jump, in3 */
 ** See also: Found, NotFound, IsUnique
 */
 case OP_NotExists: {        /* jump, in3 */
-#if 0  /* local variables moved into u.bf */
+#if 0  /* local variables moved into u.bg */
   VdbeCursor *pC;
   BtCursor *pCrsr;
   int res;
   u64 iKey;
-#endif /* local variables moved into u.bf */
+#endif /* local variables moved into u.bg */
 
   pIn3 = &aMem[pOp->p3];
   assert( pIn3->flags & MEM_Int );
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bf.pC = p->apCsr[pOp->p1];
-  assert( u.bf.pC!=0 );
-  assert( u.bf.pC->isTable );
-  assert( u.bf.pC->pseudoTableReg==0 );
-  u.bf.pCrsr = u.bf.pC->pCursor;
-  if( ALWAYS(u.bf.pCrsr!=0) ){
-    u.bf.res = 0;
-    u.bf.iKey = pIn3->u.i;
-    rc = sqlite3BtreeMovetoUnpacked(u.bf.pCrsr, 0, u.bf.iKey, 0, &u.bf.res);
-    u.bf.pC->lastRowid = pIn3->u.i;
-    u.bf.pC->rowidIsValid = u.bf.res==0 ?1:0;
-    u.bf.pC->nullRow = 0;
-    u.bf.pC->cacheStatus = CACHE_STALE;
-    u.bf.pC->deferredMoveto = 0;
-    if( u.bf.res!=0 ){
+  u.bg.pC = p->apCsr[pOp->p1];
+  assert( u.bg.pC!=0 );
+  assert( u.bg.pC->isTable );
+  assert( u.bg.pC->pseudoTableReg==0 );
+  u.bg.pCrsr = u.bg.pC->pCursor;
+  if( ALWAYS(u.bg.pCrsr!=0) ){
+    u.bg.res = 0;
+    u.bg.iKey = pIn3->u.i;
+    rc = sqlite3BtreeMovetoUnpacked(u.bg.pCrsr, 0, u.bg.iKey, 0, &u.bg.res);
+    u.bg.pC->lastRowid = pIn3->u.i;
+    u.bg.pC->rowidIsValid = u.bg.res==0 ?1:0;
+    u.bg.pC->nullRow = 0;
+    u.bg.pC->cacheStatus = CACHE_STALE;
+    u.bg.pC->deferredMoveto = 0;
+    if( u.bg.res!=0 ){
       pc = pOp->p2 - 1;
-      assert( u.bf.pC->rowidIsValid==0 );
+      assert( u.bg.pC->rowidIsValid==0 );
     }
-    u.bf.pC->seekResult = u.bf.res;
+    u.bg.pC->seekResult = u.bg.res;
   }else{
     /* This happens when an attempt to open a read cursor on the
     ** sqlite_master table returns SQLITE_EMPTY.
     */
     pc = pOp->p2 - 1;
-    assert( u.bf.pC->rowidIsValid==0 );
-    u.bf.pC->seekResult = 0;
+    assert( u.bg.pC->rowidIsValid==0 );
+    u.bg.pC->seekResult = 0;
   }
   break;
 }
@@ -67335,21 +67845,21 @@ case OP_Sequence: {           /* out2-prerelease */
 ** AUTOINCREMENT feature.
 */
 case OP_NewRowid: {           /* out2-prerelease */
-#if 0  /* local variables moved into u.bg */
+#if 0  /* local variables moved into u.bh */
   i64 v;                 /* The new rowid */
   VdbeCursor *pC;        /* Cursor of table to get the new rowid */
   int res;               /* Result of an sqlite3BtreeLast() */
   int cnt;               /* Counter to limit the number of searches */
   Mem *pMem;             /* Register holding largest rowid for AUTOINCREMENT */
   VdbeFrame *pFrame;     /* Root frame of VDBE */
-#endif /* local variables moved into u.bg */
+#endif /* local variables moved into u.bh */
 
-  u.bg.v = 0;
-  u.bg.res = 0;
+  u.bh.v = 0;
+  u.bh.res = 0;
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bg.pC = p->apCsr[pOp->p1];
-  assert( u.bg.pC!=0 );
-  if( NEVER(u.bg.pC->pCursor==0) ){
+  u.bh.pC = p->apCsr[pOp->p1];
+  assert( u.bh.pC!=0 );
+  if( NEVER(u.bh.pC->pCursor==0) ){
     /* The zero initialization above is all that is needed */
   }else{
     /* The next rowid or record number (different terms for the same
@@ -67365,7 +67875,7 @@ case OP_NewRowid: {           /* out2-prerelease */
     ** succeeded.  If the random rowid does exist, we select a new one
     ** and try again, up to 100 times.
     */
-    assert( u.bg.pC->isTable );
+    assert( u.bh.pC->isTable );
 
 #ifdef SQLITE_32BIT_ROWID
 #   define MAX_ROWID 0x7fffffff
@@ -67377,23 +67887,23 @@ case OP_NewRowid: {           /* out2-prerelease */
 #   define MAX_ROWID  (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff )
 #endif
 
-    if( !u.bg.pC->useRandomRowid ){
-      u.bg.v = sqlite3BtreeGetCachedRowid(u.bg.pC->pCursor);
-      if( u.bg.v==0 ){
-        rc = sqlite3BtreeLast(u.bg.pC->pCursor, &u.bg.res);
+    if( !u.bh.pC->useRandomRowid ){
+      u.bh.v = sqlite3BtreeGetCachedRowid(u.bh.pC->pCursor);
+      if( u.bh.v==0 ){
+        rc = sqlite3BtreeLast(u.bh.pC->pCursor, &u.bh.res);
         if( rc!=SQLITE_OK ){
           goto abort_due_to_error;
         }
-        if( u.bg.res ){
-          u.bg.v = 1;   /* IMP: R-61914-48074 */
+        if( u.bh.res ){
+          u.bh.v = 1;   /* IMP: R-61914-48074 */
         }else{
-          assert( sqlite3BtreeCursorIsValid(u.bg.pC->pCursor) );
-          rc = sqlite3BtreeKeySize(u.bg.pC->pCursor, &u.bg.v);
+          assert( sqlite3BtreeCursorIsValid(u.bh.pC->pCursor) );
+          rc = sqlite3BtreeKeySize(u.bh.pC->pCursor, &u.bh.v);
           assert( rc==SQLITE_OK );   /* Cannot fail following BtreeLast() */
-          if( u.bg.v>=MAX_ROWID ){
-            u.bg.pC->useRandomRowid = 1;
+          if( u.bh.v>=MAX_ROWID ){
+            u.bh.pC->useRandomRowid = 1;
           }else{
-            u.bg.v++;   /* IMP: R-29538-34987 */
+            u.bh.v++;   /* IMP: R-29538-34987 */
           }
         }
       }
@@ -67403,35 +67913,35 @@ case OP_NewRowid: {           /* out2-prerelease */
         /* Assert that P3 is a valid memory cell. */
         assert( pOp->p3>0 );
         if( p->pFrame ){
-          for(u.bg.pFrame=p->pFrame; u.bg.pFrame->pParent; u.bg.pFrame=u.bg.pFrame->pParent);
+          for(u.bh.pFrame=p->pFrame; u.bh.pFrame->pParent; u.bh.pFrame=u.bh.pFrame->pParent);
           /* Assert that P3 is a valid memory cell. */
-          assert( pOp->p3<=u.bg.pFrame->nMem );
-          u.bg.pMem = &u.bg.pFrame->aMem[pOp->p3];
+          assert( pOp->p3<=u.bh.pFrame->nMem );
+          u.bh.pMem = &u.bh.pFrame->aMem[pOp->p3];
         }else{
           /* Assert that P3 is a valid memory cell. */
           assert( pOp->p3<=p->nMem );
-          u.bg.pMem = &aMem[pOp->p3];
-          memAboutToChange(p, u.bg.pMem);
+          u.bh.pMem = &aMem[pOp->p3];
+          memAboutToChange(p, u.bh.pMem);
         }
-        assert( memIsValid(u.bg.pMem) );
+        assert( memIsValid(u.bh.pMem) );
 
-        REGISTER_TRACE(pOp->p3, u.bg.pMem);
-        sqlite3VdbeMemIntegerify(u.bg.pMem);
-        assert( (u.bg.pMem->flags & MEM_Int)!=0 );  /* mem(P3) holds an integer */
-        if( u.bg.pMem->u.i==MAX_ROWID || u.bg.pC->useRandomRowid ){
+        REGISTER_TRACE(pOp->p3, u.bh.pMem);
+        sqlite3VdbeMemIntegerify(u.bh.pMem);
+        assert( (u.bh.pMem->flags & MEM_Int)!=0 );  /* mem(P3) holds an integer */
+        if( u.bh.pMem->u.i==MAX_ROWID || u.bh.pC->useRandomRowid ){
           rc = SQLITE_FULL;   /* IMP: R-12275-61338 */
           goto abort_due_to_error;
         }
-        if( u.bg.v<u.bg.pMem->u.i+1 ){
-          u.bg.v = u.bg.pMem->u.i + 1;
+        if( u.bh.v<u.bh.pMem->u.i+1 ){
+          u.bh.v = u.bh.pMem->u.i + 1;
         }
-        u.bg.pMem->u.i = u.bg.v;
+        u.bh.pMem->u.i = u.bh.v;
       }
 #endif
 
-      sqlite3BtreeSetCachedRowid(u.bg.pC->pCursor, u.bg.v<MAX_ROWID ? u.bg.v+1 : 0);
+      sqlite3BtreeSetCachedRowid(u.bh.pC->pCursor, u.bh.v<MAX_ROWID ? u.bh.v+1 : 0);
     }
-    if( u.bg.pC->useRandomRowid ){
+    if( u.bh.pC->useRandomRowid ){
       /* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the
       ** largest possible integer (9223372036854775807) then the database
       ** engine starts picking positive candidate ROWIDs at random until
@@ -67439,35 +67949,35 @@ case OP_NewRowid: {           /* out2-prerelease */
       assert( pOp->p3==0 );  /* We cannot be in random rowid mode if this is
                              ** an AUTOINCREMENT table. */
       /* on the first attempt, simply do one more than previous */
-      u.bg.v = lastRowid;
-      u.bg.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
-      u.bg.v++; /* ensure non-zero */
-      u.bg.cnt = 0;
-      while(   ((rc = sqlite3BtreeMovetoUnpacked(u.bg.pC->pCursor, 0, (u64)u.bg.v,
-                                                 0, &u.bg.res))==SQLITE_OK)
-            && (u.bg.res==0)
-            && (++u.bg.cnt<100)){
+      u.bh.v = lastRowid;
+      u.bh.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
+      u.bh.v++; /* ensure non-zero */
+      u.bh.cnt = 0;
+      while(   ((rc = sqlite3BtreeMovetoUnpacked(u.bh.pC->pCursor, 0, (u64)u.bh.v,
+                                                 0, &u.bh.res))==SQLITE_OK)
+            && (u.bh.res==0)
+            && (++u.bh.cnt<100)){
         /* collision - try another random rowid */
-        sqlite3_randomness(sizeof(u.bg.v), &u.bg.v);
-        if( u.bg.cnt<5 ){
+        sqlite3_randomness(sizeof(u.bh.v), &u.bh.v);
+        if( u.bh.cnt<5 ){
           /* try "small" random rowids for the initial attempts */
-          u.bg.v &= 0xffffff;
+          u.bh.v &= 0xffffff;
         }else{
-          u.bg.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
+          u.bh.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
         }
-        u.bg.v++; /* ensure non-zero */
+        u.bh.v++; /* ensure non-zero */
       }
-      if( rc==SQLITE_OK && u.bg.res==0 ){
+      if( rc==SQLITE_OK && u.bh.res==0 ){
         rc = SQLITE_FULL;   /* IMP: R-38219-53002 */
         goto abort_due_to_error;
       }
-      assert( u.bg.v>0 );  /* EV: R-40812-03570 */
+      assert( u.bh.v>0 );  /* EV: R-40812-03570 */
     }
-    u.bg.pC->rowidIsValid = 0;
-    u.bg.pC->deferredMoveto = 0;
-    u.bg.pC->cacheStatus = CACHE_STALE;
+    u.bh.pC->rowidIsValid = 0;
+    u.bh.pC->deferredMoveto = 0;
+    u.bh.pC->cacheStatus = CACHE_STALE;
   }
-  pOut->u.i = u.bg.v;
+  pOut->u.i = u.bh.v;
   break;
 }
 
@@ -67517,7 +68027,7 @@ case OP_NewRowid: {           /* out2-prerelease */
 */
 case OP_Insert: 
 case OP_InsertInt: {
-#if 0  /* local variables moved into u.bh */
+#if 0  /* local variables moved into u.bi */
   Mem *pData;       /* MEM cell holding data for the record to be inserted */
   Mem *pKey;        /* MEM cell holding key  for the record */
   i64 iKey;         /* The integer ROWID or key for the record to be inserted */
@@ -67527,60 +68037,60 @@ case OP_InsertInt: {
   const char *zDb;  /* database name - used by the update hook */
   const char *zTbl; /* Table name - used by the opdate hook */
   int op;           /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
-#endif /* local variables moved into u.bh */
+#endif /* local variables moved into u.bi */
 
-  u.bh.pData = &aMem[pOp->p2];
+  u.bi.pData = &aMem[pOp->p2];
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  assert( memIsValid(u.bh.pData) );
-  u.bh.pC = p->apCsr[pOp->p1];
-  assert( u.bh.pC!=0 );
-  assert( u.bh.pC->pCursor!=0 );
-  assert( u.bh.pC->pseudoTableReg==0 );
-  assert( u.bh.pC->isTable );
-  REGISTER_TRACE(pOp->p2, u.bh.pData);
+  assert( memIsValid(u.bi.pData) );
+  u.bi.pC = p->apCsr[pOp->p1];
+  assert( u.bi.pC!=0 );
+  assert( u.bi.pC->pCursor!=0 );
+  assert( u.bi.pC->pseudoTableReg==0 );
+  assert( u.bi.pC->isTable );
+  REGISTER_TRACE(pOp->p2, u.bi.pData);
 
   if( pOp->opcode==OP_Insert ){
-    u.bh.pKey = &aMem[pOp->p3];
-    assert( u.bh.pKey->flags & MEM_Int );
-    assert( memIsValid(u.bh.pKey) );
-    REGISTER_TRACE(pOp->p3, u.bh.pKey);
-    u.bh.iKey = u.bh.pKey->u.i;
+    u.bi.pKey = &aMem[pOp->p3];
+    assert( u.bi.pKey->flags & MEM_Int );
+    assert( memIsValid(u.bi.pKey) );
+    REGISTER_TRACE(pOp->p3, u.bi.pKey);
+    u.bi.iKey = u.bi.pKey->u.i;
   }else{
     assert( pOp->opcode==OP_InsertInt );
-    u.bh.iKey = pOp->p3;
+    u.bi.iKey = pOp->p3;
   }
 
   if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
-  if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = u.bh.iKey;
-  if( u.bh.pData->flags & MEM_Null ){
-    u.bh.pData->z = 0;
-    u.bh.pData->n = 0;
+  if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = u.bi.iKey;
+  if( u.bi.pData->flags & MEM_Null ){
+    u.bi.pData->z = 0;
+    u.bi.pData->n = 0;
   }else{
-    assert( u.bh.pData->flags & (MEM_Blob|MEM_Str) );
+    assert( u.bi.pData->flags & (MEM_Blob|MEM_Str) );
   }
-  u.bh.seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bh.pC->seekResult : 0);
-  if( u.bh.pData->flags & MEM_Zero ){
-    u.bh.nZero = u.bh.pData->u.nZero;
+  u.bi.seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bi.pC->seekResult : 0);
+  if( u.bi.pData->flags & MEM_Zero ){
+    u.bi.nZero = u.bi.pData->u.nZero;
   }else{
-    u.bh.nZero = 0;
+    u.bi.nZero = 0;
   }
-  sqlite3BtreeSetCachedRowid(u.bh.pC->pCursor, 0);
-  rc = sqlite3BtreeInsert(u.bh.pC->pCursor, 0, u.bh.iKey,
-                          u.bh.pData->z, u.bh.pData->n, u.bh.nZero,
-                          pOp->p5 & OPFLAG_APPEND, u.bh.seekResult
+  sqlite3BtreeSetCachedRowid(u.bi.pC->pCursor, 0);
+  rc = sqlite3BtreeInsert(u.bi.pC->pCursor, 0, u.bi.iKey,
+                          u.bi.pData->z, u.bi.pData->n, u.bi.nZero,
+                          pOp->p5 & OPFLAG_APPEND, u.bi.seekResult
   );
-  u.bh.pC->rowidIsValid = 0;
-  u.bh.pC->deferredMoveto = 0;
-  u.bh.pC->cacheStatus = CACHE_STALE;
+  u.bi.pC->rowidIsValid = 0;
+  u.bi.pC->deferredMoveto = 0;
+  u.bi.pC->cacheStatus = CACHE_STALE;
 
   /* Invoke the update-hook if required. */
   if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
-    u.bh.zDb = db->aDb[u.bh.pC->iDb].zName;
-    u.bh.zTbl = pOp->p4.z;
-    u.bh.op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
-    assert( u.bh.pC->isTable );
-    db->xUpdateCallback(db->pUpdateArg, u.bh.op, u.bh.zDb, u.bh.zTbl, u.bh.iKey);
-    assert( u.bh.pC->iDb>=0 );
+    u.bi.zDb = db->aDb[u.bi.pC->iDb].zName;
+    u.bi.zTbl = pOp->p4.z;
+    u.bi.op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
+    assert( u.bi.pC->isTable );
+    db->xUpdateCallback(db->pUpdateArg, u.bi.op, u.bi.zDb, u.bi.zTbl, u.bi.iKey);
+    assert( u.bi.pC->iDb>=0 );
   }
   break;
 }
@@ -67606,47 +68116,47 @@ case OP_InsertInt: {
 ** using OP_NotFound prior to invoking this opcode.
 */
 case OP_Delete: {
-#if 0  /* local variables moved into u.bi */
+#if 0  /* local variables moved into u.bj */
   i64 iKey;
   VdbeCursor *pC;
-#endif /* local variables moved into u.bi */
+#endif /* local variables moved into u.bj */
 
-  u.bi.iKey = 0;
+  u.bj.iKey = 0;
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bi.pC = p->apCsr[pOp->p1];
-  assert( u.bi.pC!=0 );
-  assert( u.bi.pC->pCursor!=0 );  /* Only valid for real tables, no pseudotables */
+  u.bj.pC = p->apCsr[pOp->p1];
+  assert( u.bj.pC!=0 );
+  assert( u.bj.pC->pCursor!=0 );  /* Only valid for real tables, no pseudotables */
 
-  /* If the update-hook will be invoked, set u.bi.iKey to the rowid of the
+  /* If the update-hook will be invoked, set u.bj.iKey to the rowid of the
   ** row being deleted.
   */
   if( db->xUpdateCallback && pOp->p4.z ){
-    assert( u.bi.pC->isTable );
-    assert( u.bi.pC->rowidIsValid );  /* lastRowid set by previous OP_NotFound */
-    u.bi.iKey = u.bi.pC->lastRowid;
+    assert( u.bj.pC->isTable );
+    assert( u.bj.pC->rowidIsValid );  /* lastRowid set by previous OP_NotFound */
+    u.bj.iKey = u.bj.pC->lastRowid;
   }
 
   /* The OP_Delete opcode always follows an OP_NotExists or OP_Last or
   ** OP_Column on the same table without any intervening operations that
-  ** might move or invalidate the cursor.  Hence cursor u.bi.pC is always pointing
+  ** might move or invalidate the cursor.  Hence cursor u.bj.pC is always pointing
   ** to the row to be deleted and the sqlite3VdbeCursorMoveto() operation
   ** below is always a no-op and cannot fail.  We will run it anyhow, though,
   ** to guard against future changes to the code generator.
   **/
-  assert( u.bi.pC->deferredMoveto==0 );
-  rc = sqlite3VdbeCursorMoveto(u.bi.pC);
+  assert( u.bj.pC->deferredMoveto==0 );
+  rc = sqlite3VdbeCursorMoveto(u.bj.pC);
   if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
 
-  sqlite3BtreeSetCachedRowid(u.bi.pC->pCursor, 0);
-  rc = sqlite3BtreeDelete(u.bi.pC->pCursor);
-  u.bi.pC->cacheStatus = CACHE_STALE;
+  sqlite3BtreeSetCachedRowid(u.bj.pC->pCursor, 0);
+  rc = sqlite3BtreeDelete(u.bj.pC->pCursor);
+  u.bj.pC->cacheStatus = CACHE_STALE;
 
   /* Invoke the update-hook if required. */
   if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
-    const char *zDb = db->aDb[u.bi.pC->iDb].zName;
+    const char *zDb = db->aDb[u.bj.pC->iDb].zName;
     const char *zTbl = pOp->p4.z;
-    db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, u.bi.iKey);
-    assert( u.bi.pC->iDb>=0 );
+    db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, u.bj.iKey);
+    assert( u.bj.pC->iDb>=0 );
   }
   if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
   break;
@@ -67672,16 +68182,16 @@ case OP_ResetCount: {
 ** fall through to the next instruction. Otherwise, jump to instruction P2.
 */
 case OP_SorterCompare: {
-#if 0  /* local variables moved into u.bj */
+#if 0  /* local variables moved into u.bk */
   VdbeCursor *pC;
   int res;
-#endif /* local variables moved into u.bj */
+#endif /* local variables moved into u.bk */
 
-  u.bj.pC = p->apCsr[pOp->p1];
-  assert( isSorter(u.bj.pC) );
+  u.bk.pC = p->apCsr[pOp->p1];
+  assert( isSorter(u.bk.pC) );
   pIn3 = &aMem[pOp->p3];
-  rc = sqlite3VdbeSorterCompare(u.bj.pC, pIn3, &u.bj.res);
-  if( u.bj.res ){
+  rc = sqlite3VdbeSorterCompare(u.bk.pC, pIn3, &u.bk.res);
+  if( u.bk.res ){
     pc = pOp->p2-1;
   }
   break;
@@ -67692,14 +68202,15 @@ case OP_SorterCompare: {
 ** Write into register P2 the current sorter data for sorter cursor P1.
 */
 case OP_SorterData: {
-#if 0  /* local variables moved into u.bk */
+#if 0  /* local variables moved into u.bl */
   VdbeCursor *pC;
-#endif /* local variables moved into u.bk */
+#endif /* local variables moved into u.bl */
+
 #ifndef SQLITE_OMIT_MERGE_SORT
   pOut = &aMem[pOp->p2];
-  u.bk.pC = p->apCsr[pOp->p1];
-  assert( u.bk.pC->isSorter );
-  rc = sqlite3VdbeSorterRowkey(u.bk.pC, pOut);
+  u.bl.pC = p->apCsr[pOp->p1];
+  assert( u.bl.pC->isSorter );
+  rc = sqlite3VdbeSorterRowkey(u.bl.pC, pOut);
 #else
   pOp->opcode = OP_RowKey;
   pc--;
@@ -67729,62 +68240,62 @@ case OP_SorterData: {
 */
 case OP_RowKey:
 case OP_RowData: {
-#if 0  /* local variables moved into u.bl */
+#if 0  /* local variables moved into u.bm */
   VdbeCursor *pC;
   BtCursor *pCrsr;
   u32 n;
   i64 n64;
-#endif /* local variables moved into u.bl */
+#endif /* local variables moved into u.bm */
 
   pOut = &aMem[pOp->p2];
   memAboutToChange(p, pOut);
 
   /* Note that RowKey and RowData are really exactly the same instruction */
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bl.pC = p->apCsr[pOp->p1];
-  assert( u.bl.pC->isSorter==0 );
-  assert( u.bl.pC->isTable || pOp->opcode!=OP_RowData );
-  assert( u.bl.pC->isIndex || pOp->opcode==OP_RowData );
-  assert( u.bl.pC!=0 );
-  assert( u.bl.pC->nullRow==0 );
-  assert( u.bl.pC->pseudoTableReg==0 );
-  assert( u.bl.pC->pCursor!=0 );
-  u.bl.pCrsr = u.bl.pC->pCursor;
-  assert( sqlite3BtreeCursorIsValid(u.bl.pCrsr) );
+  u.bm.pC = p->apCsr[pOp->p1];
+  assert( u.bm.pC->isSorter==0 );
+  assert( u.bm.pC->isTable || pOp->opcode!=OP_RowData );
+  assert( u.bm.pC->isIndex || pOp->opcode==OP_RowData );
+  assert( u.bm.pC!=0 );
+  assert( u.bm.pC->nullRow==0 );
+  assert( u.bm.pC->pseudoTableReg==0 );
+  assert( u.bm.pC->pCursor!=0 );
+  u.bm.pCrsr = u.bm.pC->pCursor;
+  assert( sqlite3BtreeCursorIsValid(u.bm.pCrsr) );
 
   /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
   ** OP_Rewind/Op_Next with no intervening instructions that might invalidate
   ** the cursor.  Hence the following sqlite3VdbeCursorMoveto() call is always
   ** a no-op and can never fail.  But we leave it in place as a safety.
   */
-  assert( u.bl.pC->deferredMoveto==0 );
-  rc = sqlite3VdbeCursorMoveto(u.bl.pC);
+  assert( u.bm.pC->deferredMoveto==0 );
+  rc = sqlite3VdbeCursorMoveto(u.bm.pC);
   if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
 
-  if( u.bl.pC->isIndex ){
-    assert( !u.bl.pC->isTable );
-    VVA_ONLY(rc =) sqlite3BtreeKeySize(u.bl.pCrsr, &u.bl.n64);
+  if( u.bm.pC->isIndex ){
+    assert( !u.bm.pC->isTable );
+    VVA_ONLY(rc =) sqlite3BtreeKeySize(u.bm.pCrsr, &u.bm.n64);
     assert( rc==SQLITE_OK );    /* True because of CursorMoveto() call above */
-    if( u.bl.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+    if( u.bm.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
       goto too_big;
     }
-    u.bl.n = (u32)u.bl.n64;
+    u.bm.n = (u32)u.bm.n64;
   }else{
-    VVA_ONLY(rc =) sqlite3BtreeDataSize(u.bl.pCrsr, &u.bl.n);
+    VVA_ONLY(rc =) sqlite3BtreeDataSize(u.bm.pCrsr, &u.bm.n);
     assert( rc==SQLITE_OK );    /* DataSize() cannot fail */
-    if( u.bl.n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
+    if( u.bm.n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
       goto too_big;
     }
   }
-  if( sqlite3VdbeMemGrow(pOut, u.bl.n, 0) ){
+  if( sqlite3VdbeMemGrow(pOut, u.bm.n, 0) ){
     goto no_mem;
   }
-  pOut->n = u.bl.n;
+  pOut->n = u.bm.n;
   MemSetTypeFlag(pOut, MEM_Blob);
-  if( u.bl.pC->isIndex ){
-    rc = sqlite3BtreeKey(u.bl.pCrsr, 0, u.bl.n, pOut->z);
+  if( u.bm.pC->isIndex ){
+    rc = sqlite3BtreeKey(u.bm.pCrsr, 0, u.bm.n, pOut->z);
   }else{
-    rc = sqlite3BtreeData(u.bl.pCrsr, 0, u.bl.n, pOut->z);
+    rc = sqlite3BtreeData(u.bm.pCrsr, 0, u.bm.n, pOut->z);
   }
   pOut->enc = SQLITE_UTF8;  /* In case the blob is ever cast to text */
   UPDATE_MAX_BLOBSIZE(pOut);
@@ -67801,42 +68312,42 @@ case OP_RowData: {
 ** one opcode now works for both table types.
 */
 case OP_Rowid: {                 /* out2-prerelease */
-#if 0  /* local variables moved into u.bm */
+#if 0  /* local variables moved into u.bn */
   VdbeCursor *pC;
   i64 v;
   sqlite3_vtab *pVtab;
   const sqlite3_module *pModule;
-#endif /* local variables moved into u.bm */
+#endif /* local variables moved into u.bn */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bm.pC = p->apCsr[pOp->p1];
-  assert( u.bm.pC!=0 );
-  assert( u.bm.pC->pseudoTableReg==0 );
-  if( u.bm.pC->nullRow ){
+  u.bn.pC = p->apCsr[pOp->p1];
+  assert( u.bn.pC!=0 );
+  assert( u.bn.pC->pseudoTableReg==0 || u.bn.pC->nullRow );
+  if( u.bn.pC->nullRow ){
     pOut->flags = MEM_Null;
     break;
-  }else if( u.bm.pC->deferredMoveto ){
-    u.bm.v = u.bm.pC->movetoTarget;
+  }else if( u.bn.pC->deferredMoveto ){
+    u.bn.v = u.bn.pC->movetoTarget;
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  }else if( u.bm.pC->pVtabCursor ){
-    u.bm.pVtab = u.bm.pC->pVtabCursor->pVtab;
-    u.bm.pModule = u.bm.pVtab->pModule;
-    assert( u.bm.pModule->xRowid );
-    rc = u.bm.pModule->xRowid(u.bm.pC->pVtabCursor, &u.bm.v);
-    importVtabErrMsg(p, u.bm.pVtab);
+  }else if( u.bn.pC->pVtabCursor ){
+    u.bn.pVtab = u.bn.pC->pVtabCursor->pVtab;
+    u.bn.pModule = u.bn.pVtab->pModule;
+    assert( u.bn.pModule->xRowid );
+    rc = u.bn.pModule->xRowid(u.bn.pC->pVtabCursor, &u.bn.v);
+    importVtabErrMsg(p, u.bn.pVtab);
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
   }else{
-    assert( u.bm.pC->pCursor!=0 );
-    rc = sqlite3VdbeCursorMoveto(u.bm.pC);
+    assert( u.bn.pC->pCursor!=0 );
+    rc = sqlite3VdbeCursorMoveto(u.bn.pC);
     if( rc ) goto abort_due_to_error;
-    if( u.bm.pC->rowidIsValid ){
-      u.bm.v = u.bm.pC->lastRowid;
+    if( u.bn.pC->rowidIsValid ){
+      u.bn.v = u.bn.pC->lastRowid;
     }else{
-      rc = sqlite3BtreeKeySize(u.bm.pC->pCursor, &u.bm.v);
+      rc = sqlite3BtreeKeySize(u.bn.pC->pCursor, &u.bn.v);
       assert( rc==SQLITE_OK );  /* Always so because of CursorMoveto() above */
     }
   }
-  pOut->u.i = u.bm.v;
+  pOut->u.i = u.bn.v;
   break;
 }
 
@@ -67847,18 +68358,18 @@ case OP_Rowid: {                 /* out2-prerelease */
 ** write a NULL.
 */
 case OP_NullRow: {
-#if 0  /* local variables moved into u.bn */
+#if 0  /* local variables moved into u.bo */
   VdbeCursor *pC;
-#endif /* local variables moved into u.bn */
+#endif /* local variables moved into u.bo */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bn.pC = p->apCsr[pOp->p1];
-  assert( u.bn.pC!=0 );
-  u.bn.pC->nullRow = 1;
-  u.bn.pC->rowidIsValid = 0;
-  assert( u.bn.pC->pCursor || u.bn.pC->pVtabCursor );
-  if( u.bn.pC->pCursor ){
-    sqlite3BtreeClearCursor(u.bn.pC->pCursor);
+  u.bo.pC = p->apCsr[pOp->p1];
+  assert( u.bo.pC!=0 );
+  u.bo.pC->nullRow = 1;
+  u.bo.pC->rowidIsValid = 0;
+  assert( u.bo.pC->pCursor || u.bo.pC->pVtabCursor );
+  if( u.bo.pC->pCursor ){
+    sqlite3BtreeClearCursor(u.bo.pC->pCursor);
   }
   break;
 }
@@ -67872,25 +68383,25 @@ case OP_NullRow: {
 ** to the following instruction.
 */
 case OP_Last: {        /* jump */
-#if 0  /* local variables moved into u.bo */
+#if 0  /* local variables moved into u.bp */
   VdbeCursor *pC;
   BtCursor *pCrsr;
   int res;
-#endif /* local variables moved into u.bo */
+#endif /* local variables moved into u.bp */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bo.pC = p->apCsr[pOp->p1];
-  assert( u.bo.pC!=0 );
-  u.bo.pCrsr = u.bo.pC->pCursor;
-  u.bo.res = 0;
-  if( ALWAYS(u.bo.pCrsr!=0) ){
-    rc = sqlite3BtreeLast(u.bo.pCrsr, &u.bo.res);
+  u.bp.pC = p->apCsr[pOp->p1];
+  assert( u.bp.pC!=0 );
+  u.bp.pCrsr = u.bp.pC->pCursor;
+  u.bp.res = 0;
+  if( ALWAYS(u.bp.pCrsr!=0) ){
+    rc = sqlite3BtreeLast(u.bp.pCrsr, &u.bp.res);
   }
-  u.bo.pC->nullRow = (u8)u.bo.res;
-  u.bo.pC->deferredMoveto = 0;
-  u.bo.pC->rowidIsValid = 0;
-  u.bo.pC->cacheStatus = CACHE_STALE;
-  if( pOp->p2>0 && u.bo.res ){
+  u.bp.pC->nullRow = (u8)u.bp.res;
+  u.bp.pC->deferredMoveto = 0;
+  u.bp.pC->rowidIsValid = 0;
+  u.bp.pC->cacheStatus = CACHE_STALE;
+  if( pOp->p2>0 && u.bp.res ){
     pc = pOp->p2 - 1;
   }
   break;
@@ -67930,31 +68441,31 @@ case OP_Sort: {        /* jump */
 ** to the following instruction.
 */
 case OP_Rewind: {        /* jump */
-#if 0  /* local variables moved into u.bp */
+#if 0  /* local variables moved into u.bq */
   VdbeCursor *pC;
   BtCursor *pCrsr;
   int res;
-#endif /* local variables moved into u.bp */
+#endif /* local variables moved into u.bq */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bp.pC = p->apCsr[pOp->p1];
-  assert( u.bp.pC!=0 );
-  assert( u.bp.pC->isSorter==(pOp->opcode==OP_SorterSort) );
-  u.bp.res = 1;
-  if( isSorter(u.bp.pC) ){
-    rc = sqlite3VdbeSorterRewind(db, u.bp.pC, &u.bp.res);
-  }else{
-    u.bp.pCrsr = u.bp.pC->pCursor;
-    assert( u.bp.pCrsr );
-    rc = sqlite3BtreeFirst(u.bp.pCrsr, &u.bp.res);
-    u.bp.pC->atFirst = u.bp.res==0 ?1:0;
-    u.bp.pC->deferredMoveto = 0;
-    u.bp.pC->cacheStatus = CACHE_STALE;
-    u.bp.pC->rowidIsValid = 0;
+  u.bq.pC = p->apCsr[pOp->p1];
+  assert( u.bq.pC!=0 );
+  assert( u.bq.pC->isSorter==(pOp->opcode==OP_SorterSort) );
+  u.bq.res = 1;
+  if( isSorter(u.bq.pC) ){
+    rc = sqlite3VdbeSorterRewind(db, u.bq.pC, &u.bq.res);
+  }else{
+    u.bq.pCrsr = u.bq.pC->pCursor;
+    assert( u.bq.pCrsr );
+    rc = sqlite3BtreeFirst(u.bq.pCrsr, &u.bq.res);
+    u.bq.pC->atFirst = u.bq.res==0 ?1:0;
+    u.bq.pC->deferredMoveto = 0;
+    u.bq.pC->cacheStatus = CACHE_STALE;
+    u.bq.pC->rowidIsValid = 0;
   }
-  u.bp.pC->nullRow = (u8)u.bp.res;
+  u.bq.pC->nullRow = (u8)u.bq.res;
   assert( pOp->p2>0 && pOp->p2<p->nOp );
-  if( u.bp.res ){
+  if( u.bq.res ){
     pc = pOp->p2 - 1;
   }
   break;
@@ -67998,40 +68509,40 @@ case OP_SorterNext:    /* jump */
 #endif
 case OP_Prev:          /* jump */
 case OP_Next: {        /* jump */
-#if 0  /* local variables moved into u.bq */
+#if 0  /* local variables moved into u.br */
   VdbeCursor *pC;
   int res;
-#endif /* local variables moved into u.bq */
+#endif /* local variables moved into u.br */
 
   CHECK_FOR_INTERRUPT;
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
   assert( pOp->p5<=ArraySize(p->aCounter) );
-  u.bq.pC = p->apCsr[pOp->p1];
-  if( u.bq.pC==0 ){
+  u.br.pC = p->apCsr[pOp->p1];
+  if( u.br.pC==0 ){
     break;  /* See ticket #2273 */
   }
-  assert( u.bq.pC->isSorter==(pOp->opcode==OP_SorterNext) );
-  if( isSorter(u.bq.pC) ){
+  assert( u.br.pC->isSorter==(pOp->opcode==OP_SorterNext) );
+  if( isSorter(u.br.pC) ){
     assert( pOp->opcode==OP_SorterNext );
-    rc = sqlite3VdbeSorterNext(db, u.bq.pC, &u.bq.res);
+    rc = sqlite3VdbeSorterNext(db, u.br.pC, &u.br.res);
   }else{
-    u.bq.res = 1;
-    assert( u.bq.pC->deferredMoveto==0 );
-    assert( u.bq.pC->pCursor );
+    u.br.res = 1;
+    assert( u.br.pC->deferredMoveto==0 );
+    assert( u.br.pC->pCursor );
     assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
     assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
-    rc = pOp->p4.xAdvance(u.bq.pC->pCursor, &u.bq.res);
+    rc = pOp->p4.xAdvance(u.br.pC->pCursor, &u.br.res);
   }
-  u.bq.pC->nullRow = (u8)u.bq.res;
-  u.bq.pC->cacheStatus = CACHE_STALE;
-  if( u.bq.res==0 ){
+  u.br.pC->nullRow = (u8)u.br.res;
+  u.br.pC->cacheStatus = CACHE_STALE;
+  if( u.br.res==0 ){
     pc = pOp->p2 - 1;
     if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
 #ifdef SQLITE_TEST
     sqlite3_search_count++;
 #endif
   }
-  u.bq.pC->rowidIsValid = 0;
+  u.br.pC->rowidIsValid = 0;
   break;
 }
 
@@ -68052,34 +68563,34 @@ case OP_SorterInsert:       /* in2 */
   pOp->opcode = OP_IdxInsert;
 #endif
 case OP_IdxInsert: {        /* in2 */
-#if 0  /* local variables moved into u.br */
+#if 0  /* local variables moved into u.bs */
   VdbeCursor *pC;
   BtCursor *pCrsr;
   int nKey;
   const char *zKey;
-#endif /* local variables moved into u.br */
+#endif /* local variables moved into u.bs */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.br.pC = p->apCsr[pOp->p1];
-  assert( u.br.pC!=0 );
-  assert( u.br.pC->isSorter==(pOp->opcode==OP_SorterInsert) );
+  u.bs.pC = p->apCsr[pOp->p1];
+  assert( u.bs.pC!=0 );
+  assert( u.bs.pC->isSorter==(pOp->opcode==OP_SorterInsert) );
   pIn2 = &aMem[pOp->p2];
   assert( pIn2->flags & MEM_Blob );
-  u.br.pCrsr = u.br.pC->pCursor;
-  if( ALWAYS(u.br.pCrsr!=0) ){
-    assert( u.br.pC->isTable==0 );
+  u.bs.pCrsr = u.bs.pC->pCursor;
+  if( ALWAYS(u.bs.pCrsr!=0) ){
+    assert( u.bs.pC->isTable==0 );
     rc = ExpandBlob(pIn2);
     if( rc==SQLITE_OK ){
-      if( isSorter(u.br.pC) ){
-        rc = sqlite3VdbeSorterWrite(db, u.br.pC, pIn2);
+      if( isSorter(u.bs.pC) ){
+        rc = sqlite3VdbeSorterWrite(db, u.bs.pC, pIn2);
       }else{
-        u.br.nKey = pIn2->n;
-        u.br.zKey = pIn2->z;
-        rc = sqlite3BtreeInsert(u.br.pCrsr, u.br.zKey, u.br.nKey, "", 0, 0, pOp->p3,
-            ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.br.pC->seekResult : 0)
+        u.bs.nKey = pIn2->n;
+        u.bs.zKey = pIn2->z;
+        rc = sqlite3BtreeInsert(u.bs.pCrsr, u.bs.zKey, u.bs.nKey, "", 0, 0, pOp->p3,
+            ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bs.pC->seekResult : 0)
             );
-        assert( u.br.pC->deferredMoveto==0 );
-        u.br.pC->cacheStatus = CACHE_STALE;
+        assert( u.bs.pC->deferredMoveto==0 );
+        u.bs.pC->cacheStatus = CACHE_STALE;
       }
     }
   }
@@ -68093,33 +68604,33 @@ case OP_IdxInsert: {        /* in2 */
 ** index opened by cursor P1.
 */
 case OP_IdxDelete: {
-#if 0  /* local variables moved into u.bs */
+#if 0  /* local variables moved into u.bt */
   VdbeCursor *pC;
   BtCursor *pCrsr;
   int res;
   UnpackedRecord r;
-#endif /* local variables moved into u.bs */
+#endif /* local variables moved into u.bt */
 
   assert( pOp->p3>0 );
   assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem+1 );
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bs.pC = p->apCsr[pOp->p1];
-  assert( u.bs.pC!=0 );
-  u.bs.pCrsr = u.bs.pC->pCursor;
-  if( ALWAYS(u.bs.pCrsr!=0) ){
-    u.bs.r.pKeyInfo = u.bs.pC->pKeyInfo;
-    u.bs.r.nField = (u16)pOp->p3;
-    u.bs.r.flags = 0;
-    u.bs.r.aMem = &aMem[pOp->p2];
+  u.bt.pC = p->apCsr[pOp->p1];
+  assert( u.bt.pC!=0 );
+  u.bt.pCrsr = u.bt.pC->pCursor;
+  if( ALWAYS(u.bt.pCrsr!=0) ){
+    u.bt.r.pKeyInfo = u.bt.pC->pKeyInfo;
+    u.bt.r.nField = (u16)pOp->p3;
+    u.bt.r.flags = 0;
+    u.bt.r.aMem = &aMem[pOp->p2];
 #ifdef SQLITE_DEBUG
-    { int i; for(i=0; i<u.bs.r.nField; i++) assert( memIsValid(&u.bs.r.aMem[i]) ); }
+    { int i; for(i=0; i<u.bt.r.nField; i++) assert( memIsValid(&u.bt.r.aMem[i]) ); }
 #endif
-    rc = sqlite3BtreeMovetoUnpacked(u.bs.pCrsr, &u.bs.r, 0, 0, &u.bs.res);
-    if( rc==SQLITE_OK && u.bs.res==0 ){
-      rc = sqlite3BtreeDelete(u.bs.pCrsr);
+    rc = sqlite3BtreeMovetoUnpacked(u.bt.pCrsr, &u.bt.r, 0, 0, &u.bt.res);
+    if( rc==SQLITE_OK && u.bt.res==0 ){
+      rc = sqlite3BtreeDelete(u.bt.pCrsr);
     }
-    assert( u.bs.pC->deferredMoveto==0 );
-    u.bs.pC->cacheStatus = CACHE_STALE;
+    assert( u.bt.pC->deferredMoveto==0 );
+    u.bt.pC->cacheStatus = CACHE_STALE;
   }
   break;
 }
@@ -68133,28 +68644,28 @@ case OP_IdxDelete: {
 ** See also: Rowid, MakeRecord.
 */
 case OP_IdxRowid: {              /* out2-prerelease */
-#if 0  /* local variables moved into u.bt */
+#if 0  /* local variables moved into u.bu */
   BtCursor *pCrsr;
   VdbeCursor *pC;
   i64 rowid;
-#endif /* local variables moved into u.bt */
+#endif /* local variables moved into u.bu */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bt.pC = p->apCsr[pOp->p1];
-  assert( u.bt.pC!=0 );
-  u.bt.pCrsr = u.bt.pC->pCursor;
+  u.bu.pC = p->apCsr[pOp->p1];
+  assert( u.bu.pC!=0 );
+  u.bu.pCrsr = u.bu.pC->pCursor;
   pOut->flags = MEM_Null;
-  if( ALWAYS(u.bt.pCrsr!=0) ){
-    rc = sqlite3VdbeCursorMoveto(u.bt.pC);
+  if( ALWAYS(u.bu.pCrsr!=0) ){
+    rc = sqlite3VdbeCursorMoveto(u.bu.pC);
     if( NEVER(rc) ) goto abort_due_to_error;
-    assert( u.bt.pC->deferredMoveto==0 );
-    assert( u.bt.pC->isTable==0 );
-    if( !u.bt.pC->nullRow ){
-      rc = sqlite3VdbeIdxRowid(db, u.bt.pCrsr, &u.bt.rowid);
+    assert( u.bu.pC->deferredMoveto==0 );
+    assert( u.bu.pC->isTable==0 );
+    if( !u.bu.pC->nullRow ){
+      rc = sqlite3VdbeIdxRowid(db, u.bu.pCrsr, &u.bu.rowid);
       if( rc!=SQLITE_OK ){
         goto abort_due_to_error;
       }
-      pOut->u.i = u.bt.rowid;
+      pOut->u.i = u.bu.rowid;
       pOut->flags = MEM_Int;
     }
   }
@@ -68189,39 +68700,39 @@ case OP_IdxRowid: {              /* out2-prerelease */
 */
 case OP_IdxLT:          /* jump */
 case OP_IdxGE: {        /* jump */
-#if 0  /* local variables moved into u.bu */
+#if 0  /* local variables moved into u.bv */
   VdbeCursor *pC;
   int res;
   UnpackedRecord r;
-#endif /* local variables moved into u.bu */
+#endif /* local variables moved into u.bv */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bu.pC = p->apCsr[pOp->p1];
-  assert( u.bu.pC!=0 );
-  assert( u.bu.pC->isOrdered );
-  if( ALWAYS(u.bu.pC->pCursor!=0) ){
-    assert( u.bu.pC->deferredMoveto==0 );
+  u.bv.pC = p->apCsr[pOp->p1];
+  assert( u.bv.pC!=0 );
+  assert( u.bv.pC->isOrdered );
+  if( ALWAYS(u.bv.pC->pCursor!=0) ){
+    assert( u.bv.pC->deferredMoveto==0 );
     assert( pOp->p5==0 || pOp->p5==1 );
     assert( pOp->p4type==P4_INT32 );
-    u.bu.r.pKeyInfo = u.bu.pC->pKeyInfo;
-    u.bu.r.nField = (u16)pOp->p4.i;
+    u.bv.r.pKeyInfo = u.bv.pC->pKeyInfo;
+    u.bv.r.nField = (u16)pOp->p4.i;
     if( pOp->p5 ){
-      u.bu.r.flags = UNPACKED_INCRKEY | UNPACKED_PREFIX_MATCH;
+      u.bv.r.flags = UNPACKED_INCRKEY | UNPACKED_PREFIX_MATCH;
     }else{
-      u.bu.r.flags = UNPACKED_PREFIX_MATCH;
+      u.bv.r.flags = UNPACKED_PREFIX_MATCH;
     }
-    u.bu.r.aMem = &aMem[pOp->p3];
+    u.bv.r.aMem = &aMem[pOp->p3];
 #ifdef SQLITE_DEBUG
-    { int i; for(i=0; i<u.bu.r.nField; i++) assert( memIsValid(&u.bu.r.aMem[i]) ); }
+    { int i; for(i=0; i<u.bv.r.nField; i++) assert( memIsValid(&u.bv.r.aMem[i]) ); }
 #endif
-    rc = sqlite3VdbeIdxKeyCompare(u.bu.pC, &u.bu.r, &u.bu.res);
+    rc = sqlite3VdbeIdxKeyCompare(u.bv.pC, &u.bv.r, &u.bv.res);
     if( pOp->opcode==OP_IdxLT ){
-      u.bu.res = -u.bu.res;
+      u.bv.res = -u.bv.res;
     }else{
       assert( pOp->opcode==OP_IdxGE );
-      u.bu.res++;
+      u.bv.res++;
     }
-    if( u.bu.res>0 ){
+    if( u.bv.res>0 ){
       pc = pOp->p2 - 1 ;
     }
   }
@@ -68249,39 +68760,40 @@ case OP_IdxGE: {        /* jump */
 ** See also: Clear
 */
 case OP_Destroy: {     /* out2-prerelease */
-#if 0  /* local variables moved into u.bv */
+#if 0  /* local variables moved into u.bw */
   int iMoved;
   int iCnt;
   Vdbe *pVdbe;
   int iDb;
-#endif /* local variables moved into u.bv */
+#endif /* local variables moved into u.bw */
+
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  u.bv.iCnt = 0;
-  for(u.bv.pVdbe=db->pVdbe; u.bv.pVdbe; u.bv.pVdbe = u.bv.pVdbe->pNext){
-    if( u.bv.pVdbe->magic==VDBE_MAGIC_RUN && u.bv.pVdbe->inVtabMethod<2 && u.bv.pVdbe->pc>=0 ){
-      u.bv.iCnt++;
+  u.bw.iCnt = 0;
+  for(u.bw.pVdbe=db->pVdbe; u.bw.pVdbe; u.bw.pVdbe = u.bw.pVdbe->pNext){
+    if( u.bw.pVdbe->magic==VDBE_MAGIC_RUN && u.bw.pVdbe->inVtabMethod<2 && u.bw.pVdbe->pc>=0 ){
+      u.bw.iCnt++;
     }
   }
 #else
-  u.bv.iCnt = db->activeVdbeCnt;
+  u.bw.iCnt = db->activeVdbeCnt;
 #endif
   pOut->flags = MEM_Null;
-  if( u.bv.iCnt>1 ){
+  if( u.bw.iCnt>1 ){
     rc = SQLITE_LOCKED;
     p->errorAction = OE_Abort;
   }else{
-    u.bv.iDb = pOp->p3;
-    assert( u.bv.iCnt==1 );
-    assert( (p->btreeMask & (((yDbMask)1)<<u.bv.iDb))!=0 );
-    rc = sqlite3BtreeDropTable(db->aDb[u.bv.iDb].pBt, pOp->p1, &u.bv.iMoved);
+    u.bw.iDb = pOp->p3;
+    assert( u.bw.iCnt==1 );
+    assert( (p->btreeMask & (((yDbMask)1)<<u.bw.iDb))!=0 );
+    rc = sqlite3BtreeDropTable(db->aDb[u.bw.iDb].pBt, pOp->p1, &u.bw.iMoved);
     pOut->flags = MEM_Int;
-    pOut->u.i = u.bv.iMoved;
+    pOut->u.i = u.bw.iMoved;
 #ifndef SQLITE_OMIT_AUTOVACUUM
-    if( rc==SQLITE_OK && u.bv.iMoved!=0 ){
-      sqlite3RootPageMoved(db, u.bv.iDb, u.bv.iMoved, pOp->p1);
+    if( rc==SQLITE_OK && u.bw.iMoved!=0 ){
+      sqlite3RootPageMoved(db, u.bw.iDb, u.bw.iMoved, pOp->p1);
       /* All OP_Destroy operations occur on the same btree */
-      assert( resetSchemaOnFault==0 || resetSchemaOnFault==u.bv.iDb+1 );
-      resetSchemaOnFault = u.bv.iDb+1;
+      assert( resetSchemaOnFault==0 || resetSchemaOnFault==u.bw.iDb+1 );
+      resetSchemaOnFault = u.bw.iDb+1;
     }
 #endif
   }
@@ -68307,21 +68819,21 @@ case OP_Destroy: {     /* out2-prerelease */
 ** See also: Destroy
 */
 case OP_Clear: {
-#if 0  /* local variables moved into u.bw */
+#if 0  /* local variables moved into u.bx */
   int nChange;
-#endif /* local variables moved into u.bw */
+#endif /* local variables moved into u.bx */
 
-  u.bw.nChange = 0;
+  u.bx.nChange = 0;
   assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 );
   rc = sqlite3BtreeClearTable(
-      db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bw.nChange : 0)
+      db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bx.nChange : 0)
   );
   if( pOp->p3 ){
-    p->nChange += u.bw.nChange;
+    p->nChange += u.bx.nChange;
     if( pOp->p3>0 ){
       assert( memIsValid(&aMem[pOp->p3]) );
       memAboutToChange(p, &aMem[pOp->p3]);
-      aMem[pOp->p3].u.i += u.bw.nChange;
+      aMem[pOp->p3].u.i += u.bx.nChange;
     }
   }
   break;
@@ -68351,25 +68863,25 @@ case OP_Clear: {
 */
 case OP_CreateIndex:            /* out2-prerelease */
 case OP_CreateTable: {          /* out2-prerelease */
-#if 0  /* local variables moved into u.bx */
+#if 0  /* local variables moved into u.by */
   int pgno;
   int flags;
   Db *pDb;
-#endif /* local variables moved into u.bx */
+#endif /* local variables moved into u.by */
 
-  u.bx.pgno = 0;
+  u.by.pgno = 0;
   assert( pOp->p1>=0 && pOp->p1<db->nDb );
   assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
-  u.bx.pDb = &db->aDb[pOp->p1];
-  assert( u.bx.pDb->pBt!=0 );
+  u.by.pDb = &db->aDb[pOp->p1];
+  assert( u.by.pDb->pBt!=0 );
   if( pOp->opcode==OP_CreateTable ){
-    /* u.bx.flags = BTREE_INTKEY; */
-    u.bx.flags = BTREE_INTKEY;
+    /* u.by.flags = BTREE_INTKEY; */
+    u.by.flags = BTREE_INTKEY;
   }else{
-    u.bx.flags = BTREE_BLOBKEY;
+    u.by.flags = BTREE_BLOBKEY;
   }
-  rc = sqlite3BtreeCreateTable(u.bx.pDb->pBt, &u.bx.pgno, u.bx.flags);
-  pOut->u.i = u.bx.pgno;
+  rc = sqlite3BtreeCreateTable(u.by.pDb->pBt, &u.by.pgno, u.by.flags);
+  pOut->u.i = u.by.pgno;
   break;
 }
 
@@ -68382,44 +68894,44 @@ case OP_CreateTable: {          /* out2-prerelease */
 ** then runs the new virtual machine.  It is thus a re-entrant opcode.
 */
 case OP_ParseSchema: {
-#if 0  /* local variables moved into u.by */
+#if 0  /* local variables moved into u.bz */
   int iDb;
   const char *zMaster;
   char *zSql;
   InitData initData;
-#endif /* local variables moved into u.by */
+#endif /* local variables moved into u.bz */
 
   /* Any prepared statement that invokes this opcode will hold mutexes
   ** on every btree.  This is a prerequisite for invoking
   ** sqlite3InitCallback().
   */
 #ifdef SQLITE_DEBUG
-  for(u.by.iDb=0; u.by.iDb<db->nDb; u.by.iDb++){
-    assert( u.by.iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[u.by.iDb].pBt) );
+  for(u.bz.iDb=0; u.bz.iDb<db->nDb; u.bz.iDb++){
+    assert( u.bz.iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[u.bz.iDb].pBt) );
   }
 #endif
 
-  u.by.iDb = pOp->p1;
-  assert( u.by.iDb>=0 && u.by.iDb<db->nDb );
-  assert( DbHasProperty(db, u.by.iDb, DB_SchemaLoaded) );
+  u.bz.iDb = pOp->p1;
+  assert( u.bz.iDb>=0 && u.bz.iDb<db->nDb );
+  assert( DbHasProperty(db, u.bz.iDb, DB_SchemaLoaded) );
   /* Used to be a conditional */ {
-    u.by.zMaster = SCHEMA_TABLE(u.by.iDb);
-    u.by.initData.db = db;
-    u.by.initData.iDb = pOp->p1;
-    u.by.initData.pzErrMsg = &p->zErrMsg;
-    u.by.zSql = sqlite3MPrintf(db,
+    u.bz.zMaster = SCHEMA_TABLE(u.bz.iDb);
+    u.bz.initData.db = db;
+    u.bz.initData.iDb = pOp->p1;
+    u.bz.initData.pzErrMsg = &p->zErrMsg;
+    u.bz.zSql = sqlite3MPrintf(db,
        "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
-       db->aDb[u.by.iDb].zName, u.by.zMaster, pOp->p4.z);
-    if( u.by.zSql==0 ){
+       db->aDb[u.bz.iDb].zName, u.bz.zMaster, pOp->p4.z);
+    if( u.bz.zSql==0 ){
       rc = SQLITE_NOMEM;
     }else{
       assert( db->init.busy==0 );
       db->init.busy = 1;
-      u.by.initData.rc = SQLITE_OK;
+      u.bz.initData.rc = SQLITE_OK;
       assert( !db->mallocFailed );
-      rc = sqlite3_exec(db, u.by.zSql, sqlite3InitCallback, &u.by.initData, 0);
-      if( rc==SQLITE_OK ) rc = u.by.initData.rc;
-      sqlite3DbFree(db, u.by.zSql);
+      rc = sqlite3_exec(db, u.bz.zSql, sqlite3InitCallback, &u.bz.initData, 0);
+      if( rc==SQLITE_OK ) rc = u.bz.initData.rc;
+      sqlite3DbFree(db, u.bz.zSql);
       db->init.busy = 0;
     }
   }
@@ -68503,41 +69015,41 @@ case OP_DropTrigger: {
 ** This opcode is used to implement the integrity_check pragma.
 */
 case OP_IntegrityCk: {
-#if 0  /* local variables moved into u.bz */
+#if 0  /* local variables moved into u.ca */
   int nRoot;      /* Number of tables to check.  (Number of root pages.) */
   int *aRoot;     /* Array of rootpage numbers for tables to be checked */
   int j;          /* Loop counter */
   int nErr;       /* Number of errors reported */
   char *z;        /* Text of the error report */
   Mem *pnErr;     /* Register keeping track of errors remaining */
-#endif /* local variables moved into u.bz */
+#endif /* local variables moved into u.ca */
 
-  u.bz.nRoot = pOp->p2;
-  assert( u.bz.nRoot>0 );
-  u.bz.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.bz.nRoot+1) );
-  if( u.bz.aRoot==0 ) goto no_mem;
+  u.ca.nRoot = pOp->p2;
+  assert( u.ca.nRoot>0 );
+  u.ca.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.ca.nRoot+1) );
+  if( u.ca.aRoot==0 ) goto no_mem;
   assert( pOp->p3>0 && pOp->p3<=p->nMem );
-  u.bz.pnErr = &aMem[pOp->p3];
-  assert( (u.bz.pnErr->flags & MEM_Int)!=0 );
-  assert( (u.bz.pnErr->flags & (MEM_Str|MEM_Blob))==0 );
+  u.ca.pnErr = &aMem[pOp->p3];
+  assert( (u.ca.pnErr->flags & MEM_Int)!=0 );
+  assert( (u.ca.pnErr->flags & (MEM_Str|MEM_Blob))==0 );
   pIn1 = &aMem[pOp->p1];
-  for(u.bz.j=0; u.bz.j<u.bz.nRoot; u.bz.j++){
-    u.bz.aRoot[u.bz.j] = (int)sqlite3VdbeIntValue(&pIn1[u.bz.j]);
+  for(u.ca.j=0; u.ca.j<u.ca.nRoot; u.ca.j++){
+    u.ca.aRoot[u.ca.j] = (int)sqlite3VdbeIntValue(&pIn1[u.ca.j]);
   }
-  u.bz.aRoot[u.bz.j] = 0;
+  u.ca.aRoot[u.ca.j] = 0;
   assert( pOp->p5<db->nDb );
   assert( (p->btreeMask & (((yDbMask)1)<<pOp->p5))!=0 );
-  u.bz.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.bz.aRoot, u.bz.nRoot,
-                                 (int)u.bz.pnErr->u.i, &u.bz.nErr);
-  sqlite3DbFree(db, u.bz.aRoot);
-  u.bz.pnErr->u.i -= u.bz.nErr;
+  u.ca.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.ca.aRoot, u.ca.nRoot,
+                                 (int)u.ca.pnErr->u.i, &u.ca.nErr);
+  sqlite3DbFree(db, u.ca.aRoot);
+  u.ca.pnErr->u.i -= u.ca.nErr;
   sqlite3VdbeMemSetNull(pIn1);
-  if( u.bz.nErr==0 ){
-    assert( u.bz.z==0 );
-  }else if( u.bz.z==0 ){
+  if( u.ca.nErr==0 ){
+    assert( u.ca.z==0 );
+  }else if( u.ca.z==0 ){
     goto no_mem;
   }else{
-    sqlite3VdbeMemSetStr(pIn1, u.bz.z, -1, SQLITE_UTF8, sqlite3_free);
+    sqlite3VdbeMemSetStr(pIn1, u.ca.z, -1, SQLITE_UTF8, sqlite3_free);
   }
   UPDATE_MAX_BLOBSIZE(pIn1);
   sqlite3VdbeChangeEncoding(pIn1, encoding);
@@ -68571,20 +69083,20 @@ case OP_RowSetAdd: {       /* in1, in2 */
 ** unchanged and jump to instruction P2.
 */
 case OP_RowSetRead: {       /* jump, in1, out3 */
-#if 0  /* local variables moved into u.ca */
+#if 0  /* local variables moved into u.cb */
   i64 val;
-#endif /* local variables moved into u.ca */
+#endif /* local variables moved into u.cb */
   CHECK_FOR_INTERRUPT;
   pIn1 = &aMem[pOp->p1];
   if( (pIn1->flags & MEM_RowSet)==0
-   || sqlite3RowSetNext(pIn1->u.pRowSet, &u.ca.val)==0
+   || sqlite3RowSetNext(pIn1->u.pRowSet, &u.cb.val)==0
   ){
     /* The boolean index is empty */
     sqlite3VdbeMemSetNull(pIn1);
     pc = pOp->p2 - 1;
   }else{
     /* A value was pulled from the index */
-    sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.ca.val);
+    sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.cb.val);
   }
   break;
 }
@@ -68613,14 +69125,14 @@ case OP_RowSetRead: {       /* jump, in1, out3 */
 ** inserted as part of some other set).
 */
 case OP_RowSetTest: {                     /* jump, in1, in3 */
-#if 0  /* local variables moved into u.cb */
+#if 0  /* local variables moved into u.cc */
   int iSet;
   int exists;
-#endif /* local variables moved into u.cb */
+#endif /* local variables moved into u.cc */
 
   pIn1 = &aMem[pOp->p1];
   pIn3 = &aMem[pOp->p3];
-  u.cb.iSet = pOp->p4.i;
+  u.cc.iSet = pOp->p4.i;
   assert( pIn3->flags&MEM_Int );
 
   /* If there is anything other than a rowset object in memory cell P1,
@@ -68632,17 +69144,17 @@ case OP_RowSetTest: {                     /* jump, in1, in3 */
   }
 
   assert( pOp->p4type==P4_INT32 );
-  assert( u.cb.iSet==-1 || u.cb.iSet>=0 );
-  if( u.cb.iSet ){
-    u.cb.exists = sqlite3RowSetTest(pIn1->u.pRowSet,
-                               (u8)(u.cb.iSet>=0 ? u.cb.iSet & 0xf : 0xff),
+  assert( u.cc.iSet==-1 || u.cc.iSet>=0 );
+  if( u.cc.iSet ){
+    u.cc.exists = sqlite3RowSetTest(pIn1->u.pRowSet,
+                               (u8)(u.cc.iSet>=0 ? u.cc.iSet & 0xf : 0xff),
                                pIn3->u.i);
-    if( u.cb.exists ){
+    if( u.cc.exists ){
       pc = pOp->p2 - 1;
       break;
     }
   }
-  if( u.cb.iSet>=0 ){
+  if( u.cc.iSet>=0 ){
     sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i);
   }
   break;
@@ -68665,7 +69177,7 @@ case OP_RowSetTest: {                     /* jump, in1, in3 */
 ** P4 is a pointer to the VM containing the trigger program.
 */
 case OP_Program: {        /* jump */
-#if 0  /* local variables moved into u.cc */
+#if 0  /* local variables moved into u.cd */
   int nMem;               /* Number of memory registers for sub-program */
   int nByte;              /* Bytes of runtime space required for sub-program */
   Mem *pRt;               /* Register to allocate runtime space */
@@ -68674,11 +69186,11 @@ case OP_Program: {        /* jump */
   VdbeFrame *pFrame;      /* New vdbe frame to execute in */
   SubProgram *pProgram;   /* Sub-program to execute */
   void *t;                /* Token identifying trigger */
-#endif /* local variables moved into u.cc */
+#endif /* local variables moved into u.cd */
 
-  u.cc.pProgram = pOp->p4.pProgram;
-  u.cc.pRt = &aMem[pOp->p3];
-  assert( u.cc.pProgram->nOp>0 );
+  u.cd.pProgram = pOp->p4.pProgram;
+  u.cd.pRt = &aMem[pOp->p3];
+  assert( u.cd.pProgram->nOp>0 );
 
   /* If the p5 flag is clear, then recursive invocation of triggers is
   ** disabled for backwards compatibility (p5 is set if this sub-program
@@ -68692,9 +69204,9 @@ case OP_Program: {        /* jump */
   ** single trigger all have the same value for the SubProgram.token
   ** variable.  */
   if( pOp->p5 ){
-    u.cc.t = u.cc.pProgram->token;
-    for(u.cc.pFrame=p->pFrame; u.cc.pFrame && u.cc.pFrame->token!=u.cc.t; u.cc.pFrame=u.cc.pFrame->pParent);
-    if( u.cc.pFrame ) break;
+    u.cd.t = u.cd.pProgram->token;
+    for(u.cd.pFrame=p->pFrame; u.cd.pFrame && u.cd.pFrame->token!=u.cd.t; u.cd.pFrame=u.cd.pFrame->pParent);
+    if( u.cd.pFrame ) break;
   }
 
   if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
@@ -68703,69 +69215,69 @@ case OP_Program: {        /* jump */
     break;
   }
 
-  /* Register u.cc.pRt is used to store the memory required to save the state
+  /* Register u.cd.pRt is used to store the memory required to save the state
   ** of the current program, and the memory required at runtime to execute
-  ** the trigger program. If this trigger has been fired before, then u.cc.pRt
+  ** the trigger program. If this trigger has been fired before, then u.cd.pRt
   ** is already allocated. Otherwise, it must be initialized.  */
-  if( (u.cc.pRt->flags&MEM_Frame)==0 ){
+  if( (u.cd.pRt->flags&MEM_Frame)==0 ){
     /* SubProgram.nMem is set to the number of memory cells used by the
     ** program stored in SubProgram.aOp. As well as these, one memory
     ** cell is required for each cursor used by the program. Set local
-    ** variable u.cc.nMem (and later, VdbeFrame.nChildMem) to this value.
+    ** variable u.cd.nMem (and later, VdbeFrame.nChildMem) to this value.
     */
-    u.cc.nMem = u.cc.pProgram->nMem + u.cc.pProgram->nCsr;
-    u.cc.nByte = ROUND8(sizeof(VdbeFrame))
-              + u.cc.nMem * sizeof(Mem)
-              + u.cc.pProgram->nCsr * sizeof(VdbeCursor *)
-              + u.cc.pProgram->nOnce * sizeof(u8);
-    u.cc.pFrame = sqlite3DbMallocZero(db, u.cc.nByte);
-    if( !u.cc.pFrame ){
+    u.cd.nMem = u.cd.pProgram->nMem + u.cd.pProgram->nCsr;
+    u.cd.nByte = ROUND8(sizeof(VdbeFrame))
+              + u.cd.nMem * sizeof(Mem)
+              + u.cd.pProgram->nCsr * sizeof(VdbeCursor *)
+              + u.cd.pProgram->nOnce * sizeof(u8);
+    u.cd.pFrame = sqlite3DbMallocZero(db, u.cd.nByte);
+    if( !u.cd.pFrame ){
       goto no_mem;
     }
-    sqlite3VdbeMemRelease(u.cc.pRt);
-    u.cc.pRt->flags = MEM_Frame;
-    u.cc.pRt->u.pFrame = u.cc.pFrame;
+    sqlite3VdbeMemRelease(u.cd.pRt);
+    u.cd.pRt->flags = MEM_Frame;
+    u.cd.pRt->u.pFrame = u.cd.pFrame;
 
-    u.cc.pFrame->v = p;
-    u.cc.pFrame->nChildMem = u.cc.nMem;
-    u.cc.pFrame->nChildCsr = u.cc.pProgram->nCsr;
-    u.cc.pFrame->pc = pc;
-    u.cc.pFrame->aMem = p->aMem;
-    u.cc.pFrame->nMem = p->nMem;
-    u.cc.pFrame->apCsr = p->apCsr;
-    u.cc.pFrame->nCursor = p->nCursor;
-    u.cc.pFrame->aOp = p->aOp;
-    u.cc.pFrame->nOp = p->nOp;
-    u.cc.pFrame->token = u.cc.pProgram->token;
-    u.cc.pFrame->aOnceFlag = p->aOnceFlag;
-    u.cc.pFrame->nOnceFlag = p->nOnceFlag;
+    u.cd.pFrame->v = p;
+    u.cd.pFrame->nChildMem = u.cd.nMem;
+    u.cd.pFrame->nChildCsr = u.cd.pProgram->nCsr;
+    u.cd.pFrame->pc = pc;
+    u.cd.pFrame->aMem = p->aMem;
+    u.cd.pFrame->nMem = p->nMem;
+    u.cd.pFrame->apCsr = p->apCsr;
+    u.cd.pFrame->nCursor = p->nCursor;
+    u.cd.pFrame->aOp = p->aOp;
+    u.cd.pFrame->nOp = p->nOp;
+    u.cd.pFrame->token = u.cd.pProgram->token;
+    u.cd.pFrame->aOnceFlag = p->aOnceFlag;
+    u.cd.pFrame->nOnceFlag = p->nOnceFlag;
 
-    u.cc.pEnd = &VdbeFrameMem(u.cc.pFrame)[u.cc.pFrame->nChildMem];
-    for(u.cc.pMem=VdbeFrameMem(u.cc.pFrame); u.cc.pMem!=u.cc.pEnd; u.cc.pMem++){
-      u.cc.pMem->flags = MEM_Invalid;
-      u.cc.pMem->db = db;
+    u.cd.pEnd = &VdbeFrameMem(u.cd.pFrame)[u.cd.pFrame->nChildMem];
+    for(u.cd.pMem=VdbeFrameMem(u.cd.pFrame); u.cd.pMem!=u.cd.pEnd; u.cd.pMem++){
+      u.cd.pMem->flags = MEM_Invalid;
+      u.cd.pMem->db = db;
     }
   }else{
-    u.cc.pFrame = u.cc.pRt->u.pFrame;
-    assert( u.cc.pProgram->nMem+u.cc.pProgram->nCsr==u.cc.pFrame->nChildMem );
-    assert( u.cc.pProgram->nCsr==u.cc.pFrame->nChildCsr );
-    assert( pc==u.cc.pFrame->pc );
+    u.cd.pFrame = u.cd.pRt->u.pFrame;
+    assert( u.cd.pProgram->nMem+u.cd.pProgram->nCsr==u.cd.pFrame->nChildMem );
+    assert( u.cd.pProgram->nCsr==u.cd.pFrame->nChildCsr );
+    assert( pc==u.cd.pFrame->pc );
   }
 
   p->nFrame++;
-  u.cc.pFrame->pParent = p->pFrame;
-  u.cc.pFrame->lastRowid = lastRowid;
-  u.cc.pFrame->nChange = p->nChange;
+  u.cd.pFrame->pParent = p->pFrame;
+  u.cd.pFrame->lastRowid = lastRowid;
+  u.cd.pFrame->nChange = p->nChange;
   p->nChange = 0;
-  p->pFrame = u.cc.pFrame;
-  p->aMem = aMem = &VdbeFrameMem(u.cc.pFrame)[-1];
-  p->nMem = u.cc.pFrame->nChildMem;
-  p->nCursor = (u16)u.cc.pFrame->nChildCsr;
+  p->pFrame = u.cd.pFrame;
+  p->aMem = aMem = &VdbeFrameMem(u.cd.pFrame)[-1];
+  p->nMem = u.cd.pFrame->nChildMem;
+  p->nCursor = (u16)u.cd.pFrame->nChildCsr;
   p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
-  p->aOp = aOp = u.cc.pProgram->aOp;
-  p->nOp = u.cc.pProgram->nOp;
+  p->aOp = aOp = u.cd.pProgram->aOp;
+  p->nOp = u.cd.pProgram->nOp;
   p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor];
-  p->nOnceFlag = u.cc.pProgram->nOnce;
+  p->nOnceFlag = u.cd.pProgram->nOnce;
   pc = -1;
   memset(p->aOnceFlag, 0, p->nOnceFlag);
 
@@ -68785,13 +69297,13 @@ case OP_Program: {        /* jump */
 ** calling OP_Program instruction.
 */
 case OP_Param: {           /* out2-prerelease */
-#if 0  /* local variables moved into u.cd */
+#if 0  /* local variables moved into u.ce */
   VdbeFrame *pFrame;
   Mem *pIn;
-#endif /* local variables moved into u.cd */
-  u.cd.pFrame = p->pFrame;
-  u.cd.pIn = &u.cd.pFrame->aMem[pOp->p1 + u.cd.pFrame->aOp[u.cd.pFrame->pc].p1];
-  sqlite3VdbeMemShallowCopy(pOut, u.cd.pIn, MEM_Ephem);
+#endif /* local variables moved into u.ce */
+  u.ce.pFrame = p->pFrame;
+  u.ce.pIn = &u.ce.pFrame->aMem[pOp->p1 + u.ce.pFrame->aOp[u.ce.pFrame->pc].p1];
+  sqlite3VdbeMemShallowCopy(pOut, u.ce.pIn, MEM_Ephem);
   break;
 }
 
@@ -68847,22 +69359,22 @@ case OP_FkIfZero: {         /* jump */
 ** an integer.
 */
 case OP_MemMax: {        /* in2 */
-#if 0  /* local variables moved into u.ce */
+#if 0  /* local variables moved into u.cf */
   Mem *pIn1;
   VdbeFrame *pFrame;
-#endif /* local variables moved into u.ce */
+#endif /* local variables moved into u.cf */
   if( p->pFrame ){
-    for(u.ce.pFrame=p->pFrame; u.ce.pFrame->pParent; u.ce.pFrame=u.ce.pFrame->pParent);
-    u.ce.pIn1 = &u.ce.pFrame->aMem[pOp->p1];
+    for(u.cf.pFrame=p->pFrame; u.cf.pFrame->pParent; u.cf.pFrame=u.cf.pFrame->pParent);
+    u.cf.pIn1 = &u.cf.pFrame->aMem[pOp->p1];
   }else{
-    u.ce.pIn1 = &aMem[pOp->p1];
+    u.cf.pIn1 = &aMem[pOp->p1];
   }
-  assert( memIsValid(u.ce.pIn1) );
-  sqlite3VdbeMemIntegerify(u.ce.pIn1);
+  assert( memIsValid(u.cf.pIn1) );
+  sqlite3VdbeMemIntegerify(u.cf.pIn1);
   pIn2 = &aMem[pOp->p2];
   sqlite3VdbeMemIntegerify(pIn2);
-  if( u.ce.pIn1->u.i<pIn2->u.i){
-    u.ce.pIn1->u.i = pIn2->u.i;
+  if( u.cf.pIn1->u.i<pIn2->u.i){
+    u.cf.pIn1->u.i = pIn2->u.i;
   }
   break;
 }
@@ -68929,56 +69441,56 @@ case OP_IfZero: {        /* jump, in1 */
 ** successors.
 */
 case OP_AggStep: {
-#if 0  /* local variables moved into u.cf */
+#if 0  /* local variables moved into u.cg */
   int n;
   int i;
   Mem *pMem;
   Mem *pRec;
   sqlite3_context ctx;
   sqlite3_value **apVal;
-#endif /* local variables moved into u.cf */
+#endif /* local variables moved into u.cg */
 
-  u.cf.n = pOp->p5;
-  assert( u.cf.n>=0 );
-  u.cf.pRec = &aMem[pOp->p2];
-  u.cf.apVal = p->apArg;
-  assert( u.cf.apVal || u.cf.n==0 );
-  for(u.cf.i=0; u.cf.i<u.cf.n; u.cf.i++, u.cf.pRec++){
-    assert( memIsValid(u.cf.pRec) );
-    u.cf.apVal[u.cf.i] = u.cf.pRec;
-    memAboutToChange(p, u.cf.pRec);
-    sqlite3VdbeMemStoreType(u.cf.pRec);
-  }
-  u.cf.ctx.pFunc = pOp->p4.pFunc;
+  u.cg.n = pOp->p5;
+  assert( u.cg.n>=0 );
+  u.cg.pRec = &aMem[pOp->p2];
+  u.cg.apVal = p->apArg;
+  assert( u.cg.apVal || u.cg.n==0 );
+  for(u.cg.i=0; u.cg.i<u.cg.n; u.cg.i++, u.cg.pRec++){
+    assert( memIsValid(u.cg.pRec) );
+    u.cg.apVal[u.cg.i] = u.cg.pRec;
+    memAboutToChange(p, u.cg.pRec);
+    sqlite3VdbeMemStoreType(u.cg.pRec);
+  }
+  u.cg.ctx.pFunc = pOp->p4.pFunc;
   assert( pOp->p3>0 && pOp->p3<=p->nMem );
-  u.cf.ctx.pMem = u.cf.pMem = &aMem[pOp->p3];
-  u.cf.pMem->n++;
-  u.cf.ctx.s.flags = MEM_Null;
-  u.cf.ctx.s.z = 0;
-  u.cf.ctx.s.zMalloc = 0;
-  u.cf.ctx.s.xDel = 0;
-  u.cf.ctx.s.db = db;
-  u.cf.ctx.isError = 0;
-  u.cf.ctx.pColl = 0;
-  u.cf.ctx.skipFlag = 0;
-  if( u.cf.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
+  u.cg.ctx.pMem = u.cg.pMem = &aMem[pOp->p3];
+  u.cg.pMem->n++;
+  u.cg.ctx.s.flags = MEM_Null;
+  u.cg.ctx.s.z = 0;
+  u.cg.ctx.s.zMalloc = 0;
+  u.cg.ctx.s.xDel = 0;
+  u.cg.ctx.s.db = db;
+  u.cg.ctx.isError = 0;
+  u.cg.ctx.pColl = 0;
+  u.cg.ctx.skipFlag = 0;
+  if( u.cg.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
     assert( pOp>p->aOp );
     assert( pOp[-1].p4type==P4_COLLSEQ );
     assert( pOp[-1].opcode==OP_CollSeq );
-    u.cf.ctx.pColl = pOp[-1].p4.pColl;
+    u.cg.ctx.pColl = pOp[-1].p4.pColl;
   }
-  (u.cf.ctx.pFunc->xStep)(&u.cf.ctx, u.cf.n, u.cf.apVal); /* IMP: R-24505-23230 */
-  if( u.cf.ctx.isError ){
-    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.cf.ctx.s));
-    rc = u.cf.ctx.isError;
+  (u.cg.ctx.pFunc->xStep)(&u.cg.ctx, u.cg.n, u.cg.apVal); /* IMP: R-24505-23230 */
+  if( u.cg.ctx.isError ){
+    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.cg.ctx.s));
+    rc = u.cg.ctx.isError;
   }
-  if( u.cf.ctx.skipFlag ){
+  if( u.cg.ctx.skipFlag ){
     assert( pOp[-1].opcode==OP_CollSeq );
-    u.cf.i = pOp[-1].p1;
-    if( u.cf.i ) sqlite3VdbeMemSetInt64(&aMem[u.cf.i], 1);
+    u.cg.i = pOp[-1].p1;
+    if( u.cg.i ) sqlite3VdbeMemSetInt64(&aMem[u.cg.i], 1);
   }
 
-  sqlite3VdbeMemRelease(&u.cf.ctx.s);
+  sqlite3VdbeMemRelease(&u.cg.ctx.s);
 
   break;
 }
@@ -68996,19 +69508,19 @@ case OP_AggStep: {
 ** the step function was not previously called.
 */
 case OP_AggFinal: {
-#if 0  /* local variables moved into u.cg */
+#if 0  /* local variables moved into u.ch */
   Mem *pMem;
-#endif /* local variables moved into u.cg */
+#endif /* local variables moved into u.ch */
   assert( pOp->p1>0 && pOp->p1<=p->nMem );
-  u.cg.pMem = &aMem[pOp->p1];
-  assert( (u.cg.pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
-  rc = sqlite3VdbeMemFinalize(u.cg.pMem, pOp->p4.pFunc);
+  u.ch.pMem = &aMem[pOp->p1];
+  assert( (u.ch.pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
+  rc = sqlite3VdbeMemFinalize(u.ch.pMem, pOp->p4.pFunc);
   if( rc ){
-    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.cg.pMem));
+    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.ch.pMem));
   }
-  sqlite3VdbeChangeEncoding(u.cg.pMem, encoding);
-  UPDATE_MAX_BLOBSIZE(u.cg.pMem);
-  if( sqlite3VdbeMemTooBig(u.cg.pMem) ){
+  sqlite3VdbeChangeEncoding(u.ch.pMem, encoding);
+  UPDATE_MAX_BLOBSIZE(u.ch.pMem);
+  if( sqlite3VdbeMemTooBig(u.ch.pMem) ){
     goto too_big;
   }
   break;
@@ -69027,25 +69539,25 @@ case OP_AggFinal: {
 ** mem[P3+2] are initialized to -1.
 */
 case OP_Checkpoint: {
-#if 0  /* local variables moved into u.ch */
+#if 0  /* local variables moved into u.ci */
   int i;                          /* Loop counter */
   int aRes[3];                    /* Results */
   Mem *pMem;                      /* Write results here */
-#endif /* local variables moved into u.ch */
+#endif /* local variables moved into u.ci */
 
-  u.ch.aRes[0] = 0;
-  u.ch.aRes[1] = u.ch.aRes[2] = -1;
+  u.ci.aRes[0] = 0;
+  u.ci.aRes[1] = u.ci.aRes[2] = -1;
   assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE
        || pOp->p2==SQLITE_CHECKPOINT_FULL
        || pOp->p2==SQLITE_CHECKPOINT_RESTART
   );
-  rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &u.ch.aRes[1], &u.ch.aRes[2]);
+  rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &u.ci.aRes[1], &u.ci.aRes[2]);
   if( rc==SQLITE_BUSY ){
     rc = SQLITE_OK;
-    u.ch.aRes[0] = 1;
+    u.ci.aRes[0] = 1;
   }
-  for(u.ch.i=0, u.ch.pMem = &aMem[pOp->p3]; u.ch.i<3; u.ch.i++, u.ch.pMem++){
-    sqlite3VdbeMemSetInt64(u.ch.pMem, (i64)u.ch.aRes[u.ch.i]);
+  for(u.ci.i=0, u.ci.pMem = &aMem[pOp->p3]; u.ci.i<3; u.ci.i++, u.ci.pMem++){
+    sqlite3VdbeMemSetInt64(u.ci.pMem, (i64)u.ci.aRes[u.ci.i]);
   }
   break;
 };  
@@ -69064,91 +69576,93 @@ case OP_Checkpoint: {
 ** Write a string containing the final journal-mode to register P2.
 */
 case OP_JournalMode: {    /* out2-prerelease */
-#if 0  /* local variables moved into u.ci */
+#if 0  /* local variables moved into u.cj */
   Btree *pBt;                     /* Btree to change journal mode of */
   Pager *pPager;                  /* Pager associated with pBt */
   int eNew;                       /* New journal mode */
   int eOld;                       /* The old journal mode */
+#ifndef SQLITE_OMIT_WAL
   const char *zFilename;          /* Name of database file for pPager */
-#endif /* local variables moved into u.ci */
+#endif
+#endif /* local variables moved into u.cj */
 
-  u.ci.eNew = pOp->p3;
-  assert( u.ci.eNew==PAGER_JOURNALMODE_DELETE
-       || u.ci.eNew==PAGER_JOURNALMODE_TRUNCATE
-       || u.ci.eNew==PAGER_JOURNALMODE_PERSIST
-       || u.ci.eNew==PAGER_JOURNALMODE_OFF
-       || u.ci.eNew==PAGER_JOURNALMODE_MEMORY
-       || u.ci.eNew==PAGER_JOURNALMODE_WAL
-       || u.ci.eNew==PAGER_JOURNALMODE_QUERY
+  u.cj.eNew = pOp->p3;
+  assert( u.cj.eNew==PAGER_JOURNALMODE_DELETE
+       || u.cj.eNew==PAGER_JOURNALMODE_TRUNCATE
+       || u.cj.eNew==PAGER_JOURNALMODE_PERSIST
+       || u.cj.eNew==PAGER_JOURNALMODE_OFF
+       || u.cj.eNew==PAGER_JOURNALMODE_MEMORY
+       || u.cj.eNew==PAGER_JOURNALMODE_WAL
+       || u.cj.eNew==PAGER_JOURNALMODE_QUERY
   );
   assert( pOp->p1>=0 && pOp->p1<db->nDb );
 
-  u.ci.pBt = db->aDb[pOp->p1].pBt;
-  u.ci.pPager = sqlite3BtreePager(u.ci.pBt);
-  u.ci.eOld = sqlite3PagerGetJournalMode(u.ci.pPager);
-  if( u.ci.eNew==PAGER_JOURNALMODE_QUERY ) u.ci.eNew = u.ci.eOld;
-  if( !sqlite3PagerOkToChangeJournalMode(u.ci.pPager) ) u.ci.eNew = u.ci.eOld;
+  u.cj.pBt = db->aDb[pOp->p1].pBt;
+  u.cj.pPager = sqlite3BtreePager(u.cj.pBt);
+  u.cj.eOld = sqlite3PagerGetJournalMode(u.cj.pPager);
+  if( u.cj.eNew==PAGER_JOURNALMODE_QUERY ) u.cj.eNew = u.cj.eOld;
+  if( !sqlite3PagerOkToChangeJournalMode(u.cj.pPager) ) u.cj.eNew = u.cj.eOld;
 
 #ifndef SQLITE_OMIT_WAL
-  u.ci.zFilename = sqlite3PagerFilename(u.ci.pPager, 1);
+  u.cj.zFilename = sqlite3PagerFilename(u.cj.pPager, 1);
 
   /* Do not allow a transition to journal_mode=WAL for a database
   ** in temporary storage or if the VFS does not support shared memory
   */
-  if( u.ci.eNew==PAGER_JOURNALMODE_WAL
-   && (sqlite3Strlen30(u.ci.zFilename)==0           /* Temp file */
-       || !sqlite3PagerWalSupported(u.ci.pPager))   /* No shared-memory support */
+  if( u.cj.eNew==PAGER_JOURNALMODE_WAL
+   && (sqlite3Strlen30(u.cj.zFilename)==0           /* Temp file */
+       || !sqlite3PagerWalSupported(u.cj.pPager))   /* No shared-memory support */
   ){
-    u.ci.eNew = u.ci.eOld;
+    u.cj.eNew = u.cj.eOld;
   }
 
-  if( (u.ci.eNew!=u.ci.eOld)
-   && (u.ci.eOld==PAGER_JOURNALMODE_WAL || u.ci.eNew==PAGER_JOURNALMODE_WAL)
+  if( (u.cj.eNew!=u.cj.eOld)
+   && (u.cj.eOld==PAGER_JOURNALMODE_WAL || u.cj.eNew==PAGER_JOURNALMODE_WAL)
   ){
     if( !db->autoCommit || db->activeVdbeCnt>1 ){
       rc = SQLITE_ERROR;
       sqlite3SetString(&p->zErrMsg, db,
           "cannot change %s wal mode from within a transaction",
-          (u.ci.eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
+          (u.cj.eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
       );
       break;
     }else{
 
-      if( u.ci.eOld==PAGER_JOURNALMODE_WAL ){
+      if( u.cj.eOld==PAGER_JOURNALMODE_WAL ){
         /* If leaving WAL mode, close the log file. If successful, the call
         ** to PagerCloseWal() checkpoints and deletes the write-ahead-log
         ** file. An EXCLUSIVE lock may still be held on the database file
         ** after a successful return.
         */
-        rc = sqlite3PagerCloseWal(u.ci.pPager);
+        rc = sqlite3PagerCloseWal(u.cj.pPager);
         if( rc==SQLITE_OK ){
-          sqlite3PagerSetJournalMode(u.ci.pPager, u.ci.eNew);
+          sqlite3PagerSetJournalMode(u.cj.pPager, u.cj.eNew);
         }
-      }else if( u.ci.eOld==PAGER_JOURNALMODE_MEMORY ){
+      }else if( u.cj.eOld==PAGER_JOURNALMODE_MEMORY ){
         /* Cannot transition directly from MEMORY to WAL.  Use mode OFF
         ** as an intermediate */
-        sqlite3PagerSetJournalMode(u.ci.pPager, PAGER_JOURNALMODE_OFF);
+        sqlite3PagerSetJournalMode(u.cj.pPager, PAGER_JOURNALMODE_OFF);
       }
 
       /* Open a transaction on the database file. Regardless of the journal
       ** mode, this transaction always uses a rollback journal.
       */
-      assert( sqlite3BtreeIsInTrans(u.ci.pBt)==0 );
+      assert( sqlite3BtreeIsInTrans(u.cj.pBt)==0 );
       if( rc==SQLITE_OK ){
-        rc = sqlite3BtreeSetVersion(u.ci.pBt, (u.ci.eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
+        rc = sqlite3BtreeSetVersion(u.cj.pBt, (u.cj.eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
       }
     }
   }
 #endif /* ifndef SQLITE_OMIT_WAL */
 
   if( rc ){
-    u.ci.eNew = u.ci.eOld;
+    u.cj.eNew = u.cj.eOld;
   }
-  u.ci.eNew = sqlite3PagerSetJournalMode(u.ci.pPager, u.ci.eNew);
+  u.cj.eNew = sqlite3PagerSetJournalMode(u.cj.pPager, u.cj.eNew);
 
   pOut = &aMem[pOp->p2];
   pOut->flags = MEM_Str|MEM_Static|MEM_Term;
-  pOut->z = (char *)sqlite3JournalModename(u.ci.eNew);
+  pOut->z = (char *)sqlite3JournalModename(u.cj.eNew);
   pOut->n = sqlite3Strlen30(pOut->z);
   pOut->enc = SQLITE_UTF8;
   sqlite3VdbeChangeEncoding(pOut, encoding);
@@ -69177,14 +69691,14 @@ case OP_Vacuum: {
 ** P2. Otherwise, fall through to the next instruction.
 */
 case OP_IncrVacuum: {        /* jump */
-#if 0  /* local variables moved into u.cj */
+#if 0  /* local variables moved into u.ck */
   Btree *pBt;
-#endif /* local variables moved into u.cj */
+#endif /* local variables moved into u.ck */
 
   assert( pOp->p1>=0 && pOp->p1<db->nDb );
   assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
-  u.cj.pBt = db->aDb[pOp->p1].pBt;
-  rc = sqlite3BtreeIncrVacuum(u.cj.pBt);
+  u.ck.pBt = db->aDb[pOp->p1].pBt;
+  rc = sqlite3BtreeIncrVacuum(u.ck.pBt);
   if( rc==SQLITE_DONE ){
     pc = pOp->p2 - 1;
     rc = SQLITE_OK;
@@ -69254,12 +69768,12 @@ case OP_TableLock: {
 ** code will be set to SQLITE_LOCKED.
 */
 case OP_VBegin: {
-#if 0  /* local variables moved into u.ck */
+#if 0  /* local variables moved into u.cl */
   VTable *pVTab;
-#endif /* local variables moved into u.ck */
-  u.ck.pVTab = pOp->p4.pVtab;
-  rc = sqlite3VtabBegin(db, u.ck.pVTab);
-  if( u.ck.pVTab ) importVtabErrMsg(p, u.ck.pVTab->pVtab);
+#endif /* local variables moved into u.cl */
+  u.cl.pVTab = pOp->p4.pVtab;
+  rc = sqlite3VtabBegin(db, u.cl.pVTab);
+  if( u.cl.pVTab ) importVtabErrMsg(p, u.cl.pVTab->pVtab);
   break;
 }
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -69298,32 +69812,32 @@ case OP_VDestroy: {
 ** table and stores that cursor in P1.
 */
 case OP_VOpen: {
-#if 0  /* local variables moved into u.cl */
+#if 0  /* local variables moved into u.cm */
   VdbeCursor *pCur;
   sqlite3_vtab_cursor *pVtabCursor;
   sqlite3_vtab *pVtab;
   sqlite3_module *pModule;
-#endif /* local variables moved into u.cl */
+#endif /* local variables moved into u.cm */
 
-  u.cl.pCur = 0;
-  u.cl.pVtabCursor = 0;
-  u.cl.pVtab = pOp->p4.pVtab->pVtab;
-  u.cl.pModule = (sqlite3_module *)u.cl.pVtab->pModule;
-  assert(u.cl.pVtab && u.cl.pModule);
-  rc = u.cl.pModule->xOpen(u.cl.pVtab, &u.cl.pVtabCursor);
-  importVtabErrMsg(p, u.cl.pVtab);
+  u.cm.pCur = 0;
+  u.cm.pVtabCursor = 0;
+  u.cm.pVtab = pOp->p4.pVtab->pVtab;
+  u.cm.pModule = (sqlite3_module *)u.cm.pVtab->pModule;
+  assert(u.cm.pVtab && u.cm.pModule);
+  rc = u.cm.pModule->xOpen(u.cm.pVtab, &u.cm.pVtabCursor);
+  importVtabErrMsg(p, u.cm.pVtab);
   if( SQLITE_OK==rc ){
     /* Initialize sqlite3_vtab_cursor base class */
-    u.cl.pVtabCursor->pVtab = u.cl.pVtab;
+    u.cm.pVtabCursor->pVtab = u.cm.pVtab;
 
     /* Initialise vdbe cursor object */
-    u.cl.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
-    if( u.cl.pCur ){
-      u.cl.pCur->pVtabCursor = u.cl.pVtabCursor;
-      u.cl.pCur->pModule = u.cl.pVtabCursor->pVtab->pModule;
+    u.cm.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
+    if( u.cm.pCur ){
+      u.cm.pCur->pVtabCursor = u.cm.pVtabCursor;
+      u.cm.pCur->pModule = u.cm.pVtabCursor->pVtab->pModule;
     }else{
       db->mallocFailed = 1;
-      u.cl.pModule->xClose(u.cl.pVtabCursor);
+      u.cm.pModule->xClose(u.cm.pVtabCursor);
     }
   }
   break;
@@ -69350,7 +69864,7 @@ case OP_VOpen: {
 ** A jump is made to P2 if the result set after filtering would be empty.
 */
 case OP_VFilter: {   /* jump */
-#if 0  /* local variables moved into u.cm */
+#if 0  /* local variables moved into u.cn */
   int nArg;
   int iQuery;
   const sqlite3_module *pModule;
@@ -69362,45 +69876,45 @@ case OP_VFilter: {   /* jump */
   int res;
   int i;
   Mem **apArg;
-#endif /* local variables moved into u.cm */
+#endif /* local variables moved into u.cn */
 
-  u.cm.pQuery = &aMem[pOp->p3];
-  u.cm.pArgc = &u.cm.pQuery[1];
-  u.cm.pCur = p->apCsr[pOp->p1];
-  assert( memIsValid(u.cm.pQuery) );
-  REGISTER_TRACE(pOp->p3, u.cm.pQuery);
-  assert( u.cm.pCur->pVtabCursor );
-  u.cm.pVtabCursor = u.cm.pCur->pVtabCursor;
-  u.cm.pVtab = u.cm.pVtabCursor->pVtab;
-  u.cm.pModule = u.cm.pVtab->pModule;
+  u.cn.pQuery = &aMem[pOp->p3];
+  u.cn.pArgc = &u.cn.pQuery[1];
+  u.cn.pCur = p->apCsr[pOp->p1];
+  assert( memIsValid(u.cn.pQuery) );
+  REGISTER_TRACE(pOp->p3, u.cn.pQuery);
+  assert( u.cn.pCur->pVtabCursor );
+  u.cn.pVtabCursor = u.cn.pCur->pVtabCursor;
+  u.cn.pVtab = u.cn.pVtabCursor->pVtab;
+  u.cn.pModule = u.cn.pVtab->pModule;
 
   /* Grab the index number and argc parameters */
-  assert( (u.cm.pQuery->flags&MEM_Int)!=0 && u.cm.pArgc->flags==MEM_Int );
-  u.cm.nArg = (int)u.cm.pArgc->u.i;
-  u.cm.iQuery = (int)u.cm.pQuery->u.i;
+  assert( (u.cn.pQuery->flags&MEM_Int)!=0 && u.cn.pArgc->flags==MEM_Int );
+  u.cn.nArg = (int)u.cn.pArgc->u.i;
+  u.cn.iQuery = (int)u.cn.pQuery->u.i;
 
   /* Invoke the xFilter method */
   {
-    u.cm.res = 0;
-    u.cm.apArg = p->apArg;
-    for(u.cm.i = 0; u.cm.i<u.cm.nArg; u.cm.i++){
-      u.cm.apArg[u.cm.i] = &u.cm.pArgc[u.cm.i+1];
-      sqlite3VdbeMemStoreType(u.cm.apArg[u.cm.i]);
+    u.cn.res = 0;
+    u.cn.apArg = p->apArg;
+    for(u.cn.i = 0; u.cn.i<u.cn.nArg; u.cn.i++){
+      u.cn.apArg[u.cn.i] = &u.cn.pArgc[u.cn.i+1];
+      sqlite3VdbeMemStoreType(u.cn.apArg[u.cn.i]);
     }
 
     p->inVtabMethod = 1;
-    rc = u.cm.pModule->xFilter(u.cm.pVtabCursor, u.cm.iQuery, pOp->p4.z, u.cm.nArg, u.cm.apArg);
+    rc = u.cn.pModule->xFilter(u.cn.pVtabCursor, u.cn.iQuery, pOp->p4.z, u.cn.nArg, u.cn.apArg);
     p->inVtabMethod = 0;
-    importVtabErrMsg(p, u.cm.pVtab);
+    importVtabErrMsg(p, u.cn.pVtab);
     if( rc==SQLITE_OK ){
-      u.cm.res = u.cm.pModule->xEof(u.cm.pVtabCursor);
+      u.cn.res = u.cn.pModule->xEof(u.cn.pVtabCursor);
     }
 
-    if( u.cm.res ){
+    if( u.cn.res ){
       pc = pOp->p2 - 1;
     }
   }
-  u.cm.pCur->nullRow = 0;
+  u.cn.pCur->nullRow = 0;
 
   break;
 }
@@ -69414,51 +69928,51 @@ case OP_VFilter: {   /* jump */
 ** P1 cursor is pointing to into register P3.
 */
 case OP_VColumn: {
-#if 0  /* local variables moved into u.cn */
+#if 0  /* local variables moved into u.co */
   sqlite3_vtab *pVtab;
   const sqlite3_module *pModule;
   Mem *pDest;
   sqlite3_context sContext;
-#endif /* local variables moved into u.cn */
+#endif /* local variables moved into u.co */
 
   VdbeCursor *pCur = p->apCsr[pOp->p1];
   assert( pCur->pVtabCursor );
   assert( pOp->p3>0 && pOp->p3<=p->nMem );
-  u.cn.pDest = &aMem[pOp->p3];
-  memAboutToChange(p, u.cn.pDest);
+  u.co.pDest = &aMem[pOp->p3];
+  memAboutToChange(p, u.co.pDest);
   if( pCur->nullRow ){
-    sqlite3VdbeMemSetNull(u.cn.pDest);
+    sqlite3VdbeMemSetNull(u.co.pDest);
     break;
   }
-  u.cn.pVtab = pCur->pVtabCursor->pVtab;
-  u.cn.pModule = u.cn.pVtab->pModule;
-  assert( u.cn.pModule->xColumn );
-  memset(&u.cn.sContext, 0, sizeof(u.cn.sContext));
+  u.co.pVtab = pCur->pVtabCursor->pVtab;
+  u.co.pModule = u.co.pVtab->pModule;
+  assert( u.co.pModule->xColumn );
+  memset(&u.co.sContext, 0, sizeof(u.co.sContext));
 
   /* The output cell may already have a buffer allocated. Move
-  ** the current contents to u.cn.sContext.s so in case the user-function
+  ** the current contents to u.co.sContext.s so in case the user-function
   ** can use the already allocated buffer instead of allocating a
   ** new one.
   */
-  sqlite3VdbeMemMove(&u.cn.sContext.s, u.cn.pDest);
-  MemSetTypeFlag(&u.cn.sContext.s, MEM_Null);
+  sqlite3VdbeMemMove(&u.co.sContext.s, u.co.pDest);
+  MemSetTypeFlag(&u.co.sContext.s, MEM_Null);
 
-  rc = u.cn.pModule->xColumn(pCur->pVtabCursor, &u.cn.sContext, pOp->p2);
-  importVtabErrMsg(p, u.cn.pVtab);
-  if( u.cn.sContext.isError ){
-    rc = u.cn.sContext.isError;
+  rc = u.co.pModule->xColumn(pCur->pVtabCursor, &u.co.sContext, pOp->p2);
+  importVtabErrMsg(p, u.co.pVtab);
+  if( u.co.sContext.isError ){
+    rc = u.co.sContext.isError;
   }
 
   /* Copy the result of the function to the P3 register. We
   ** do this regardless of whether or not an error occurred to ensure any
-  ** dynamic allocation in u.cn.sContext.s (a Mem struct) is  released.
+  ** dynamic allocation in u.co.sContext.s (a Mem struct) is  released.
   */
-  sqlite3VdbeChangeEncoding(&u.cn.sContext.s, encoding);
-  sqlite3VdbeMemMove(u.cn.pDest, &u.cn.sContext.s);
-  REGISTER_TRACE(pOp->p3, u.cn.pDest);
-  UPDATE_MAX_BLOBSIZE(u.cn.pDest);
+  sqlite3VdbeChangeEncoding(&u.co.sContext.s, encoding);
+  sqlite3VdbeMemMove(u.co.pDest, &u.co.sContext.s);
+  REGISTER_TRACE(pOp->p3, u.co.pDest);
+  UPDATE_MAX_BLOBSIZE(u.co.pDest);
 
-  if( sqlite3VdbeMemTooBig(u.cn.pDest) ){
+  if( sqlite3VdbeMemTooBig(u.co.pDest) ){
     goto too_big;
   }
   break;
@@ -69473,22 +69987,22 @@ case OP_VColumn: {
 ** the end of its result set, then fall through to the next instruction.
 */
 case OP_VNext: {   /* jump */
-#if 0  /* local variables moved into u.co */
+#if 0  /* local variables moved into u.cp */
   sqlite3_vtab *pVtab;
   const sqlite3_module *pModule;
   int res;
   VdbeCursor *pCur;
-#endif /* local variables moved into u.co */
+#endif /* local variables moved into u.cp */
 
-  u.co.res = 0;
-  u.co.pCur = p->apCsr[pOp->p1];
-  assert( u.co.pCur->pVtabCursor );
-  if( u.co.pCur->nullRow ){
+  u.cp.res = 0;
+  u.cp.pCur = p->apCsr[pOp->p1];
+  assert( u.cp.pCur->pVtabCursor );
+  if( u.cp.pCur->nullRow ){
     break;
   }
-  u.co.pVtab = u.co.pCur->pVtabCursor->pVtab;
-  u.co.pModule = u.co.pVtab->pModule;
-  assert( u.co.pModule->xNext );
+  u.cp.pVtab = u.cp.pCur->pVtabCursor->pVtab;
+  u.cp.pModule = u.cp.pVtab->pModule;
+  assert( u.cp.pModule->xNext );
 
   /* Invoke the xNext() method of the module. There is no way for the
   ** underlying implementation to return an error if one occurs during
@@ -69497,14 +70011,14 @@ case OP_VNext: {   /* jump */
   ** some other method is next invoked on the save virtual table cursor.
   */
   p->inVtabMethod = 1;
-  rc = u.co.pModule->xNext(u.co.pCur->pVtabCursor);
+  rc = u.cp.pModule->xNext(u.cp.pCur->pVtabCursor);
   p->inVtabMethod = 0;
-  importVtabErrMsg(p, u.co.pVtab);
+  importVtabErrMsg(p, u.cp.pVtab);
   if( rc==SQLITE_OK ){
-    u.co.res = u.co.pModule->xEof(u.co.pCur->pVtabCursor);
+    u.cp.res = u.cp.pModule->xEof(u.cp.pCur->pVtabCursor);
   }
 
-  if( !u.co.res ){
+  if( !u.cp.res ){
     /* If there is data, jump to P2 */
     pc = pOp->p2 - 1;
   }
@@ -69520,24 +70034,24 @@ case OP_VNext: {   /* jump */
 ** in register P1 is passed as the zName argument to the xRename method.
 */
 case OP_VRename: {
-#if 0  /* local variables moved into u.cp */
+#if 0  /* local variables moved into u.cq */
   sqlite3_vtab *pVtab;
   Mem *pName;
-#endif /* local variables moved into u.cp */
+#endif /* local variables moved into u.cq */
 
-  u.cp.pVtab = pOp->p4.pVtab->pVtab;
-  u.cp.pName = &aMem[pOp->p1];
-  assert( u.cp.pVtab->pModule->xRename );
-  assert( memIsValid(u.cp.pName) );
-  REGISTER_TRACE(pOp->p1, u.cp.pName);
-  assert( u.cp.pName->flags & MEM_Str );
-  testcase( u.cp.pName->enc==SQLITE_UTF8 );
-  testcase( u.cp.pName->enc==SQLITE_UTF16BE );
-  testcase( u.cp.pName->enc==SQLITE_UTF16LE );
-  rc = sqlite3VdbeChangeEncoding(u.cp.pName, SQLITE_UTF8);
+  u.cq.pVtab = pOp->p4.pVtab->pVtab;
+  u.cq.pName = &aMem[pOp->p1];
+  assert( u.cq.pVtab->pModule->xRename );
+  assert( memIsValid(u.cq.pName) );
+  REGISTER_TRACE(pOp->p1, u.cq.pName);
+  assert( u.cq.pName->flags & MEM_Str );
+  testcase( u.cq.pName->enc==SQLITE_UTF8 );
+  testcase( u.cq.pName->enc==SQLITE_UTF16BE );
+  testcase( u.cq.pName->enc==SQLITE_UTF16LE );
+  rc = sqlite3VdbeChangeEncoding(u.cq.pName, SQLITE_UTF8);
   if( rc==SQLITE_OK ){
-    rc = u.cp.pVtab->pModule->xRename(u.cp.pVtab, u.cp.pName->z);
-    importVtabErrMsg(p, u.cp.pVtab);
+    rc = u.cq.pVtab->pModule->xRename(u.cq.pVtab, u.cq.pName->z);
+    importVtabErrMsg(p, u.cq.pVtab);
     p->expired = 0;
   }
   break;
@@ -69569,7 +70083,7 @@ case OP_VRename: {
 ** is set to the value of the rowid for the row just inserted.
 */
 case OP_VUpdate: {
-#if 0  /* local variables moved into u.cq */
+#if 0  /* local variables moved into u.cr */
   sqlite3_vtab *pVtab;
   sqlite3_module *pModule;
   int nArg;
@@ -69577,33 +70091,33 @@ case OP_VUpdate: {
   sqlite_int64 rowid;
   Mem **apArg;
   Mem *pX;
-#endif /* local variables moved into u.cq */
+#endif /* local variables moved into u.cr */
 
   assert( pOp->p2==1        || pOp->p5==OE_Fail   || pOp->p5==OE_Rollback
        || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
   );
-  u.cq.pVtab = pOp->p4.pVtab->pVtab;
-  u.cq.pModule = (sqlite3_module *)u.cq.pVtab->pModule;
-  u.cq.nArg = pOp->p2;
+  u.cr.pVtab = pOp->p4.pVtab->pVtab;
+  u.cr.pModule = (sqlite3_module *)u.cr.pVtab->pModule;
+  u.cr.nArg = pOp->p2;
   assert( pOp->p4type==P4_VTAB );
-  if( ALWAYS(u.cq.pModule->xUpdate) ){
+  if( ALWAYS(u.cr.pModule->xUpdate) ){
     u8 vtabOnConflict = db->vtabOnConflict;
-    u.cq.apArg = p->apArg;
-    u.cq.pX = &aMem[pOp->p3];
-    for(u.cq.i=0; u.cq.i<u.cq.nArg; u.cq.i++){
-      assert( memIsValid(u.cq.pX) );
-      memAboutToChange(p, u.cq.pX);
-      sqlite3VdbeMemStoreType(u.cq.pX);
-      u.cq.apArg[u.cq.i] = u.cq.pX;
-      u.cq.pX++;
+    u.cr.apArg = p->apArg;
+    u.cr.pX = &aMem[pOp->p3];
+    for(u.cr.i=0; u.cr.i<u.cr.nArg; u.cr.i++){
+      assert( memIsValid(u.cr.pX) );
+      memAboutToChange(p, u.cr.pX);
+      sqlite3VdbeMemStoreType(u.cr.pX);
+      u.cr.apArg[u.cr.i] = u.cr.pX;
+      u.cr.pX++;
     }
     db->vtabOnConflict = pOp->p5;
-    rc = u.cq.pModule->xUpdate(u.cq.pVtab, u.cq.nArg, u.cq.apArg, &u.cq.rowid);
+    rc = u.cr.pModule->xUpdate(u.cr.pVtab, u.cr.nArg, u.cr.apArg, &u.cr.rowid);
     db->vtabOnConflict = vtabOnConflict;
-    importVtabErrMsg(p, u.cq.pVtab);
+    importVtabErrMsg(p, u.cr.pVtab);
     if( rc==SQLITE_OK && pOp->p1 ){
-      assert( u.cq.nArg>1 && u.cq.apArg[0] && (u.cq.apArg[0]->flags&MEM_Null) );
-      db->lastRowid = lastRowid = u.cq.rowid;
+      assert( u.cr.nArg>1 && u.cr.apArg[0] && (u.cr.apArg[0]->flags&MEM_Null) );
+      db->lastRowid = lastRowid = u.cr.rowid;
     }
     if( rc==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
       if( pOp->p5==OE_Ignore ){
@@ -69663,21 +70177,24 @@ case OP_MaxPgcnt: {            /* out2-prerelease */
 ** the UTF-8 string contained in P4 is emitted on the trace callback.
 */
 case OP_Trace: {
-#if 0  /* local variables moved into u.cr */
+#if 0  /* local variables moved into u.cs */
   char *zTrace;
   char *z;
-#endif /* local variables moved into u.cr */
+#endif /* local variables moved into u.cs */
 
-  if( db->xTrace && (u.cr.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 ){
-    u.cr.z = sqlite3VdbeExpandSql(p, u.cr.zTrace);
-    db->xTrace(db->pTraceArg, u.cr.z);
-    sqlite3DbFree(db, u.cr.z);
+  if( db->xTrace
+   && !p->doingRerun
+   && (u.cs.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
+  ){
+    u.cs.z = sqlite3VdbeExpandSql(p, u.cs.zTrace);
+    db->xTrace(db->pTraceArg, u.cs.z);
+    sqlite3DbFree(db, u.cs.z);
   }
 #ifdef SQLITE_DEBUG
   if( (db->flags & SQLITE_SqlTrace)!=0
-   && (u.cr.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
+   && (u.cs.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
   ){
-    sqlite3DebugPrintf("SQL-trace: %s\n", u.cr.zTrace);
+    sqlite3DebugPrintf("SQL-trace: %s\n", u.cs.zTrace);
   }
 #endif /* SQLITE_DEBUG */
   break;
@@ -70472,8 +70989,11 @@ static int vdbeSorterIterRead(
     int rc;                       /* sqlite3OsRead() return code */
 
     /* Determine how many bytes of data to read. */
-    nRead = (int)(p->iEof - p->iReadOff);
-    if( nRead>p->nBuffer ) nRead = p->nBuffer;
+    if( (p->iEof - p->iReadOff) > (i64)p->nBuffer ){
+      nRead = p->nBuffer;
+    }else{
+      nRead = (int)(p->iEof - p->iReadOff);
+    }
     assert( nRead>0 );
 
     /* Read data from the file. Return early if an error occurs. */
@@ -71545,6 +72065,16 @@ SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *p){
   return createFile((JournalFile *)p);
 }
 
+/*
+** The file-handle passed as the only argument is guaranteed to be an open
+** file. It may or may not be of class JournalFile. If the file is a
+** JournalFile, and the underlying file on disk has not yet been opened,
+** return 0. Otherwise, return 1.
+*/
+SQLITE_PRIVATE int sqlite3JournalExists(sqlite3_file *p){
+  return (p->pMethods!=&JournalFileMethods || ((JournalFile *)p)->pReal!=0);
+}
+
 /* 
 ** Return the number of bytes required to store a JournalFile that uses vfs
 ** pVfs to create the underlying on-disk files.
@@ -72030,6 +72560,15 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){
 ** from the result in the result-set.  We might fix this someday.  Or
 ** then again, we might not...
 **
+** If the reference is followed by a COLLATE operator, then make sure
+** the COLLATE operator is preserved.  For example:
+**
+**     SELECT a+b, c+d FROM t1 ORDER BY 1 COLLATE nocase;
+**
+** Should be transformed into:
+**
+**     SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase;
+**
 ** The nSubquery parameter specifies how many levels of subquery the
 ** alias is removed from the original expression.  The usually value is
 ** zero but it might be more if the alias is contained within a subquery
@@ -72053,8 +72592,9 @@ static void resolveAlias(
   assert( pOrig!=0 );
   assert( pOrig->flags & EP_Resolved );
   db = pParse->db;
+  pDup = sqlite3ExprDup(db, pOrig, 0);
+  if( pDup==0 ) return;
   if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){
-    pDup = sqlite3ExprDup(db, pOrig, 0);
     incrAggFunctionDepth(pDup, nSubquery);
     pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
     if( pDup==0 ) return;
@@ -72062,32 +72602,26 @@ static void resolveAlias(
       pEList->a[iCol].iAlias = (u16)(++pParse->nAlias);
     }
     pDup->iTable = pEList->a[iCol].iAlias;
-  }else if( ExprHasProperty(pOrig, EP_IntValue) || pOrig->u.zToken==0 ){
-    pDup = sqlite3ExprDup(db, pOrig, 0);
-    if( pDup==0 ) return;
-  }else{
-    char *zToken = pOrig->u.zToken;
-    assert( zToken!=0 );
-    pOrig->u.zToken = 0;
-    pDup = sqlite3ExprDup(db, pOrig, 0);
-    pOrig->u.zToken = zToken;
-    if( pDup==0 ) return;
-    assert( (pDup->flags & (EP_Reduced|EP_TokenOnly))==0 );
-    pDup->flags2 |= EP2_MallocedToken;
-    pDup->u.zToken = sqlite3DbStrDup(db, zToken);
   }
-  if( pExpr->flags & EP_ExpCollate ){
-    pDup->pColl = pExpr->pColl;
-    pDup->flags |= EP_ExpCollate;
+  if( pExpr->op==TK_COLLATE ){
+    pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
   }
 
   /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This 
   ** prevents ExprDelete() from deleting the Expr structure itself,
   ** allowing it to be repopulated by the memcpy() on the following line.
+  ** The pExpr->u.zToken might point into memory that will be freed by the
+  ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to
+  ** make a copy of the token before doing the sqlite3DbFree().
   */
   ExprSetProperty(pExpr, EP_Static);
   sqlite3ExprDelete(db, pExpr);
   memcpy(pExpr, pDup, sizeof(*pExpr));
+  if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
+    assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
+    pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
+    pExpr->flags2 |= EP2_MallocedToken;
+  }
   sqlite3DbFree(db, pDup);
 }
 
@@ -72157,7 +72691,7 @@ static int lookupName(
 
   assert( pNC );     /* the name context cannot be NULL. */
   assert( zCol );    /* The Z in X.Y.Z cannot be NULL */
-  assert( ~ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
+  assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
 
   /* Initialize the node to no-match */
   pExpr->iTable = -1;
@@ -72774,7 +73308,7 @@ static int resolveCompoundOrderBy(
       int iCol = -1;
       Expr *pE, *pDup;
       if( pItem->done ) continue;
-      pE = pItem->pExpr;
+      pE = sqlite3ExprSkipCollate(pItem->pExpr);
       if( sqlite3ExprIsInteger(pE, &iCol) ){
         if( iCol<=0 || iCol>pEList->nExpr ){
           resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
@@ -72792,14 +73326,20 @@ static int resolveCompoundOrderBy(
         }
       }
       if( iCol>0 ){
-        CollSeq *pColl = pE->pColl;
-        int flags = pE->flags & EP_ExpCollate;
+        /* Convert the ORDER BY term into an integer column number iCol,
+        ** taking care to preserve the COLLATE clause if it exists */
+        Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
+        if( pNew==0 ) return 1;
+        pNew->flags |= EP_IntValue;
+        pNew->u.iValue = iCol;
+        if( pItem->pExpr==pE ){
+          pItem->pExpr = pNew;
+        }else{
+          assert( pItem->pExpr->op==TK_COLLATE );
+          assert( pItem->pExpr->pLeft==pE );
+          pItem->pExpr->pLeft = pNew;
+        }
         sqlite3ExprDelete(db, pE);
-        pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0);
-        if( pE==0 ) return 1;
-        pE->pColl = pColl;
-        pE->flags |= EP_IntValue | flags;
-        pE->u.iValue = iCol;
         pItem->iOrderByCol = (u16)iCol;
         pItem->done = 1;
       }else{
@@ -72904,11 +73444,11 @@ static int resolveOrderGroupBy(
       pItem->iOrderByCol = (u16)iCol;
       continue;
     }
-    if( sqlite3ExprIsInteger(pE, &iCol) ){
+    if( sqlite3ExprIsInteger(sqlite3ExprSkipCollate(pE), &iCol) ){
       /* The ORDER BY term is an integer constant.  Again, set the column
       ** number so that sqlite3ResolveOrderGroupBy() will convert the
       ** order-by term to a copy of the result-set expression */
-      if( iCol<1 ){
+      if( iCol<1 || iCol>0xffff ){
         resolveOutOfRangeError(pParse, zType, i+1, nResult);
         return 1;
       }
@@ -73262,7 +73802,9 @@ SQLITE_PRIVATE void sqlite3ResolveSelectNames(
 ** SELECT * FROM t1 WHERE (select a from t1);
 */
 SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
-  int op = pExpr->op;
+  int op;
+  pExpr = sqlite3ExprSkipCollate(pExpr);
+  op = pExpr->op;
   if( op==TK_SELECT ){
     assert( pExpr->flags&EP_xIsSelect );
     return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
@@ -73287,66 +73829,94 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
 }
 
 /*
-** Set the explicit collating sequence for an expression to the
-** collating sequence supplied in the second argument.
+** Set the collating sequence for expression pExpr to be the collating
+** sequence named by pToken.   Return a pointer to a new Expr node that
+** implements the COLLATE operator.
+**
+** If a memory allocation error occurs, that fact is recorded in pParse->db
+** and the pExpr parameter is returned unchanged.
 */
-SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr *pExpr, CollSeq *pColl){
-  if( pExpr && pColl ){
-    pExpr->pColl = pColl;
-    pExpr->flags |= EP_ExpCollate;
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName){
+  if( pCollName->n>0 ){
+    Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1);
+    if( pNew ){
+      pNew->pLeft = pExpr;
+      pNew->flags |= EP_Collate;
+      pExpr = pNew;
+    }
   }
   return pExpr;
 }
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
+  Token s;
+  assert( zC!=0 );
+  s.z = zC;
+  s.n = sqlite3Strlen30(s.z);
+  return sqlite3ExprAddCollateToken(pParse, pExpr, &s);
+}
 
 /*
-** Set the collating sequence for expression pExpr to be the collating
-** sequence named by pToken.   Return a pointer to the revised expression.
-** The collating sequence is marked as "explicit" using the EP_ExpCollate
-** flag.  An explicit collating sequence will override implicit
-** collating sequences.
+** Skip over any TK_COLLATE and/or TK_AS operators at the root of
+** an expression.
 */
-SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr *pExpr, Token *pCollName){
-  char *zColl = 0;            /* Dequoted name of collation sequence */
-  CollSeq *pColl;
-  sqlite3 *db = pParse->db;
-  zColl = sqlite3NameFromToken(db, pCollName);
-  pColl = sqlite3LocateCollSeq(pParse, zColl);
-  sqlite3ExprSetColl(pExpr, pColl);
-  sqlite3DbFree(db, zColl);
+SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){
+  while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){
+    pExpr = pExpr->pLeft;
+  }
   return pExpr;
 }
 
 /*
-** Return the default collation sequence for the expression pExpr. If
-** there is no default collation type, return 0.
+** Return the collation sequence for the expression pExpr. If
+** there is no defined collating sequence, return NULL.
+**
+** The collating sequence might be determined by a COLLATE operator
+** or by the presence of a column with a defined collating sequence.
+** COLLATE operators take first precedence.  Left operands take
+** precedence over right operands.
 */
 SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
+  sqlite3 *db = pParse->db;
   CollSeq *pColl = 0;
   Expr *p = pExpr;
   while( p ){
-    int op;
-    pColl = p->pColl;
-    if( pColl ) break;
-    op = p->op;
-    if( p->pTab!=0 && (
-        op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER
-    )){
+    int op = p->op;
+    if( op==TK_CAST || op==TK_UPLUS ){
+      p = p->pLeft;
+      continue;
+    }
+    assert( op!=TK_REGISTER || p->op2!=TK_COLLATE );
+    if( op==TK_COLLATE ){
+      if( db->init.busy ){
+        /* Do not report errors when parsing while the schema */
+        pColl = sqlite3FindCollSeq(db, ENC(db), p->u.zToken, 0);
+      }else{
+        pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
+      }
+      break;
+    }
+    if( p->pTab!=0
+     && (op==TK_AGG_COLUMN || op==TK_COLUMN
+          || op==TK_REGISTER || op==TK_TRIGGER)
+    ){
       /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
       ** a TK_COLUMN but was previously evaluated and cached in a register */
-      const char *zColl;
       int j = p->iColumn;
       if( j>=0 ){
-        sqlite3 *db = pParse->db;
-        zColl = p->pTab->aCol[j].zColl;
+        const char *zColl = p->pTab->aCol[j].zColl;
         pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
-        pExpr->pColl = pColl;
       }
       break;
     }
-    if( op!=TK_CAST && op!=TK_UPLUS ){
+    if( p->flags & EP_Collate ){
+      if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){
+        p = p->pLeft;
+      }else{
+        p = p->pRight;
+      }
+    }else{
       break;
     }
-    p = p->pLeft;
   }
   if( sqlite3CheckCollSeq(pParse, pColl) ){ 
     pColl = 0;
@@ -73450,12 +74020,10 @@ SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(
 ){
   CollSeq *pColl;
   assert( pLeft );
-  if( pLeft->flags & EP_ExpCollate ){
-    assert( pLeft->pColl );
-    pColl = pLeft->pColl;
-  }else if( pRight && pRight->flags & EP_ExpCollate ){
-    assert( pRight->pColl );
-    pColl = pRight->pColl;
+  if( pLeft->flags & EP_Collate ){
+    pColl = sqlite3ExprCollSeq(pParse, pLeft);
+  }else if( pRight && (pRight->flags & EP_Collate)!=0 ){
+    pColl = sqlite3ExprCollSeq(pParse, pRight);
   }else{
     pColl = sqlite3ExprCollSeq(pParse, pLeft);
     if( !pColl ){
@@ -73685,17 +74253,11 @@ SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(
   }else{
     if( pRight ){
       pRoot->pRight = pRight;
-      if( pRight->flags & EP_ExpCollate ){
-        pRoot->flags |= EP_ExpCollate;
-        pRoot->pColl = pRight->pColl;
-      }
+      pRoot->flags |= EP_Collate & pRight->flags;
     }
     if( pLeft ){
       pRoot->pLeft = pLeft;
-      if( pLeft->flags & EP_ExpCollate ){
-        pRoot->flags |= EP_ExpCollate;
-        pRoot->pColl = pLeft->pColl;
-      }
+      pRoot->flags |= EP_Collate & pLeft->flags;
     }
     exprSetHeight(pRoot);
   }
@@ -73953,7 +74515,7 @@ static int dupedExprStructSize(Expr *p, int flags){
     assert( !ExprHasProperty(p, EP_FromJoin) ); 
     assert( (p->flags2 & EP2_MallocedToken)==0 );
     assert( (p->flags2 & EP2_Irreducible)==0 );
-    if( p->pLeft || p->pRight || p->pColl || p->x.pList ){
+    if( p->pLeft || p->pRight || p->x.pList ){
       nSize = EXPR_REDUCEDSIZE | EP_Reduced;
     }else{
       nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
@@ -74161,6 +74723,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
     struct SrcList_item *pNewItem = &pNew->a[i];
     struct SrcList_item *pOldItem = &p->a[i];
     Table *pTab;
+    pNewItem->pSchema = pOldItem->pSchema;
     pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
     pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
     pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
@@ -74169,6 +74732,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
     pNewItem->addrFillSub = pOldItem->addrFillSub;
     pNewItem->regReturn = pOldItem->regReturn;
     pNewItem->isCorrelated = pOldItem->isCorrelated;
+    pNewItem->viaCoroutine = pOldItem->viaCoroutine;
     pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
     pNewItem->notIndexed = pOldItem->notIndexed;
     pNewItem->pIndex = pOldItem->pIndex;
@@ -74651,12 +75215,16 @@ SQLITE_PRIVATE int sqlite3CodeOnce(Parse *pParse){
 
 /*
 ** This function is used by the implementation of the IN (...) operator.
-** It's job is to find or create a b-tree structure that may be used
-** either to test for membership of the (...) set or to iterate through
-** its members, skipping duplicates.
+** The pX parameter is the expression on the RHS of the IN operator, which
+** might be either a list of expressions or a subquery.
+**
+** The job of this routine is to find or create a b-tree object that can
+** be used either to test for membership in the RHS set or to iterate through
+** all members of the RHS set, skipping duplicates.
+**
+** A cursor is opened on the b-tree object that the RHS of the IN operator
+** and pX->iTable is set to the index of that cursor.
 **
-** The index of the cursor opened on the b-tree (database table, database index 
-** or ephermal table) is stored in pX->iTable before this function returns.
 ** The returned value of this function indicates the b-tree type, as follows:
 **
 **   IN_INDEX_ROWID - The cursor was opened on a database table.
@@ -74664,11 +75232,16 @@ SQLITE_PRIVATE int sqlite3CodeOnce(Parse *pParse){
 **   IN_INDEX_EPH -   The cursor was opened on a specially created and
 **                    populated epheremal table.
 **
-** An existing b-tree may only be used if the SELECT is of the simple
-** form:
+** An existing b-tree might be used if the RHS expression pX is a simple
+** subquery such as:
 **
 **     SELECT <column> FROM <table>
 **
+** If the RHS of the IN operator is a list or a more complex subquery, then
+** an ephemeral table might need to be generated from the RHS and then
+** pX->iTable made to point to the ephermeral table instead of an
+** existing table.  
+**
 ** If the prNotFound parameter is 0, then the b-tree will be used to iterate
 ** through the set members, skipping any duplicates. In this case an
 ** epheremal table must be used unless the selected <column> is guaranteed
@@ -74764,8 +75337,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
       ** comparison is the same as the affinity of the column. If
       ** it is not, it is not possible to use any index.
       */
-      char aff = comparisonAffinity(pX);
-      int affinity_ok = (pTab->aCol[iCol].affinity==aff||aff==SQLITE_AFF_NONE);
+      int affinity_ok = sqlite3IndexAffinityOk(pX, pTab->aCol[iCol].affinity);
 
       for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){
         if( (pIdx->aiColumn[0]==iCol)
@@ -74893,6 +75465,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
     case TK_IN: {
       char affinity;              /* Affinity of the LHS of the IN */
       KeyInfo keyInfo;            /* Keyinfo for the generated table */
+      static u8 sortOrder = 0;    /* Fake aSortOrder for keyInfo */
       int addr;                   /* Address of OP_OpenEphemeral instruction */
       Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */
 
@@ -74920,6 +75493,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
       if( rMayHaveNull==0 ) sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
       memset(&keyInfo, 0, sizeof(keyInfo));
       keyInfo.nField = 1;
+      keyInfo.aSortOrder = &sortOrder;
 
       if( ExprHasProperty(pExpr, EP_xIsSelect) ){
         /* Case 1:     expr IN (SELECT ...)
@@ -74960,6 +75534,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
           affinity = SQLITE_AFF_NONE;
         }
         keyInfo.aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
+        keyInfo.aSortOrder = &sortOrder;
 
         /* Loop through each expression in <exprlist>. */
         r1 = sqlite3GetTempReg(pParse);
@@ -75286,7 +75861,7 @@ SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int
   ** for testing only - to verify that SQLite always gets the same answer
   ** with and without the column cache.
   */
-  if( pParse->db->flags & SQLITE_ColumnCache ) return;
+  if( OptimizationDisabled(pParse->db, SQLITE_ColumnCache) ) return;
 
   /* First replace any existing entry.
   **
@@ -75483,8 +76058,8 @@ SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, in
 SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
   int i;
   struct yColCache *p;
-  if( NEVER(iFrom==iTo) ) return;
-  sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg);
+  assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo );
+  sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg-1);
   for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
     int x = p->iReg;
     if( x>=iFrom && x<iFrom+nReg ){
@@ -75493,18 +76068,6 @@ SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int n
   }
 }
 
-/*
-** Generate code to copy content from registers iFrom...iFrom+nReg-1
-** over to iTo..iTo+nReg-1.
-*/
-SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse *pParse, int iFrom, int iTo, int nReg){
-  int i;
-  if( NEVER(iFrom==iTo) ) return;
-  for(i=0; i<nReg; i++){
-    sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, iFrom+i, iTo+i);
-  }
-}
-
 #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
 /*
 ** Return true if any register in the range iFrom..iTo (inclusive)
@@ -75976,6 +76539,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
       sqlite3ReleaseTempReg(pParse, r4);
       break;
     }
+    case TK_COLLATE: 
     case TK_UPLUS: {
       inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
       break;
@@ -76345,6 +76909,12 @@ SQLITE_PRIVATE void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
     case TK_ISNULL:  zUniOp = "ISNULL"; break;
     case TK_NOTNULL: zUniOp = "NOTNULL"; break;
 
+    case TK_COLLATE: {
+      sqlite3ExplainExpr(pOut, pExpr->pLeft);
+      sqlite3ExplainPrintf(pOut,".COLLATE(%s)",pExpr->u.zToken);
+      break;
+    }
+
     case TK_AGG_FUNCTION:
     case TK_CONST_FUNC:
     case TK_FUNCTION: {
@@ -76563,6 +77133,9 @@ static int evalConstExpr(Walker *pWalker, Expr *pExpr){
     case TK_REGISTER: {
       return WRC_Prune;
     }
+    case TK_COLLATE: {
+      return WRC_Continue;
+    }
     case TK_FUNCTION:
     case TK_AGG_FUNCTION:
     case TK_CONST_FUNC: {
@@ -76584,9 +77157,11 @@ static int evalConstExpr(Walker *pWalker, Expr *pExpr){
   }
   if( isAppropriateForFactoring(pExpr) ){
     int r1 = ++pParse->nMem;
-    int r2;
-    r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
-    if( NEVER(r1!=r2) ) sqlite3ReleaseTempReg(pParse, r1);
+    int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
+    /* If r2!=r1, it means that register r1 is never used.  That is harmless
+    ** but suboptimal, so we want to know about the situation to fix it.
+    ** Hence the following assert: */
+    assert( r2==r1 );
     pExpr->op2 = pExpr->op;
     pExpr->op = TK_REGISTER;
     pExpr->iTable = r2;
@@ -76614,7 +77189,7 @@ static int evalConstExpr(Walker *pWalker, Expr *pExpr){
 SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){
   Walker w;
   if( pParse->cookieGoto ) return;
-  if( (pParse->db->flags & SQLITE_FactorOutConst)!=0 ) return;
+  if( OptimizationDisabled(pParse->db, SQLITE_FactorOutConst) ) return;
   w.xExprCallback = evalConstExpr;
   w.xSelectCallback = 0;
   w.pParse = pParse;
@@ -77003,7 +77578,15 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){
     return 2;
   }
   if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
-  if( pA->op!=pB->op ) return 2;
+  if( pA->op!=pB->op ){
+    if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB)<2 ){
+      return 1;
+    }
+    if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft)<2 ){
+      return 1;
+    }
+    return 2;
+  }
   if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2;
   if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2;
   if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2;
@@ -77015,11 +77598,9 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){
   }else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){
     if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
     if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
-      return 2;
+      return pA->op==TK_COLLATE ? 1 : 2;
     }
   }
-  if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1;
-  if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2;
   return 0;
 }
 
@@ -77260,8 +77841,10 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
         ExprSetIrreducible(pExpr);
         pExpr->iAgg = (i16)i;
         pExpr->pAggInfo = pAggInfo;
+        return WRC_Prune;
+      }else{
+        return WRC_Continue;
       }
-      return WRC_Prune;
     }
   }
   return WRC_Continue;
@@ -77273,9 +77856,10 @@ static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
 }
 
 /*
-** Analyze the given expression looking for aggregate functions and
-** for variables that need to be added to the pParse->aAgg[] array.
-** Make additional entries to the pParse->aAgg[] array as necessary.
+** Analyze the pExpr expression looking for aggregate functions and
+** for variables that need to be added to AggInfo object that pNC->pAggInfo
+** points to.  Additional entries are made on the AggInfo object as
+** necessary.
 **
 ** This routine should only be called after the expression has been
 ** analyzed by sqlite3ResolveExprNames().
@@ -77788,7 +78372,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
   assert( pSrc->nSrc==1 );
   assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
 
-  pTab = sqlite3LocateTable(pParse, 0, pSrc->a[0].zName, pSrc->a[0].zDatabase);
+  pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
   if( !pTab ) goto exit_rename_table;
   iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
   zDb = db->aDb[iDb].zName;
@@ -78038,7 +78622,7 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
   ** If there is a NOT NULL constraint, then the default value for the
   ** column must not be NULL.
   */
-  if( pCol->isPrimKey ){
+  if( pCol->colFlags & COLFLAG_PRIMKEY ){
     sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column");
     return;
   }
@@ -78131,7 +78715,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
   assert( pParse->pNewTable==0 );
   assert( sqlite3BtreeHoldsAllMutexes(db) );
   if( db->mallocFailed ) goto exit_begin_add_column;
-  pTab = sqlite3LocateTable(pParse, 0, pSrc->a[0].zName, pSrc->a[0].zDatabase);
+  pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
   if( !pTab ) goto exit_begin_add_column;
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -79762,6 +80346,7 @@ SQLITE_PRIVATE int sqlite3FixInit(
   assert( db->nDb>iDb );
   pFix->pParse = pParse;
   pFix->zDb = db->aDb[iDb].zName;
+  pFix->pSchema = db->aDb[iDb].pSchema;
   pFix->zType = zType;
   pFix->pName = pName;
   return 1;
@@ -79792,14 +80377,15 @@ SQLITE_PRIVATE int sqlite3FixSrcList(
   if( NEVER(pList==0) ) return 0;
   zDb = pFix->zDb;
   for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
-    if( pItem->zDatabase==0 ){
-      pItem->zDatabase = sqlite3DbStrDup(pFix->pParse->db, zDb);
-    }else if( sqlite3StrICmp(pItem->zDatabase,zDb)!=0 ){
+    if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
       sqlite3ErrorMsg(pFix->pParse,
          "%s %T cannot reference objects in database %s",
          pFix->zType, pFix->pName, pItem->zDatabase);
       return 1;
     }
+    sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
+    pItem->zDatabase = 0;
+    pItem->pSchema = pFix->pSchema;
 #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
     if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
     if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
@@ -80265,6 +80851,7 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
   sqlite3 *db;
   Vdbe *v;
 
+  assert( pParse->pToplevel==0 );
   db = pParse->db;
   if( db->mallocFailed ) return;
   if( pParse->nested ) return;
@@ -80457,6 +81044,31 @@ SQLITE_PRIVATE Table *sqlite3LocateTable(
   return p;
 }
 
+/*
+** Locate the table identified by *p.
+**
+** This is a wrapper around sqlite3LocateTable(). The difference between
+** sqlite3LocateTable() and this function is that this function restricts
+** the search to schema (p->pSchema) if it is not NULL. p->pSchema may be
+** non-NULL if it is part of a view or trigger program definition. See
+** sqlite3FixSrcList() for details.
+*/
+SQLITE_PRIVATE Table *sqlite3LocateTableItem(
+  Parse *pParse, 
+  int isView, 
+  struct SrcList_item *p
+){
+  const char *zDb;
+  assert( p->pSchema==0 || p->zDatabase==0 );
+  if( p->pSchema ){
+    int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
+    zDb = pParse->db->aDb[iDb].zName;
+  }else{
+    zDb = p->zDatabase;
+  }
+  return sqlite3LocateTable(pParse, isView, p->zName, zDb);
+}
+
 /*
 ** Locate the in-memory structure that describes 
 ** a particular index given the name of that index
@@ -81307,7 +81919,7 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
   pTab->tabFlags |= TF_HasPrimaryKey;
   if( pList==0 ){
     iCol = pTab->nCol - 1;
-    pTab->aCol[iCol].isPrimKey = 1;
+    pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY;
   }else{
     for(i=0; i<pList->nExpr; i++){
       for(iCol=0; iCol<pTab->nCol; iCol++){
@@ -81316,7 +81928,7 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
         }
       }
       if( iCol<pTab->nCol ){
-        pTab->aCol[iCol].isPrimKey = 1;
+        pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY;
       }
     }
     if( pList->nExpr>1 ) iCol = -1;
@@ -81433,10 +82045,7 @@ SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){
 
   pColl = sqlite3FindCollSeq(db, enc, zName, initbusy);
   if( !initbusy && (!pColl || !pColl->xCmp) ){
-    pColl = sqlite3GetCollSeq(db, enc, pColl, zName);
-    if( !pColl ){
-      sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
-    }
+    pColl = sqlite3GetCollSeq(pParse, enc, pColl, zName);
   }
 
   return pColl;
@@ -82135,6 +82744,7 @@ static void destroyTable(Parse *pParse, Table *pTab){
       return;
     }else{
       int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+      assert( iDb>=0 && iDb<pParse->db->nDb );
       destroyRootPage(pParse, iLargest, iDb);
       iDestroyed = iLargest;
     }
@@ -82252,8 +82862,7 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,
   assert( pParse->nErr==0 );
   assert( pName->nSrc==1 );
   if( noErr ) db->suppressErr++;
-  pTab = sqlite3LocateTable(pParse, isView, 
-                            pName->a[0].zName, pName->a[0].zDatabase);
+  pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]);
   if( noErr ) db->suppressErr--;
 
   if( pTab==0 ){
@@ -82693,9 +83302,9 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
       ** sqlite3FixSrcList can never fail. */
       assert(0);
     }
-    pTab = sqlite3LocateTable(pParse, 0, pTblName->a[0].zName, 
-        pTblName->a[0].zDatabase);
-    if( !pTab || db->mallocFailed ) goto exit_create_index;
+    pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
+    assert( db->mallocFailed==0 || pTab==0 );
+    if( pTab==0 ) goto exit_create_index;
     assert( db->aDb[iDb].pSchema==pTab->pSchema );
   }else{
     assert( pName==0 );
@@ -82806,10 +83415,8 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
   for(i=0; i<pList->nExpr; i++){
     Expr *pExpr = pList->a[i].pExpr;
     if( pExpr ){
-      CollSeq *pColl = pExpr->pColl;
-      /* Either pColl!=0 or there was an OOM failure.  But if an OOM
-      ** failure we have quit before reaching this point. */
-      if( ALWAYS(pColl) ){
+      CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr);
+      if( pColl ){
         nExtra += (1 + sqlite3Strlen30(pColl->zName));
       }
     }
@@ -82872,6 +83479,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
     const char *zColName = pListItem->zName;
     Column *pTabCol;
     int requestedSortOrder;
+    CollSeq *pColl;                /* Collating sequence */
     char *zColl;                   /* Collation sequence name */
 
     for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){
@@ -82884,14 +83492,11 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
       goto exit_create_index;
     }
     pIndex->aiColumn[i] = j;
-    /* Justification of the ALWAYS(pListItem->pExpr->pColl):  Because of
-    ** the way the "idxlist" non-terminal is constructed by the parser,
-    ** if pListItem->pExpr is not null then either pListItem->pExpr->pColl
-    ** must exist or else there must have been an OOM error.  But if there
-    ** was an OOM error, we would never reach this point. */
-    if( pListItem->pExpr && ALWAYS(pListItem->pExpr->pColl) ){
+    if( pListItem->pExpr
+     && (pColl = sqlite3ExprCollSeq(pParse, pListItem->pExpr))!=0
+    ){
       int nColl;
-      zColl = pListItem->pExpr->pColl->zName;
+      zColl = pColl->zName;
       nColl = sqlite3Strlen30(zColl) + 1;
       assert( nExtra>=nColl );
       memcpy(zExtra, zColl, nColl);
@@ -83705,6 +84310,15 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){
 SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
   Parse *pToplevel = sqlite3ParseToplevel(pParse);
 
+#ifndef SQLITE_OMIT_TRIGGER
+  if( pToplevel!=pParse ){
+    /* This branch is taken if a trigger is currently being coded. In this
+    ** case, set cookieGoto to a non-zero value to show that this function
+    ** has been called. This is used by the sqlite3ExprCodeConstants()
+    ** function. */
+    pParse->cookieGoto = -1;
+  }
+#endif
   if( pToplevel->cookieGoto==0 ){
     Vdbe *v = sqlite3GetVdbe(pToplevel);
     if( v==0 ) return;  /* This only happens if there was a prior error */
@@ -84054,17 +84668,18 @@ static int synthCollSeq(sqlite3 *db, CollSeq *pColl){
 **
 ** The return value is either the collation sequence to be used in database
 ** db for collation type name zName, length nName, or NULL, if no collation
-** sequence can be found.
+** sequence can be found.  If no collation is found, leave an error message.
 **
 ** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq()
 */
 SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(
-  sqlite3* db,          /* The database connection */
+  Parse *pParse,        /* Parsing context */
   u8 enc,               /* The desired encoding for the collating sequence */
   CollSeq *pColl,       /* Collating sequence with native encoding, or NULL */
   const char *zName     /* Collating sequence name */
 ){
   CollSeq *p;
+  sqlite3 *db = pParse->db;
 
   p = pColl;
   if( !p ){
@@ -84081,6 +84696,9 @@ SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(
     p = 0;
   }
   assert( !p || p->xCmp );
+  if( p==0 ){
+    sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
+  }
   return p;
 }
 
@@ -84099,10 +84717,8 @@ SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){
   if( pColl ){
     const char *zName = pColl->zName;
     sqlite3 *db = pParse->db;
-    CollSeq *p = sqlite3GetCollSeq(db, ENC(db), pColl, zName);
+    CollSeq *p = sqlite3GetCollSeq(pParse, ENC(db), pColl, zName);
     if( !p ){
-      sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
-      pParse->nErr++;
       return SQLITE_ERROR;
     }
     assert( p==pColl );
@@ -84489,7 +85105,7 @@ SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
   struct SrcList_item *pItem = pSrc->a;
   Table *pTab;
   assert( pItem && pSrc->nSrc==1 );
-  pTab = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);
+  pTab = sqlite3LocateTableItem(pParse, 0, pItem);
   sqlite3DeleteTable(pParse->db, pItem->pTab);
   pItem->pTab = pTab;
   if( pTab ){
@@ -84569,6 +85185,7 @@ SQLITE_PRIVATE void sqlite3MaterializeView(
       sqlite3SelectDelete(db, pDup);
     }
     pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
+    if( pDup ) pDup->selFlags |= SF_Materialize;
   }
   sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
   sqlite3Select(pParse, pDup, &dest);
@@ -85095,7 +85712,9 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
   }
   if( doMakeRec ){
     const char *zAff;
-    if( pTab->pSelect || (pParse->db->flags & SQLITE_IdxRealAsInt)!=0 ){
+    if( pTab->pSelect
+     || OptimizationDisabled(pParse->db, SQLITE_IdxRealAsInt)
+    ){
       zAff = 0;
     }else{
       zAff = sqlite3IndexAffinityStr(v, pIdx);
@@ -85277,6 +85896,56 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
   }
 }
 
+/*
+** Implementation of the instr() function.
+**
+** instr(haystack,needle) finds the first occurrence of needle
+** in haystack and returns the number of previous characters plus 1,
+** or 0 if needle does not occur within haystack.
+**
+** If both haystack and needle are BLOBs, then the result is one more than
+** the number of bytes in haystack prior to the first occurrence of needle,
+** or 0 if needle never occurs in haystack.
+*/
+static void instrFunc(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  const unsigned char *zHaystack;
+  const unsigned char *zNeedle;
+  int nHaystack;
+  int nNeedle;
+  int typeHaystack, typeNeedle;
+  int N = 1;
+  int isText;
+
+  UNUSED_PARAMETER(argc);
+  typeHaystack = sqlite3_value_type(argv[0]);
+  typeNeedle = sqlite3_value_type(argv[1]);
+  if( typeHaystack==SQLITE_NULL || typeNeedle==SQLITE_NULL ) return;
+  nHaystack = sqlite3_value_bytes(argv[0]);
+  nNeedle = sqlite3_value_bytes(argv[1]);
+  if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){
+    zHaystack = sqlite3_value_blob(argv[0]);
+    zNeedle = sqlite3_value_blob(argv[1]);
+    isText = 0;
+  }else{
+    zHaystack = sqlite3_value_text(argv[0]);
+    zNeedle = sqlite3_value_text(argv[1]);
+    isText = 1;
+  }
+  while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){
+    N++;
+    do{
+      nHaystack--;
+      zHaystack++;
+    }while( isText && (zHaystack[0]&0xc0)==0x80 );
+  }
+  if( nNeedle>nHaystack ) N = 0;
+  sqlite3_result_int(context, N);
+}
+
 /*
 ** Implementation of the substr() function.
 **
@@ -85476,33 +86145,14 @@ static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
   }
 }
 
-
-#if 0  /* This function is never used. */
-/*
-** The COALESCE() and IFNULL() functions used to be implemented as shown
-** here.  But now they are implemented as VDBE code so that unused arguments
-** do not have to be computed.  This legacy implementation is retained as
-** comment.
-*/
 /*
-** Implementation of the IFNULL(), NVL(), and COALESCE() functions.  
-** All three do the same thing.  They return the first non-NULL
-** argument.
+** The COALESCE() and IFNULL() functions are implemented as VDBE code so
+** that unused argument values do not have to be computed.  However, we
+** still need some kind of function implementation for this routines in
+** the function table.  That function implementation will never be called
+** so it doesn't matter what the implementation is.  We might as well use
+** the "version()" function as a substitute.
 */
-static void ifnullFunc(
-  sqlite3_context *context,
-  int argc,
-  sqlite3_value **argv
-){
-  int i;
-  for(i=0; i<argc; i++){
-    if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
-      sqlite3_result_value(context, argv[i]);
-      break;
-    }
-  }
-}
-#endif /* NOT USED */
 #define ifnullFunc versionFunc   /* Substitute function - never called */
 
 /*
@@ -85621,7 +86271,7 @@ struct compareInfo {
 ** whereas only characters less than 0x80 do in ASCII.
 */
 #if defined(SQLITE_EBCDIC)
-# define sqlite3Utf8Read(A,C)  (*(A++))
+# define sqlite3Utf8Read(A)    (*((*A)++))
 # define GlogUpperToLower(A)   A = sqlite3UpperToLower[A]
 #else
 # define GlogUpperToLower(A)   if( !((A)&~0x7f) ){ A = sqlite3UpperToLower[A]; }
@@ -85678,18 +86328,18 @@ static int patternCompare(
   u8 noCase = pInfo->noCase; 
   int prevEscape = 0;     /* True if the previous character was 'escape' */
 
-  while( (c = sqlite3Utf8Read(zPattern,&zPattern))!=0 ){
-    if( !prevEscape && c==matchAll ){
-      while( (c=sqlite3Utf8Read(zPattern,&zPattern)) == matchAll
+  while( (c = sqlite3Utf8Read(&zPattern))!=0 ){
+    if( c==matchAll && !prevEscape ){
+      while( (c=sqlite3Utf8Read(&zPattern)) == matchAll
                || c == matchOne ){
-        if( c==matchOne && sqlite3Utf8Read(zString, &zString)==0 ){
+        if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){
           return 0;
         }
       }
       if( c==0 ){
         return 1;
       }else if( c==esc ){
-        c = sqlite3Utf8Read(zPattern, &zPattern);
+        c = sqlite3Utf8Read(&zPattern);
         if( c==0 ){
           return 0;
         }
@@ -85701,25 +86351,25 @@ static int patternCompare(
         }
         return *zString!=0;
       }
-      while( (c2 = sqlite3Utf8Read(zString,&zString))!=0 ){
+      while( (c2 = sqlite3Utf8Read(&zString))!=0 ){
         if( noCase ){
           GlogUpperToLower(c2);
           GlogUpperToLower(c);
           while( c2 != 0 && c2 != c ){
-            c2 = sqlite3Utf8Read(zString, &zString);
+            c2 = sqlite3Utf8Read(&zString);
             GlogUpperToLower(c2);
           }
         }else{
           while( c2 != 0 && c2 != c ){
-            c2 = sqlite3Utf8Read(zString, &zString);
+            c2 = sqlite3Utf8Read(&zString);
           }
         }
         if( c2==0 ) return 0;
         if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
       }
       return 0;
-    }else if( !prevEscape && c==matchOne ){
-      if( sqlite3Utf8Read(zString, &zString)==0 ){
+    }else if( c==matchOne && !prevEscape ){
+      if( sqlite3Utf8Read(&zString)==0 ){
         return 0;
       }
     }else if( c==matchSet ){
@@ -85727,20 +86377,20 @@ static int patternCompare(
       assert( esc==0 );    /* This only occurs for GLOB, not LIKE */
       seen = 0;
       invert = 0;
-      c = sqlite3Utf8Read(zString, &zString);
+      c = sqlite3Utf8Read(&zString);
       if( c==0 ) return 0;
-      c2 = sqlite3Utf8Read(zPattern, &zPattern);
+      c2 = sqlite3Utf8Read(&zPattern);
       if( c2=='^' ){
         invert = 1;
-        c2 = sqlite3Utf8Read(zPattern, &zPattern);
+        c2 = sqlite3Utf8Read(&zPattern);
       }
       if( c2==']' ){
         if( c==']' ) seen = 1;
-        c2 = sqlite3Utf8Read(zPattern, &zPattern);
+        c2 = sqlite3Utf8Read(&zPattern);
       }
       while( c2 && c2!=']' ){
         if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){
-          c2 = sqlite3Utf8Read(zPattern, &zPattern);
+          c2 = sqlite3Utf8Read(&zPattern);
           if( c>=prior_c && c<=c2 ) seen = 1;
           prior_c = 0;
         }else{
@@ -85749,7 +86399,7 @@ static int patternCompare(
           }
           prior_c = c2;
         }
-        c2 = sqlite3Utf8Read(zPattern, &zPattern);
+        c2 = sqlite3Utf8Read(&zPattern);
       }
       if( c2==0 || (seen ^ invert)==0 ){
         return 0;
@@ -85757,7 +86407,7 @@ static int patternCompare(
     }else if( esc==c && !prevEscape ){
       prevEscape = 1;
     }else{
-      c2 = sqlite3Utf8Read(zString, &zString);
+      c2 = sqlite3Utf8Read(&zString);
       if( noCase ){
         GlogUpperToLower(c);
         GlogUpperToLower(c2);
@@ -85829,7 +86479,7 @@ static void likeFunc(
           "ESCAPE expression must be a single character", -1);
       return;
     }
-    escape = sqlite3Utf8Read(zEsc, &zEsc);
+    escape = sqlite3Utf8Read(&zEsc);
   }
   if( zA && zB ){
     struct compareInfo *pInfo = sqlite3_user_data(context);
@@ -86664,6 +87314,7 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
     AGGREGATE(max,               1, 1, 1, minmaxStep,      minMaxFinalize ),
     FUNCTION2(typeof,            1, 0, 0, typeofFunc,  SQLITE_FUNC_TYPEOF),
     FUNCTION2(length,            1, 0, 0, lengthFunc,  SQLITE_FUNC_LENGTH),
+    FUNCTION(instr,              2, 0, 0, instrFunc        ),
     FUNCTION(substr,             2, 0, 0, substrFunc       ),
     FUNCTION(substr,             3, 0, 0, substrFunc       ),
     FUNCTION(abs,                1, 0, 0, absFunc          ),
@@ -87247,12 +87898,15 @@ static void fkScanChildren(
       ** expression to the parent key column defaults.  */
       if( pIdx ){
         Column *pCol;
+        const char *zColl;
         iCol = pIdx->aiColumn[i];
         pCol = &pTab->aCol[iCol];
         if( pTab->iPKey==iCol ) iCol = -1;
         pLeft->iTable = regData+iCol+1;
         pLeft->affinity = pCol->affinity;
-        pLeft->pColl = sqlite3LocateCollSeq(pParse, pCol->zColl);
+        zColl = pCol->zColl;
+        if( zColl==0 ) zColl = db->pDfltColl->zName;
+        pLeft = sqlite3ExprAddCollateString(pParse, pLeft, zColl);
       }else{
         pLeft->iTable = regData;
         pLeft->affinity = SQLITE_AFF_INTEGER;
@@ -87661,7 +88315,8 @@ SQLITE_PRIVATE int sqlite3FkRequired(
           int iKey;
           for(iKey=0; iKey<pTab->nCol; iKey++){
             Column *pCol = &pTab->aCol[iKey];
-            if( (zKey ? !sqlite3StrICmp(pCol->zName, zKey) : pCol->isPrimKey) ){
+            if( (zKey ? !sqlite3StrICmp(pCol->zName, zKey)
+                      : (pCol->colFlags & COLFLAG_PRIMKEY)!=0) ){
               if( aChange[iKey]>=0 ) return 1;
               if( iKey==pTab->iPKey && chngRowid ) return 1;
             }
@@ -87982,7 +88637,7 @@ SQLITE_PRIVATE void sqlite3OpenTable(
   int opcode      /* OP_OpenRead or OP_OpenWrite */
 ){
   Vdbe *v;
-  if( IsVirtual(pTab) ) return;
+  assert( !IsVirtual(pTab) );
   v = sqlite3GetVdbe(p);
   assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
   sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite)?1:0, pTab->zName);
@@ -88277,6 +88932,97 @@ SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){
 #endif /* SQLITE_OMIT_AUTOINCREMENT */
 
 
+/*
+** Generate code for a co-routine that will evaluate a subquery one
+** row at a time.
+**
+** The pSelect parameter is the subquery that the co-routine will evaluation.
+** Information about the location of co-routine and the registers it will use
+** is returned by filling in the pDest object.
+**
+** Registers are allocated as follows:
+**
+**   pDest->iSDParm      The register holding the next entry-point of the
+**                       co-routine.  Run the co-routine to its next breakpoint
+**                       by calling "OP_Yield $X" where $X is pDest->iSDParm.
+**
+**   pDest->iSDParm+1    The register holding the "completed" flag for the
+**                       co-routine. This register is 0 if the previous Yield
+**                       generated a new result row, or 1 if the subquery
+**                       has completed.  If the Yield is called again
+**                       after this register becomes 1, then the VDBE will
+**                       halt with an SQLITE_INTERNAL error.
+**
+**   pDest->iSdst        First result register.
+**
+**   pDest->nSdst        Number of result registers.
+**
+** This routine handles all of the register allocation and fills in the
+** pDest structure appropriately.
+**
+** Here is a schematic of the generated code assuming that X is the 
+** co-routine entry-point register reg[pDest->iSDParm], that EOF is the
+** completed flag reg[pDest->iSDParm+1], and R and S are the range of
+** registers that hold the result set, reg[pDest->iSdst] through
+** reg[pDest->iSdst+pDest->nSdst-1]:
+**
+**         X <- A
+**         EOF <- 0
+**         goto B
+**      A: setup for the SELECT
+**         loop rows in the SELECT
+**           load results into registers R..S
+**           yield X
+**         end loop
+**         cleanup after the SELECT
+**         EOF <- 1
+**         yield X
+**         halt-error
+**      B:
+**
+** To use this subroutine, the caller generates code as follows:
+**
+**         [ Co-routine generated by this subroutine, shown above ]
+**      S: yield X
+**         if EOF goto E
+**         if skip this row, goto C
+**         if terminate loop, goto E
+**         deal with this row
+**      C: goto S
+**      E:
+*/
+SQLITE_PRIVATE int sqlite3CodeCoroutine(Parse *pParse, Select *pSelect, SelectDest *pDest){
+  int regYield;       /* Register holding co-routine entry-point */
+  int regEof;         /* Register holding co-routine completion flag */
+  int addrTop;        /* Top of the co-routine */
+  int j1;             /* Jump instruction */
+  int rc;             /* Result code */
+  Vdbe *v;            /* VDBE under construction */
+
+  regYield = ++pParse->nMem;
+  regEof = ++pParse->nMem;
+  v = sqlite3GetVdbe(pParse);
+  addrTop = sqlite3VdbeCurrentAddr(v);
+  sqlite3VdbeAddOp2(v, OP_Integer, addrTop+2, regYield); /* X <- A */
+  VdbeComment((v, "Co-routine entry point"));
+  sqlite3VdbeAddOp2(v, OP_Integer, 0, regEof);           /* EOF <- 0 */
+  VdbeComment((v, "Co-routine completion flag"));
+  sqlite3SelectDestInit(pDest, SRT_Coroutine, regYield);
+  j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
+  rc = sqlite3Select(pParse, pSelect, pDest);
+  assert( pParse->nErr==0 || rc );
+  if( pParse->db->mallocFailed && rc==SQLITE_OK ) rc = SQLITE_NOMEM;
+  if( rc ) return rc;
+  sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof);            /* EOF <- 1 */
+  sqlite3VdbeAddOp1(v, OP_Yield, regYield);   /* yield X */
+  sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_INTERNAL, OE_Abort);
+  VdbeComment((v, "End of coroutine"));
+  sqlite3VdbeJumpHere(v, j1);                             /* label B: */
+  return rc;
+}
+
+
+
 /* Forward declaration */
 static int xferOptimization(
   Parse *pParse,        /* Parser context */
@@ -88525,51 +89271,12 @@ SQLITE_PRIVATE void sqlite3Insert(
   ** co-routine is the common header to the 3rd and 4th templates.
   */
   if( pSelect ){
-    /* Data is coming from a SELECT.  Generate code to implement that SELECT
-    ** as a co-routine.  The code is common to both the 3rd and 4th
-    ** templates:
-    **
-    **         EOF <- 0
-    **         X <- A
-    **         goto B
-    **      A: setup for the SELECT
-    **         loop over the tables in the SELECT
-    **           load value into register R..R+n
-    **           yield X
-    **         end loop
-    **         cleanup after the SELECT
-    **         EOF <- 1
-    **         yield X
-    **         halt-error
-    **
-    ** On each invocation of the co-routine, it puts a single row of the
-    ** SELECT result into registers dest.iMem...dest.iMem+dest.nMem-1.
-    ** (These output registers are allocated by sqlite3Select().)  When
-    ** the SELECT completes, it sets the EOF flag stored in regEof.
-    */
-    int rc, j1;
-
-    regEof = ++pParse->nMem;
-    sqlite3VdbeAddOp2(v, OP_Integer, 0, regEof);      /* EOF <- 0 */
-    VdbeComment((v, "SELECT eof flag"));
-    sqlite3SelectDestInit(&dest, SRT_Coroutine, ++pParse->nMem);
-    addrSelect = sqlite3VdbeCurrentAddr(v)+2;
-    sqlite3VdbeAddOp2(v, OP_Integer, addrSelect-1, dest.iSDParm);
-    j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
-    VdbeComment((v, "Jump over SELECT coroutine"));
-
-    /* Resolve the expressions in the SELECT statement and execute it. */
-    rc = sqlite3Select(pParse, pSelect, &dest);
-    assert( pParse->nErr==0 || rc );
-    if( rc || NEVER(pParse->nErr) || db->mallocFailed ){
-      goto insert_cleanup;
-    }
-    sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof);         /* EOF <- 1 */
-    sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);   /* yield X */
-    sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_INTERNAL, OE_Abort);
-    VdbeComment((v, "End of SELECT coroutine"));
-    sqlite3VdbeJumpHere(v, j1);                          /* label B: */
+    /* Data is coming from a SELECT.  Generate a co-routine to run that
+    ** SELECT. */
+    int rc = sqlite3CodeCoroutine(pParse, pSelect, &dest);
+    if( rc ) goto insert_cleanup;
 
+    regEof = dest.iSDParm + 1;
     regFromSelect = dest.iSdst;
     assert( pSelect->pEList );
     nColumn = pSelect->pEList->nExpr;
@@ -89648,7 +90355,7 @@ static int xferOptimization(
   ** we have to check the semantics.
   */
   pItem = pSelect->pSrc->a;
-  pSrc = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);
+  pSrc = sqlite3LocateTableItem(pParse, 0, pItem);
   if( pSrc==0 ){
     return 0;   /* FROM clause does not contain a real table */
   }
@@ -91426,6 +92133,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
   aFcntl[1] = zLeft;
   aFcntl[2] = zRight;
   aFcntl[3] = 0;
+  db->busyHandler.nBusy = 0;
   rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl);
   if( rc==SQLITE_OK ){
     if( aFcntl[0] ){
@@ -92043,7 +92751,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
         }else{
           sqlite3VdbeAddOp2(v, OP_Null, 0, 5);
         }
-        sqlite3VdbeAddOp2(v, OP_Integer, pCol->isPrimKey, 6);
+        sqlite3VdbeAddOp2(v, OP_Integer,
+                            (pCol->colFlags&COLFLAG_PRIMKEY)!=0, 6);
         sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
       }
     }
@@ -92302,7 +93011,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
       sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
          sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName),
          P4_DYNAMIC);
-      sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1);
+      sqlite3VdbeAddOp2(v, OP_Move, 2, 4);
       sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2);
       sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1);
       sqlite3VdbeJumpHere(v, addr);
@@ -92605,6 +93314,22 @@ SQLITE_PRIVATE void sqlite3Pragma(
     sqlite3_db_release_memory(db);
   }else
 
+  /*
+  **   PRAGMA busy_timeout
+  **   PRAGMA busy_timeout = N
+  **
+  ** Call sqlite3_busy_timeout(db, N).  Return the current timeout value
+  ** if one is set.  If no busy handler or a different busy handler is set
+  ** then 0 is returned.  Setting the busy_timeout to 0 or negative
+  ** disables the timeout.
+  */
+  if( sqlite3StrICmp(zLeft, "busy_timeout")==0 ){
+    if( zRight ){
+      sqlite3_busy_timeout(db, sqlite3Atoi(zRight));
+    }
+    returnSingleInt(pParse, "timeout",  db->busyTimeout);
+  }else
+
 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
   /*
   ** Report the current state of file logs for all databases
@@ -92620,13 +93345,12 @@ SQLITE_PRIVATE void sqlite3Pragma(
     sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", SQLITE_STATIC);
     for(i=0; i<db->nDb; i++){
       Btree *pBt;
-      Pager *pPager;
       const char *zState = "unknown";
       int j;
       if( db->aDb[i].zName==0 ) continue;
       sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, db->aDb[i].zName, P4_STATIC);
       pBt = db->aDb[i].pBt;
-      if( pBt==0 || (pPager = sqlite3BtreePager(pBt))==0 ){
+      if( pBt==0 || sqlite3BtreePager(pBt)==0 ){
         zState = "closed";
       }else if( sqlite3_file_control(db, i ? db->aDb[i].zName : 0, 
                                      SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){
@@ -92835,7 +93559,9 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
 static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
   int rc;
   int i;
+#ifndef SQLITE_OMIT_DEPRECATED
   int size;
+#endif
   Table *pTab;
   Db *pDb;
   char const *azArg[4];
@@ -94090,6 +94816,19 @@ static int checkForMultiColumnSelectError(
 }
 #endif
 
+/*
+** An instance of the following object is used to record information about
+** how to process the DISTINCT keyword, to simplify passing that information
+** into the selectInnerLoop() routine.
+*/
+typedef struct DistinctCtx DistinctCtx;
+struct DistinctCtx {
+  u8 isTnct;      /* True if the DISTINCT keyword is present */
+  u8 eTnctType;   /* One of the WHERE_DISTINCT_* operators */
+  int tabTnct;    /* Ephemeral table used for DISTINCT processing */
+  int addrTnct;   /* Address of OP_OpenEphemeral opcode for tabTnct */
+};
+
 /*
 ** This routine generates the code for the inside of the inner loop
 ** of a SELECT.
@@ -94106,7 +94845,7 @@ static void selectInnerLoop(
   int srcTab,             /* Pull data from this table */
   int nColumn,            /* Number of columns in the source table */
   ExprList *pOrderBy,     /* If not NULL, sort results using this key */
-  int distinct,           /* If >=0, make sure results are distinct */
+  DistinctCtx *pDistinct, /* If not NULL, info on how to process DISTINCT */
   SelectDest *pDest,      /* How to dispose of the results */
   int iContinue,          /* Jump here to continue with next row */
   int iBreak              /* Jump here to break out of the inner loop */
@@ -94122,7 +94861,7 @@ static void selectInnerLoop(
   assert( v );
   if( NEVER(v==0) ) return;
   assert( pEList!=0 );
-  hasDistinct = distinct>=0;
+  hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP;
   if( pOrderBy==0 && !hasDistinct ){
     codeOffset(v, p, iContinue);
   }
@@ -94162,7 +94901,55 @@ static void selectInnerLoop(
   if( hasDistinct ){
     assert( pEList!=0 );
     assert( pEList->nExpr==nColumn );
-    codeDistinct(pParse, distinct, iContinue, nColumn, regResult);
+    switch( pDistinct->eTnctType ){
+      case WHERE_DISTINCT_ORDERED: {
+        VdbeOp *pOp;            /* No longer required OpenEphemeral instr. */
+        int iJump;              /* Jump destination */
+        int regPrev;            /* Previous row content */
+
+        /* Allocate space for the previous row */
+        regPrev = pParse->nMem+1;
+        pParse->nMem += nColumn;
+
+        /* Change the OP_OpenEphemeral coded earlier to an OP_Null
+        ** sets the MEM_Cleared bit on the first register of the
+        ** previous value.  This will cause the OP_Ne below to always
+        ** fail on the first iteration of the loop even if the first
+        ** row is all NULLs.
+        */
+        sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct);
+        pOp = sqlite3VdbeGetOp(v, pDistinct->addrTnct);
+        pOp->opcode = OP_Null;
+        pOp->p1 = 1;
+        pOp->p2 = regPrev;
+
+        iJump = sqlite3VdbeCurrentAddr(v) + nColumn;
+        for(i=0; i<nColumn; i++){
+          CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[i].pExpr);
+          if( i<nColumn-1 ){
+            sqlite3VdbeAddOp3(v, OP_Ne, regResult+i, iJump, regPrev+i);
+          }else{
+            sqlite3VdbeAddOp3(v, OP_Eq, regResult+i, iContinue, regPrev+i);
+          }
+          sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
+          sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
+        }
+        assert( sqlite3VdbeCurrentAddr(v)==iJump );
+        sqlite3VdbeAddOp3(v, OP_Copy, regResult, regPrev, nColumn-1);
+        break;
+      }
+
+      case WHERE_DISTINCT_UNIQUE: {
+        sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct);
+        break;
+      }
+
+      default: {
+        assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED );
+        codeDistinct(pParse, pDistinct->tabTnct, iContinue, nColumn, regResult);
+        break;
+      }
+    }
     if( pOrderBy==0 ){
       codeOffset(v, p, iContinue);
     }
@@ -94220,7 +95007,8 @@ static void selectInnerLoop(
     */
     case SRT_Set: {
       assert( nColumn==1 );
-      p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affSdst);
+      pDest->affSdst =
+                  sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affSdst);
       if( pOrderBy ){
         /* At first glance you would think we could optimize out the
         ** ORDER BY in this case since the order of entries in the set
@@ -94229,7 +95017,7 @@ static void selectInnerLoop(
         pushOntoSorter(pParse, pOrderBy, p, regResult);
       }else{
         int r1 = sqlite3GetTempReg(pParse);
-        sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1);
+        sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult,1,r1, &pDest->affSdst, 1);
         sqlite3ExprCacheAffinityChange(pParse, regResult, 1);
         sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
         sqlite3ReleaseTempReg(pParse, r1);
@@ -94496,7 +95284,8 @@ static void generateSortTail(
 #ifndef SQLITE_OMIT_SUBQUERY
     case SRT_Set: {
       assert( nColumn==1 );
-      sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, &p->affinity, 1);
+      sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid,
+                        &pDest->affSdst, 1);
       sqlite3ExprCacheAffinityChange(pParse, regRow, 1);
       sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid);
       break;
@@ -94811,7 +95600,7 @@ static void generateColumnNames(
 static int selectColumnsFromExprList(
   Parse *pParse,          /* Parsing context */
   ExprList *pEList,       /* Expr list from which to derive column names */
-  int *pnCol,             /* Write the number of columns here */
+  i16 *pnCol,             /* Write the number of columns here */
   Column **paCol          /* Write the new column list here */
 ){
   sqlite3 *db = pParse->db;   /* Database connection */
@@ -94837,7 +95626,7 @@ static int selectColumnsFromExprList(
   for(i=0, pCol=aCol; i<nCol; i++, pCol++){
     /* Get an appropriate name for the column
     */
-    p = pEList->a[i].pExpr;
+    p = sqlite3ExprSkipCollate(pEList->a[i].pExpr);
     assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue)
                || p->pRight->u.zToken==0 || p->pRight->u.zToken[0]!=0 );
     if( (zName = pEList->a[i].zName)!=0 ){
@@ -95333,7 +96122,7 @@ static int multiSelect(
         sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak);
         iStart = sqlite3VdbeCurrentAddr(v);
         selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr,
-                        0, -1, &dest, iCont, iBreak);
+                        0, 0, &dest, iCont, iBreak);
         sqlite3VdbeResolveLabel(v, iCont);
         sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart);
         sqlite3VdbeResolveLabel(v, iBreak);
@@ -95411,7 +96200,7 @@ static int multiSelect(
       sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0);
       sqlite3ReleaseTempReg(pParse, r1);
       selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr,
-                      0, -1, &dest, iCont, iBreak);
+                      0, 0, &dest, iCont, iBreak);
       sqlite3VdbeResolveLabel(v, iCont);
       sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart);
       sqlite3VdbeResolveLabel(v, iBreak);
@@ -95457,6 +96246,7 @@ static int multiSelect(
         *apColl = db->pDfltColl;
       }
     }
+    pKeyInfo->aSortOrder = (u8*)apColl;
 
     for(pLoop=p; pLoop; pLoop=pLoop->pPrior){
       for(i=0; i<2; i++){
@@ -95530,7 +96320,7 @@ static int generateOutputSubroutine(
                               (char*)pKeyInfo, p4type);
     sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2);
     sqlite3VdbeJumpHere(v, j1);
-    sqlite3ExprCodeCopy(pParse, pIn->iSdst, regPrev+1, pIn->nSdst);
+    sqlite3VdbeAddOp3(v, OP_Copy, pIn->iSdst, regPrev+1, pIn->nSdst-1);
     sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev);
   }
   if( pParse->db->mallocFailed ) return 0;
@@ -95565,10 +96355,10 @@ static int generateOutputSubroutine(
     case SRT_Set: {
       int r1;
       assert( pIn->nSdst==1 );
-      p->affinity = 
+      pDest->affSdst = 
          sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affSdst);
       r1 = sqlite3GetTempReg(pParse);
-      sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, 1, r1, &p->affinity, 1);
+      sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, 1, r1, &pDest->affSdst,1);
       sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, 1);
       sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest->iSDParm, r1);
       sqlite3ReleaseTempReg(pParse, r1);
@@ -95834,12 +96624,13 @@ static int multiSelectOrderBy(
       for(i=0; i<nOrderBy; i++){
         CollSeq *pColl;
         Expr *pTerm = pOrderBy->a[i].pExpr;
-        if( pTerm->flags & EP_ExpCollate ){
-          pColl = pTerm->pColl;
+        if( pTerm->flags & EP_Collate ){
+          pColl = sqlite3ExprCollSeq(pParse, pTerm);
         }else{
           pColl = multiSelectCollSeq(pParse, p, aPermute[i]);
-          pTerm->flags |= EP_ExpCollate;
-          pTerm->pColl = pColl;
+          if( pColl==0 ) pColl = db->pDfltColl;
+          pOrderBy->a[i].pExpr =
+             sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
         }
         pKeyMerge->aColl[i] = pColl;
         pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder;
@@ -96042,6 +96833,7 @@ static int multiSelectOrderBy(
   sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);
   sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy,
                          (char*)pKeyMerge, P4_KEYINFO_HANDOFF);
+  sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE);
   sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);
 
   /* Release temporary registers
@@ -96109,9 +96901,6 @@ static Expr *substExpr(
       assert( pEList!=0 && pExpr->iColumn<pEList->nExpr );
       assert( pExpr->pLeft==0 && pExpr->pRight==0 );
       pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0);
-      if( pNew && pExpr->pColl ){
-        pNew->pColl = pExpr->pColl;
-      }
       sqlite3ExprDelete(db, pExpr);
       pExpr = pNew;
     }
@@ -96310,7 +97099,7 @@ static int flattenSubquery(
   */
   assert( p!=0 );
   assert( p->pPrior==0 );  /* Unable to flatten compound queries */
-  if( db->flags & SQLITE_QueryFlattener ) return 0;
+  if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) return 0;
   pSrc = p->pSrc;
   assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
   pSubitem = &pSrc->a[iFrom];
@@ -96599,10 +97388,9 @@ static int flattenSubquery(
     pList = pParent->pEList;
     for(i=0; i<pList->nExpr; i++){
       if( pList->a[i].zName==0 ){
-        const char *zSpan = pList->a[i].zSpan;
-        if( ALWAYS(zSpan) ){
-          pList->a[i].zName = sqlite3DbStrDup(db, zSpan);
-        }
+        char *zName = sqlite3DbStrDup(db, pList->a[i].zSpan);
+        sqlite3Dequote(zName);
+        pList->a[i].zName = zName;
       }
     }
     substExprList(db, pParent->pEList, iParent, pSub->pEList);
@@ -96833,8 +97621,7 @@ static int selectExpander(Walker *pWalker, Select *p){
     }else{
       /* An ordinary table or view name in the FROM clause */
       assert( pFrom->pTab==0 );
-      pFrom->pTab = pTab = 
-        sqlite3LocateTable(pParse,0,pFrom->zName,pFrom->zDatabase);
+      pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
       if( pTab==0 ) return WRC_Abort;
       pTab->nRef++;
 #if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
@@ -97350,11 +98137,9 @@ SQLITE_PRIVATE int sqlite3Select(
   ExprList *pOrderBy;    /* The ORDER BY clause.  May be NULL */
   ExprList *pGroupBy;    /* The GROUP BY clause.  May be NULL */
   Expr *pHaving;         /* The HAVING clause.  May be NULL */
-  int isDistinct;        /* True if the DISTINCT keyword is present */
-  int distinct;          /* Table to use for the distinct set */
   int rc = 1;            /* Value to return from this function */
   int addrSortIndex;     /* Address of an OP_OpenEphemeral instruction */
-  int addrDistinctIndex; /* Address of an OP_OpenEphemeral instruction */
+  DistinctCtx sDistinct; /* Info on how to code the DISTINCT keyword */
   AggInfo sAggInfo;      /* Information used by aggregate queries */
   int iEnd;              /* Address of the end of the query */
   sqlite3 *db;           /* The database connection */
@@ -97414,8 +98199,17 @@ SQLITE_PRIVATE int sqlite3Select(
     int isAggSub;
 
     if( pSub==0 ) continue;
+
+    /* Sometimes the code for a subquery will be generated more than
+    ** once, if the subquery is part of the WHERE clause in a LEFT JOIN,
+    ** for example.  In that case, do not regenerate the code to manifest
+    ** a view or the co-routine to implement a view.  The first instance
+    ** is sufficient, though the subroutine to manifest the view does need
+    ** to be invoked again. */
     if( pItem->addrFillSub ){
-      sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
+      if( pItem->viaCoroutine==0 ){
+        sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
+      }
       continue;
     }
 
@@ -97436,6 +98230,44 @@ SQLITE_PRIVATE int sqlite3Select(
         p->selFlags |= SF_Aggregate;
       }
       i = -1;
+    }else if( pTabList->nSrc==1 && (p->selFlags & SF_Materialize)==0
+      && OptimizationEnabled(db, SQLITE_SubqCoroutine)
+    ){
+      /* Implement a co-routine that will return a single row of the result
+      ** set on each invocation.
+      */
+      int addrTop;
+      int addrEof;
+      pItem->regReturn = ++pParse->nMem;
+      addrEof = ++pParse->nMem;
+      /* Before coding the OP_Goto to jump to the start of the main routine,
+      ** ensure that the jump to the verify-schema routine has already
+      ** been coded. Otherwise, the verify-schema would likely be coded as 
+      ** part of the co-routine. If the main routine then accessed the 
+      ** database before invoking the co-routine for the first time (for 
+      ** example to initialize a LIMIT register from a sub-select), it would 
+      ** be doing so without having verified the schema version and obtained 
+      ** the required db locks. See ticket d6b36be38.  */
+      sqlite3CodeVerifySchema(pParse, -1);
+      sqlite3VdbeAddOp0(v, OP_Goto);
+      addrTop = sqlite3VdbeAddOp1(v, OP_OpenPseudo, pItem->iCursor);
+      sqlite3VdbeChangeP5(v, 1);
+      VdbeComment((v, "coroutine for %s", pItem->pTab->zName));
+      pItem->addrFillSub = addrTop;
+      sqlite3VdbeAddOp2(v, OP_Integer, 0, addrEof);
+      sqlite3VdbeChangeP5(v, 1);
+      sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
+      explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
+      sqlite3Select(pParse, pSub, &dest);
+      pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
+      pItem->viaCoroutine = 1;
+      sqlite3VdbeChangeP2(v, addrTop, dest.iSdst);
+      sqlite3VdbeChangeP3(v, addrTop, dest.nSdst);
+      sqlite3VdbeAddOp2(v, OP_Integer, 1, addrEof);
+      sqlite3VdbeAddOp1(v, OP_Yield, pItem->regReturn);
+      VdbeComment((v, "end %s", pItem->pTab->zName));
+      sqlite3VdbeJumpHere(v, addrTop-1);
+      sqlite3ClearTempRegCache(pParse);
     }else{
       /* Generate a subroutine that will fill an ephemeral table with
       ** the content of this subquery.  pItem->addrFillSub will point
@@ -97480,7 +98312,7 @@ SQLITE_PRIVATE int sqlite3Select(
   pWhere = p->pWhere;
   pGroupBy = p->pGroupBy;
   pHaving = p->pHaving;
-  isDistinct = (p->selFlags & SF_Distinct)!=0;
+  sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0;
 
 #ifndef SQLITE_OMIT_COMPOUND_SELECT
   /* If there is are a sequence of queries, do the earlier ones first.
@@ -97515,7 +98347,7 @@ SQLITE_PRIVATE int sqlite3Select(
   ** to disable this optimization for testing purposes.
   */
   if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy)==0
-         && (db->flags & SQLITE_GroupByOrder)==0 ){
+         && OptimizationEnabled(db, SQLITE_GroupByOrder) ){
     pOrderBy = 0;
   }
 
@@ -97541,6 +98373,10 @@ SQLITE_PRIVATE int sqlite3Select(
     p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
     pGroupBy = p->pGroupBy;
     pOrderBy = 0;
+    /* Notice that even thought SF_Distinct has been cleared from p->selFlags,
+    ** the sDistinct.isTnct is still set.  Hence, isTnct represents the
+    ** original setting of the SF_Distinct flag, not the current setting */
+    assert( sDistinct.isTnct );
   }
 
   /* If there is an ORDER BY clause, then this sorting
@@ -97581,24 +98417,27 @@ SQLITE_PRIVATE int sqlite3Select(
   /* Open a virtual index to use for the distinct set.
   */
   if( p->selFlags & SF_Distinct ){
-    KeyInfo *pKeyInfo;
-    distinct = pParse->nTab++;
-    pKeyInfo = keyInfoFromExprList(pParse, p->pEList);
-    addrDistinctIndex = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0,
-        (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
+    sDistinct.tabTnct = pParse->nTab++;
+    sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
+                                sDistinct.tabTnct, 0, 0,
+                                (char*)keyInfoFromExprList(pParse, p->pEList),
+                                P4_KEYINFO_HANDOFF);
     sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
+    sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED;
   }else{
-    distinct = addrDistinctIndex = -1;
+    sDistinct.eTnctType = WHERE_DISTINCT_NOOP;
   }
 
-  /* Aggregate and non-aggregate queries are handled differently */
   if( !isAgg && pGroupBy==0 ){
-    ExprList *pDist = (isDistinct ? p->pEList : 0);
+    /* No aggregate functions and no GROUP BY clause */
+    ExprList *pDist = (sDistinct.isTnct ? p->pEList : 0);
 
     /* Begin the database scan. */
-    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, pDist, 0,0);
+    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pOrderBy, pDist, 0,0);
     if( pWInfo==0 ) goto select_end;
     if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;
+    if( pWInfo->eDistinct ) sDistinct.eTnctType = pWInfo->eDistinct;
+    if( pOrderBy && pWInfo->nOBSat==pOrderBy->nExpr ) pOrderBy = 0;
 
     /* If sorting index that was created by a prior OP_OpenEphemeral 
     ** instruction ended up not being needed, then change the OP_OpenEphemeral
@@ -97609,59 +98448,16 @@ SQLITE_PRIVATE int sqlite3Select(
       p->addrOpenEphm[2] = -1;
     }
 
-    if( pWInfo->eDistinct ){
-      VdbeOp *pOp;                /* No longer required OpenEphemeral instr. */
-     
-      assert( addrDistinctIndex>=0 );
-      pOp = sqlite3VdbeGetOp(v, addrDistinctIndex);
-
-      assert( isDistinct );
-      assert( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED 
-           || pWInfo->eDistinct==WHERE_DISTINCT_UNIQUE 
-      );
-      distinct = -1;
-      if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED ){
-        int iJump;
-        int iExpr;
-        int iFlag = ++pParse->nMem;
-        int iBase = pParse->nMem+1;
-        int iBase2 = iBase + pEList->nExpr;
-        pParse->nMem += (pEList->nExpr*2);
-
-        /* Change the OP_OpenEphemeral coded earlier to an OP_Integer. The
-        ** OP_Integer initializes the "first row" flag.  */
-        pOp->opcode = OP_Integer;
-        pOp->p1 = 1;
-        pOp->p2 = iFlag;
-
-        sqlite3ExprCodeExprList(pParse, pEList, iBase, 1);
-        iJump = sqlite3VdbeCurrentAddr(v) + 1 + pEList->nExpr + 1 + 1;
-        sqlite3VdbeAddOp2(v, OP_If, iFlag, iJump-1);
-        for(iExpr=0; iExpr<pEList->nExpr; iExpr++){
-          CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[iExpr].pExpr);
-          sqlite3VdbeAddOp3(v, OP_Ne, iBase+iExpr, iJump, iBase2+iExpr);
-          sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
-          sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
-        }
-        sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iContinue);
-
-        sqlite3VdbeAddOp2(v, OP_Integer, 0, iFlag);
-        assert( sqlite3VdbeCurrentAddr(v)==iJump );
-        sqlite3VdbeAddOp3(v, OP_Move, iBase, iBase2, pEList->nExpr);
-      }else{
-        pOp->opcode = OP_Noop;
-      }
-    }
-
     /* Use the standard inner loop. */
-    selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, pDest,
+    selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, &sDistinct, pDest,
                     pWInfo->iContinue, pWInfo->iBreak);
 
     /* End the database scan loop.
     */
     sqlite3WhereEnd(pWInfo);
   }else{
-    /* This is the processing for aggregate queries */
+    /* This case when there exist aggregate functions or a GROUP BY clause
+    ** or both */
     NameContext sNC;    /* Name context for processing aggregate information */
     int iAMem;          /* First Mem address for storing current GROUP BY */
     int iBMem;          /* First Mem address for previous GROUP BY */
@@ -97769,14 +98565,13 @@ SQLITE_PRIVATE int sqlite3Select(
       ** in the right order to begin with.
       */
       sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
-      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0, 0, 0);
+      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0, 0, 0);
       if( pWInfo==0 ) goto select_end;
-      if( pGroupBy==0 ){
+      if( pWInfo->nOBSat==pGroupBy->nExpr ){
         /* The optimizer is able to deliver rows in group by order so
         ** we do not have to sort.  The OP_OpenEphemeral table will be
         ** cancelled later because we still need to use the pKeyInfo
         */
-        pGroupBy = p->pGroupBy;
         groupBySort = 0;
       }else{
         /* Rows are coming out in undetermined order.  We have to push
@@ -97790,7 +98585,8 @@ SQLITE_PRIVATE int sqlite3Select(
         int nGroupBy;
 
         explainTempTable(pParse, 
-            isDistinct && !(p->selFlags&SF_Distinct)?"DISTINCT":"GROUP BY");
+            (sDistinct.isTnct && (p->selFlags&SF_Distinct)==0) ?
+                    "DISTINCT" : "GROUP BY");
 
         groupBySort = 1;
         nGroupBy = pGroupBy->nExpr;
@@ -97922,7 +98718,7 @@ SQLITE_PRIVATE int sqlite3Select(
       finalizeAggFunctions(pParse, &sAggInfo);
       sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL);
       selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy,
-                      distinct, pDest,
+                      &sDistinct, pDest,
                       addrOutputRow+1, addrSetAbort);
       sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
       VdbeComment((v, "end groupby result generator"));
@@ -98025,6 +98821,7 @@ SQLITE_PRIVATE int sqlite3Select(
         u8 flag = minMaxQuery(p);
         if( flag ){
           assert( !ExprHasProperty(p->pEList->a[0].pExpr, EP_xIsSelect) );
+          assert( p->pEList->a[0].pExpr->x.pList->nExpr==1 );
           pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->x.pList,0);
           pDel = pMinMax;
           if( pMinMax && !db->mallocFailed ){
@@ -98038,13 +98835,14 @@ SQLITE_PRIVATE int sqlite3Select(
         ** of output.
         */
         resetAccumulator(pParse, &sAggInfo);
-        pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax,0,flag,0);
+        pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax,0,flag,0);
         if( pWInfo==0 ){
           sqlite3ExprListDelete(db, pDel);
           goto select_end;
         }
         updateAccumulator(pParse, &sAggInfo);
-        if( !pMinMax && flag ){
+        assert( pMinMax==0 || pMinMax->nExpr==1 );
+        if( pWInfo->nOBSat>0 ){
           sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak);
           VdbeComment((v, "%s() by index",
                 (flag==WHERE_ORDERBY_MIN?"min":"max")));
@@ -98055,7 +98853,7 @@ SQLITE_PRIVATE int sqlite3Select(
 
       pOrderBy = 0;
       sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL);
-      selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, -1
+      selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, 0
                       pDest, addrEnd, addrEnd);
       sqlite3ExprListDelete(db, pDel);
     }
@@ -98063,7 +98861,7 @@ SQLITE_PRIVATE int sqlite3Select(
     
   } /* endif aggregate query */
 
-  if( distinct>=0 ){
+  if( sDistinct.eTnctType==WHERE_DISTINCT_UNORDERED ){
     explainTempTable(pParse, "DISTINCT");
   }
 
@@ -99128,6 +99926,15 @@ static int codeTriggerProgram(
     */
     pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf;
 
+    /* Clear the cookieGoto flag. When coding triggers, the cookieGoto 
+    ** variable is used as a flag to indicate to sqlite3ExprCodeConstants()
+    ** that it is not safe to refactor constants (this happens after the
+    ** start of the first loop in the SQL statement is coded - at that 
+    ** point code may be conditionally executed, so it is no longer safe to 
+    ** initialize constant register values).  */
+    assert( pParse->cookieGoto==0 || pParse->cookieGoto==-1 );
+    pParse->cookieGoto = 0;
+
     switch( pStep->op ){
       case TK_UPDATE: {
         sqlite3Update(pParse, 
@@ -100284,6 +101091,7 @@ SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){
   Vdbe *v = sqlite3GetVdbe(pParse);
   if( v ){
     sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0);
+    sqlite3VdbeUsesBtree(v, 0);
   }
   return;
 }
@@ -100812,7 +101620,7 @@ SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){
   if( p->azModuleArg ){
     int i;
     for(i=0; i<p->nModuleArg; i++){
-      sqlite3DbFree(db, p->azModuleArg[i]);
+      if( i!=1 ) sqlite3DbFree(db, p->azModuleArg[i]);
     }
     sqlite3DbFree(db, p->azModuleArg);
   }
@@ -100872,7 +101680,7 @@ SQLITE_PRIVATE void sqlite3VtabBeginParse(
   pTable->tabFlags |= TF_Virtual;
   pTable->nModuleArg = 0;
   addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName));
-  addModuleArgument(db, pTable, sqlite3DbStrDup(db, db->aDb[iDb].zName));
+  addModuleArgument(db, pTable, 0);
   addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName));
   pParse->sNameToken.n = (int)(&pModuleName->z[pModuleName->n] - pName1->z);
 
@@ -101029,6 +101837,7 @@ static int vtabCallConstructor(
   int nArg = pTab->nModuleArg;
   char *zErr = 0;
   char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName);
+  int iDb;
 
   if( !zModuleName ){
     return SQLITE_NOMEM;
@@ -101042,6 +101851,9 @@ static int vtabCallConstructor(
   pVTable->db = db;
   pVTable->pMod = pMod;
 
+  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+  pTab->azModuleArg[1] = db->aDb[iDb].zName;
+
   /* Invoke the virtual table constructor */
   assert( &db->pVtabCtx );
   assert( xConstruct );
@@ -101076,7 +101888,7 @@ static int vtabCallConstructor(
       /* If everything went according to plan, link the new VTable structure
       ** into the linked list headed by pTab->pVTable. Then loop through the 
       ** columns of the table to see if any of them contain the token "hidden".
-      ** If so, set the Column.isHidden flag and remove the token from
+      ** If so, set the Column COLFLAG_HIDDEN flag and remove the token from
       ** the type string.  */
       pVTable->pNext = pTab->pVTable;
       pTab->pVTable = pVTable;
@@ -101107,7 +101919,7 @@ static int vtabCallConstructor(
             assert(zType[i-1]==' ');
             zType[i-1] = '\0';
           }
-          pTab->aCol[iCol].isHidden = 1;
+          pTab->aCol[iCol].colFlags |= COLFLAG_HIDDEN;
         }
       }
     }
@@ -101668,9 +102480,10 @@ SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){
 ** Trace output macros
 */
 #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
-SQLITE_PRIVATE int sqlite3WhereTrace = 0;
+/***/ int sqlite3WhereTrace = 0;
 #endif
-#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+#if defined(SQLITE_DEBUG) \
+    && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
 # define WHERETRACE(X)  if(sqlite3WhereTrace) sqlite3DebugPrintf X
 #else
 # define WHERETRACE(X)
@@ -101901,14 +102714,49 @@ struct WhereCost {
 #define WHERE_TOP_LIMIT    0x00100000  /* x<EXPR or x<=EXPR constraint */
 #define WHERE_BTM_LIMIT    0x00200000  /* x>EXPR or x>=EXPR constraint */
 #define WHERE_BOTH_LIMIT   0x00300000  /* Both x>EXPR and x<EXPR */
-#define WHERE_IDX_ONLY     0x00800000  /* Use index only - omit table */
-#define WHERE_ORDERBY      0x01000000  /* Output will appear in correct order */
-#define WHERE_REVERSE      0x02000000  /* Scan in reverse order */
-#define WHERE_UNIQUE       0x04000000  /* Selects no more than one row */
+#define WHERE_IDX_ONLY     0x00400000  /* Use index only - omit table */
+#define WHERE_ORDERED      0x00800000  /* Output will appear in correct order */
+#define WHERE_REVERSE      0x01000000  /* Scan in reverse order */
+#define WHERE_UNIQUE       0x02000000  /* Selects no more than one row */
+#define WHERE_ALL_UNIQUE   0x04000000  /* This and all prior have one row */
 #define WHERE_VIRTUALTABLE 0x08000000  /* Use virtual-table processing */
 #define WHERE_MULTI_OR     0x10000000  /* OR using multiple indices */
 #define WHERE_TEMP_INDEX   0x20000000  /* Uses an ephemeral index */
 #define WHERE_DISTINCT     0x40000000  /* Correct order for DISTINCT */
+#define WHERE_COVER_SCAN   0x80000000  /* Full scan of a covering index */
+
+/*
+** This module contains many separate subroutines that work together to
+** find the best indices to use for accessing a particular table in a query.
+** An instance of the following structure holds context information about the
+** index search so that it can be more easily passed between the various
+** routines.
+*/
+typedef struct WhereBestIdx WhereBestIdx;
+struct WhereBestIdx {
+  Parse *pParse;                  /* Parser context */
+  WhereClause *pWC;               /* The WHERE clause */
+  struct SrcList_item *pSrc;      /* The FROM clause term to search */
+  Bitmask notReady;               /* Mask of cursors not available */
+  Bitmask notValid;               /* Cursors not available for any purpose */
+  ExprList *pOrderBy;             /* The ORDER BY clause */
+  ExprList *pDistinct;            /* The select-list if query is DISTINCT */
+  sqlite3_index_info **ppIdxInfo; /* Index information passed to xBestIndex */
+  int i, n;                       /* Which loop is being coded; # of loops */
+  WhereLevel *aLevel;             /* Info about outer loops */
+  WhereCost cost;                 /* Lowest cost query plan */
+};
+
+/*
+** Return TRUE if the probe cost is less than the baseline cost
+*/
+static int compareCost(const WhereCost *pProbe, const WhereCost *pBaseline){
+  if( pProbe->rCost<pBaseline->rCost ) return 1;
+  if( pProbe->rCost>pBaseline->rCost ) return 0;
+  if( pProbe->plan.nOBSat>pBaseline->plan.nOBSat ) return 1;
+  if( pProbe->plan.nRow<pBaseline->plan.nRow ) return 1;
+  return 0;
+}
 
 /*
 ** Initialize a preallocated WhereClause structure.
@@ -102172,23 +103020,32 @@ static int allowedOp(int op){
 ** Commute a comparison operator.  Expressions of the form "X op Y"
 ** are converted into "Y op X".
 **
-** If a collation sequence is associated with either the left or right
+** If left/right precendence rules come into play when determining the
+** collating
 ** side of the comparison, it remains associated with the same side after
 ** the commutation. So "Y collate NOCASE op X" becomes 
-** "X collate NOCASE op Y". This is because any collation sequence on
+** "X op Y". This is because any collation sequence on
 ** the left hand side of a comparison overrides any collation sequence 
-** attached to the right. For the same reason the EP_ExpCollate flag
+** attached to the right. For the same reason the EP_Collate flag
 ** is not commuted.
 */
 static void exprCommute(Parse *pParse, Expr *pExpr){
-  u16 expRight = (pExpr->pRight->flags & EP_ExpCollate);
-  u16 expLeft = (pExpr->pLeft->flags & EP_ExpCollate);
+  u16 expRight = (pExpr->pRight->flags & EP_Collate);
+  u16 expLeft = (pExpr->pLeft->flags & EP_Collate);
   assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
-  pExpr->pRight->pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight);
-  pExpr->pLeft->pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
-  SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl);
-  pExpr->pRight->flags = (pExpr->pRight->flags & ~EP_ExpCollate) | expLeft;
-  pExpr->pLeft->flags = (pExpr->pLeft->flags & ~EP_ExpCollate) | expRight;
+  if( expRight==expLeft ){
+    /* Either X and Y both have COLLATE operator or neither do */
+    if( expRight ){
+      /* Both X and Y have COLLATE operators.  Make sure X is always
+      ** used by clearing the EP_Collate flag from Y. */
+      pExpr->pRight->flags &= ~EP_Collate;
+    }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){
+      /* Neither X nor Y have COLLATE operators, but X has a non-default
+      ** collating sequence.  So add the EP_Collate marker on X to cause
+      ** it to be searched first. */
+      pExpr->pLeft->flags |= EP_Collate;
+    }
+  }
   SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
   if( pExpr->op>=TK_GT ){
     assert( TK_LT==TK_GT+2 );
@@ -102265,12 +103122,12 @@ static WhereTerm *findTerm(
           */
           assert(pX->pLeft);
           pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
-          assert(pColl || pParse->nErr);
+          if( pColl==0 ) pColl = pParse->db->pDfltColl;
   
           for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
             if( NEVER(j>=pIdx->nColumn) ) return 0;
           }
-          if( pColl && sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
+          if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
         }
         return pTerm;
       }
@@ -102788,7 +103645,7 @@ static void exprAnalyze(
   }
   pTerm = &pWC->a[idxTerm];
   pMaskSet = pWC->pMaskSet;
-  pExpr = pTerm->pExpr;
+  pExpr = sqlite3ExprSkipCollate(pTerm->pExpr);
   prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
   op = pExpr->op;
   if( op==TK_IN ){
@@ -102815,8 +103672,8 @@ static void exprAnalyze(
   pTerm->iParent = -1;
   pTerm->eOperator = 0;
   if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){
-    Expr *pLeft = pExpr->pLeft;
-    Expr *pRight = pExpr->pRight;
+    Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
+    Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
     if( pLeft->op==TK_COLUMN ){
       pTerm->leftCursor = pLeft->iTable;
       pTerm->u.leftColumn = pLeft->iColumn;
@@ -102844,7 +103701,7 @@ static void exprAnalyze(
         pNew = pTerm;
       }
       exprCommute(pParse, pDup);
-      pLeft = pDup->pLeft;
+      pLeft = sqlite3ExprSkipCollate(pDup->pLeft);
       pNew->leftCursor = pLeft->iTable;
       pNew->u.leftColumn = pLeft->iColumn;
       testcase( (prereqLeft | extraRight) != prereqLeft );
@@ -102923,7 +103780,7 @@ static void exprAnalyze(
     Expr *pNewExpr2;
     int idxNew1;
     int idxNew2;
-    CollSeq *pColl;    /* Collating sequence to use */
+    Token sCollSeqName;  /* Name of collating sequence */
 
     pLeft = pExpr->x.pList->a[1].pExpr;
     pStr2 = sqlite3ExprDup(db, pStr1, 0);
@@ -102945,16 +103802,19 @@ static void exprAnalyze(
       }
       *pC = c + 1;
     }
-    pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, noCase ? "NOCASE" : "BINARY",0);
+    sCollSeqName.z = noCase ? "NOCASE" : "BINARY";
+    sCollSeqName.n = 6;
+    pNewExpr1 = sqlite3ExprDup(db, pLeft, 0);
     pNewExpr1 = sqlite3PExpr(pParse, TK_GE, 
-                     sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl),
-                     pStr1, 0);
+           sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName),
+           pStr1, 0);
     idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
     testcase( idxNew1==0 );
     exprAnalyze(pSrc, pWC, idxNew1);
+    pNewExpr2 = sqlite3ExprDup(db, pLeft, 0);
     pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
-                     sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl),
-                     pStr2, 0);
+           sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName),
+           pStr2, 0);
     idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
     testcase( idxNew2==0 );
     exprAnalyze(pSrc, pWC, idxNew2);
@@ -103051,25 +103911,6 @@ static void exprAnalyze(
   pTerm->prereqRight |= extraRight;
 }
 
-/*
-** Return TRUE if any of the expressions in pList->a[iFirst...] contain
-** a reference to any table other than the iBase table.
-*/
-static int referencesOtherTables(
-  ExprList *pList,          /* Search expressions in ths list */
-  WhereMaskSet *pMaskSet,   /* Mapping from tables to bitmaps */
-  int iFirst,               /* Be searching with the iFirst-th expression */
-  int iBase                 /* Ignore references to this table */
-){
-  Bitmask allowed = ~getMask(pMaskSet, iBase);
-  while( iFirst<pList->nExpr ){
-    if( (exprTableUsage(pMaskSet, pList->a[iFirst++].pExpr)&allowed)!=0 ){
-      return 1;
-    }
-  }
-  return 0;
-}
-
 /*
 ** This function searches the expression list passed as the second argument
 ** for an expression of type TK_COLUMN that refers to the same column and
@@ -103091,12 +103932,12 @@ static int findIndexCol(
   const char *zColl = pIdx->azColl[iCol];
 
   for(i=0; i<pList->nExpr; i++){
-    Expr *p = pList->a[i].pExpr;
+    Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr);
     if( p->op==TK_COLUMN
      && p->iColumn==pIdx->aiColumn[iCol]
      && p->iTable==iBase
     ){
-      CollSeq *pColl = sqlite3ExprCollSeq(pParse, p);
+      CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr);
       if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){
         return i;
       }
@@ -103129,7 +103970,8 @@ static int isDistinctIndex(
   Bitmask mask = 0;               /* Mask of unaccounted for pDistinct exprs */
   int i;                          /* Iterator variable */
 
-  if( pIdx->zName==0 || pDistinct==0 || pDistinct->nExpr>=BMS ) return 0;
+  assert( pDistinct!=0 );
+  if( pIdx->zName==0 || pDistinct->nExpr>=BMS ) return 0;
   testcase( pDistinct->nExpr==BMS-1 );
 
   /* Loop through all the expressions in the distinct list. If any of them
@@ -103142,7 +103984,7 @@ static int isDistinctIndex(
   */
   for(i=0; i<pDistinct->nExpr; i++){
     WhereTerm *pTerm;
-    Expr *p = pDistinct->a[i].pExpr;
+    Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr);
     if( p->op!=TK_COLUMN ) return 0;
     pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0);
     if( pTerm ){
@@ -103194,7 +104036,7 @@ static int isDistinctRedundant(
   ** current SELECT is a correlated sub-query.
   */
   for(i=0; i<pDistinct->nExpr; i++){
-    Expr *p = pDistinct->a[i].pExpr;
+    Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr);
     if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
   }
 
@@ -103231,165 +104073,6 @@ static int isDistinctRedundant(
   return 0;
 }
 
-/*
-** This routine decides if pIdx can be used to satisfy the ORDER BY
-** clause.  If it can, it returns 1.  If pIdx cannot satisfy the
-** ORDER BY clause, this routine returns 0.
-**
-** pOrderBy is an ORDER BY clause from a SELECT statement.  pTab is the
-** left-most table in the FROM clause of that same SELECT statement and
-** the table has a cursor number of "base".  pIdx is an index on pTab.
-**
-** nEqCol is the number of columns of pIdx that are used as equality
-** constraints.  Any of these columns may be missing from the ORDER BY
-** clause and the match can still be a success.
-**
-** All terms of the ORDER BY that match against the index must be either
-** ASC or DESC.  (Terms of the ORDER BY clause past the end of a UNIQUE
-** index do not need to satisfy this constraint.)  The *pbRev value is
-** set to 1 if the ORDER BY clause is all DESC and it is set to 0 if
-** the ORDER BY clause is all ASC.
-*/
-static int isSortingIndex(
-  Parse *pParse,          /* Parsing context */
-  WhereMaskSet *pMaskSet, /* Mapping from table cursor numbers to bitmaps */
-  Index *pIdx,            /* The index we are testing */
-  int base,               /* Cursor number for the table to be sorted */
-  ExprList *pOrderBy,     /* The ORDER BY clause */
-  int nEqCol,             /* Number of index columns with == constraints */
-  int wsFlags,            /* Index usages flags */
-  int *pbRev              /* Set to 1 if ORDER BY is DESC */
-){
-  int i, j;                       /* Loop counters */
-  int sortOrder = 0;              /* XOR of index and ORDER BY sort direction */
-  int nTerm;                      /* Number of ORDER BY terms */
-  struct ExprList_item *pTerm;    /* A term of the ORDER BY clause */
-  sqlite3 *db = pParse->db;
-
-  if( !pOrderBy ) return 0;
-  if( wsFlags & WHERE_COLUMN_IN ) return 0;
-  if( pIdx->bUnordered ) return 0;
-
-  nTerm = pOrderBy->nExpr;
-  assert( nTerm>0 );
-
-  /* Argument pIdx must either point to a 'real' named index structure, 
-  ** or an index structure allocated on the stack by bestBtreeIndex() to
-  ** represent the rowid index that is part of every table.  */
-  assert( pIdx->zName || (pIdx->nColumn==1 && pIdx->aiColumn[0]==-1) );
-
-  /* Match terms of the ORDER BY clause against columns of
-  ** the index.
-  **
-  ** Note that indices have pIdx->nColumn regular columns plus
-  ** one additional column containing the rowid.  The rowid column
-  ** of the index is also allowed to match against the ORDER BY
-  ** clause.
-  */
-  for(i=j=0, pTerm=pOrderBy->a; j<nTerm && i<=pIdx->nColumn; i++){
-    Expr *pExpr;       /* The expression of the ORDER BY pTerm */
-    CollSeq *pColl;    /* The collating sequence of pExpr */
-    int termSortOrder; /* Sort order for this term */
-    int iColumn;       /* The i-th column of the index.  -1 for rowid */
-    int iSortOrder;    /* 1 for DESC, 0 for ASC on the i-th index term */
-    const char *zColl; /* Name of the collating sequence for i-th index term */
-
-    pExpr = pTerm->pExpr;
-    if( pExpr->op!=TK_COLUMN || pExpr->iTable!=base ){
-      /* Can not use an index sort on anything that is not a column in the
-      ** left-most table of the FROM clause */
-      break;
-    }
-    pColl = sqlite3ExprCollSeq(pParse, pExpr);
-    if( !pColl ){
-      pColl = db->pDfltColl;
-    }
-    if( pIdx->zName && i<pIdx->nColumn ){
-      iColumn = pIdx->aiColumn[i];
-      if( iColumn==pIdx->pTable->iPKey ){
-        iColumn = -1;
-      }
-      iSortOrder = pIdx->aSortOrder[i];
-      zColl = pIdx->azColl[i];
-    }else{
-      iColumn = -1;
-      iSortOrder = 0;
-      zColl = pColl->zName;
-    }
-    if( pExpr->iColumn!=iColumn || sqlite3StrICmp(pColl->zName, zColl) ){
-      /* Term j of the ORDER BY clause does not match column i of the index */
-      if( i<nEqCol ){
-        /* If an index column that is constrained by == fails to match an
-        ** ORDER BY term, that is OK.  Just ignore that column of the index
-        */
-        continue;
-      }else if( i==pIdx->nColumn ){
-        /* Index column i is the rowid.  All other terms match. */
-        break;
-      }else{
-        /* If an index column fails to match and is not constrained by ==
-        ** then the index cannot satisfy the ORDER BY constraint.
-        */
-        return 0;
-      }
-    }
-    assert( pIdx->aSortOrder!=0 || iColumn==-1 );
-    assert( pTerm->sortOrder==0 || pTerm->sortOrder==1 );
-    assert( iSortOrder==0 || iSortOrder==1 );
-    termSortOrder = iSortOrder ^ pTerm->sortOrder;
-    if( i>nEqCol ){
-      if( termSortOrder!=sortOrder ){
-        /* Indices can only be used if all ORDER BY terms past the
-        ** equality constraints are all either DESC or ASC. */
-        return 0;
-      }
-    }else{
-      sortOrder = termSortOrder;
-    }
-    j++;
-    pTerm++;
-    if( iColumn<0 && !referencesOtherTables(pOrderBy, pMaskSet, j, base) ){
-      /* If the indexed column is the primary key and everything matches
-      ** so far and none of the ORDER BY terms to the right reference other
-      ** tables in the join, then we are assured that the index can be used 
-      ** to sort because the primary key is unique and so none of the other
-      ** columns will make any difference
-      */
-      j = nTerm;
-    }
-  }
-
-  *pbRev = sortOrder!=0;
-  if( j>=nTerm ){
-    /* All terms of the ORDER BY clause are covered by this index so
-    ** this index can be used for sorting. */
-    return 1;
-  }
-  if( pIdx->onError!=OE_None && i==pIdx->nColumn
-      && (wsFlags & WHERE_COLUMN_NULL)==0
-      && !referencesOtherTables(pOrderBy, pMaskSet, j, base) 
-  ){
-    Column *aCol = pIdx->pTable->aCol;
-
-    /* All terms of this index match some prefix of the ORDER BY clause,
-    ** the index is UNIQUE, and no terms on the tail of the ORDER BY
-    ** refer to other tables in a join. So, assuming that the index entries
-    ** visited contain no NULL values, then this index delivers rows in
-    ** the required order.
-    **
-    ** It is not possible for any of the first nEqCol index fields to be
-    ** NULL (since the corresponding "=" operator in the WHERE clause would 
-    ** not be true). So if all remaining index columns have NOT NULL 
-    ** constaints attached to them, we can be confident that the visited
-    ** index entries are free of NULLs.  */
-    for(i=nEqCol; i<pIdx->nColumn; i++){
-      if( aCol[pIdx->aiColumn[i]].notNull==0 ) break;
-    }
-    return (i==pIdx->nColumn);
-  }
-  return 0;
-}
-
 /*
 ** Prepare a crude estimate of the logarithm of the input value.
 ** The results need not be exact.  This is only used for estimating
@@ -103454,9 +104137,7 @@ static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
 /* 
 ** Required because bestIndex() is called by bestOrClauseIndex() 
 */
-static void bestIndex(
-    Parse*, WhereClause*, struct SrcList_item*,
-    Bitmask, Bitmask, ExprList*, WhereCost*);
+static void bestIndex(WhereBestIdx*);
 
 /*
 ** This routine attempts to find an scanning strategy that can be used 
@@ -103465,20 +104146,14 @@ static void bestIndex(
 ** The table associated with FROM clause term pSrc may be either a
 ** regular B-Tree table or a virtual table.
 */
-static void bestOrClauseIndex(
-  Parse *pParse,              /* The parsing context */
-  WhereClause *pWC,           /* The WHERE clause */
-  struct SrcList_item *pSrc,  /* The FROM clause term to search */
-  Bitmask notReady,           /* Mask of cursors not available for indexing */
-  Bitmask notValid,           /* Cursors not available for any purpose */
-  ExprList *pOrderBy,         /* The ORDER BY clause */
-  WhereCost *pCost            /* Lowest cost query plan */
-){
+static void bestOrClauseIndex(WhereBestIdx *p){
 #ifndef SQLITE_OMIT_OR_OPTIMIZATION
-  const int iCur = pSrc->iCursor;   /* The cursor of the table to be accessed */
+  WhereClause *pWC = p->pWC;           /* The WHERE clause */
+  struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
+  const int iCur = pSrc->iCursor;      /* The cursor of the table  */
   const Bitmask maskSrc = getMask(pWC->pMaskSet, iCur);  /* Bitmask for pSrc */
   WhereTerm * const pWCEnd = &pWC->a[pWC->nTerm];        /* End of pWC->a[] */
-  WhereTerm *pTerm;                 /* A single term of the WHERE clause */
+  WhereTerm *pTerm;                    /* A single term of the WHERE clause */
 
   /* The OR-clause optimization is disallowed if the INDEXED BY or
   ** NOT INDEXED clauses are used or if the WHERE_AND_ONLY bit is set. */
@@ -103492,7 +104167,7 @@ static void bestOrClauseIndex(
   /* Search the WHERE clause terms for a usable WO_OR term. */
   for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
     if( pTerm->eOperator==WO_OR 
-     && ((pTerm->prereqAll & ~maskSrc) & notReady)==0
+     && ((pTerm->prereqAll & ~maskSrc) & p->notReady)==0
      && (pTerm->u.pOrInfo->indexable & maskSrc)!=0 
     ){
       WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
@@ -103502,15 +104177,19 @@ static void bestOrClauseIndex(
       double rTotal = 0;
       double nRow = 0;
       Bitmask used = 0;
+      WhereBestIdx sBOI;
 
+      sBOI = *p;
+      sBOI.pOrderBy = 0;
+      sBOI.pDistinct = 0;
+      sBOI.ppIdxInfo = 0;
       for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
-        WhereCost sTermCost;
         WHERETRACE(("... Multi-index OR testing for term %d of %d....\n", 
           (pOrTerm - pOrWC->a), (pTerm - pWC->a)
         ));
         if( pOrTerm->eOperator==WO_AND ){
-          WhereClause *pAndWC = &pOrTerm->u.pAndInfo->wc;
-          bestIndex(pParse, pAndWC, pSrc, notReady, notValid, 0, &sTermCost);
+          sBOI.pWC = &pOrTerm->u.pAndInfo->wc;
+          bestIndex(&sBOI);
         }else if( pOrTerm->leftCursor==iCur ){
           WhereClause tempWC;
           tempWC.pParse = pWC->pParse;
@@ -103520,19 +104199,20 @@ static void bestOrClauseIndex(
           tempWC.a = pOrTerm;
           tempWC.wctrlFlags = 0;
           tempWC.nTerm = 1;
-          bestIndex(pParse, &tempWC, pSrc, notReady, notValid, 0, &sTermCost);
+          sBOI.pWC = &tempWC;
+          bestIndex(&sBOI);
         }else{
           continue;
         }
-        rTotal += sTermCost.rCost;
-        nRow += sTermCost.plan.nRow;
-        used |= sTermCost.used;
-        if( rTotal>=pCost->rCost ) break;
+        rTotal += sBOI.cost.rCost;
+        nRow += sBOI.cost.plan.nRow;
+        used |= sBOI.cost.used;
+        if( rTotal>=p->cost.rCost ) break;
       }
 
       /* If there is an ORDER BY clause, increase the scan cost to account 
       ** for the cost of the sort. */
-      if( pOrderBy!=0 ){
+      if( p->pOrderBy!=0 ){
         WHERETRACE(("... sorting increases OR cost %.9g to %.9g\n",
                     rTotal, rTotal+nRow*estLog(nRow)));
         rTotal += nRow*estLog(nRow);
@@ -103542,12 +104222,13 @@ static void bestOrClauseIndex(
       ** less than the current cost stored in pCost, replace the contents
       ** of pCost. */
       WHERETRACE(("... multi-index OR cost=%.9g nrow=%.9g\n", rTotal, nRow));
-      if( rTotal<pCost->rCost ){
-        pCost->rCost = rTotal;
-        pCost->used = used;
-        pCost->plan.nRow = nRow;
-        pCost->plan.wsFlags = flags;
-        pCost->plan.u.pTerm = pTerm;
+      if( rTotal<p->cost.rCost ){
+        p->cost.rCost = rTotal;
+        p->cost.used = used;
+        p->cost.plan.nRow = nRow;
+        p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0;
+        p->cost.plan.wsFlags = flags;
+        p->cost.plan.u.pTerm = pTerm;
       }
     }
   }
@@ -103584,15 +104265,12 @@ static int termCanDriveIndex(
 ** is taken into account, then alter the query plan to use the
 ** transient index.
 */
-static void bestAutomaticIndex(
-  Parse *pParse,              /* The parsing context */
-  WhereClause *pWC,           /* The WHERE clause */
-  struct SrcList_item *pSrc,  /* The FROM clause term to search */
-  Bitmask notReady,           /* Mask of cursors that are not available */
-  WhereCost *pCost            /* Lowest cost query plan */
-){
-  double nTableRow;           /* Rows in the input table */
-  double logN;                /* log(nTableRow) */
+static void bestAutomaticIndex(WhereBestIdx *p){
+  Parse *pParse = p->pParse;            /* The parsing context */
+  WhereClause *pWC = p->pWC;            /* The WHERE clause */
+  struct SrcList_item *pSrc = p->pSrc;  /* The FROM clause term to search */
+  double nTableRow;                     /* Rows in the input table */
+  double logN;                          /* log(nTableRow) */
   double costTempIdx;         /* per-query cost of the transient index */
   WhereTerm *pTerm;           /* A single term of the WHERE clause */
   WhereTerm *pWCEnd;          /* End of pWC->a[] */
@@ -103606,10 +104284,16 @@ static void bestAutomaticIndex(
     /* Automatic indices are disabled at run-time */
     return;
   }
-  if( (pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)!=0 ){
+  if( (p->cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0
+   && (p->cost.plan.wsFlags & WHERE_COVER_SCAN)==0
+  ){
     /* We already have some kind of index in use for this query. */
     return;
   }
+  if( pSrc->viaCoroutine ){
+    /* Cannot index a co-routine */
+    return;
+  }
   if( pSrc->notIndexed ){
     /* The NOT INDEXED clause appears in the SQL. */
     return;
@@ -103624,7 +104308,7 @@ static void bestAutomaticIndex(
   nTableRow = pTable->nRowEst;
   logN = estLog(nTableRow);
   costTempIdx = 2*logN*(nTableRow/pParse->nQueryLoop + 1);
-  if( costTempIdx>=pCost->rCost ){
+  if( costTempIdx>=p->cost.rCost ){
     /* The cost of creating the transient table would be greater than
     ** doing the full table scan */
     return;
@@ -103633,19 +104317,19 @@ static void bestAutomaticIndex(
   /* Search for any equality comparison term */
   pWCEnd = &pWC->a[pWC->nTerm];
   for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
-    if( termCanDriveIndex(pTerm, pSrc, notReady) ){
+    if( termCanDriveIndex(pTerm, pSrc, p->notReady) ){
       WHERETRACE(("auto-index reduces cost from %.1f to %.1f\n",
-                    pCost->rCost, costTempIdx));
-      pCost->rCost = costTempIdx;
-      pCost->plan.nRow = logN + 1;
-      pCost->plan.wsFlags = WHERE_TEMP_INDEX;
-      pCost->used = pTerm->prereqRight;
+                    p->cost.rCost, costTempIdx));
+      p->cost.rCost = costTempIdx;
+      p->cost.plan.nRow = logN + 1;
+      p->cost.plan.wsFlags = WHERE_TEMP_INDEX;
+      p->cost.used = pTerm->prereqRight;
       break;
     }
   }
 }
 #else
-# define bestAutomaticIndex(A,B,C,D,E)  /* no-op */
+# define bestAutomaticIndex(A)  /* no-op */
 #endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
 
 
@@ -103806,12 +104490,11 @@ static void constructAutomaticIndex(
 ** responsibility of the caller to eventually release the structure
 ** by passing the pointer returned by this function to sqlite3_free().
 */
-static sqlite3_index_info *allocateIndexInfo(
-  Parse *pParse, 
-  WhereClause *pWC,
-  struct SrcList_item *pSrc,
-  ExprList *pOrderBy
-){
+static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
+  Parse *pParse = p->pParse; 
+  WhereClause *pWC = p->pWC;
+  struct SrcList_item *pSrc = p->pSrc;
+  ExprList *pOrderBy = p->pOrderBy;
   int i, j;
   int nTerm;
   struct sqlite3_index_constraint *pIdxCons;
@@ -103841,12 +104524,13 @@ static sqlite3_index_info *allocateIndexInfo(
   */
   nOrderBy = 0;
   if( pOrderBy ){
-    for(i=0; i<pOrderBy->nExpr; i++){
+    int n = pOrderBy->nExpr;
+    for(i=0; i<n; i++){
       Expr *pExpr = pOrderBy->a[i].pExpr;
       if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break;
     }
-    if( i==pOrderBy->nExpr ){
-      nOrderBy = pOrderBy->nExpr;
+    if( i==n){
+      nOrderBy = n;
     }
   }
 
@@ -103970,16 +104654,10 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
 ** routine takes care of freeing the sqlite3_index_info structure after
 ** everybody has finished with it.
 */
-static void bestVirtualIndex(
-  Parse *pParse,                  /* The parsing context */
-  WhereClause *pWC,               /* The WHERE clause */
-  struct SrcList_item *pSrc,      /* The FROM clause term to search */
-  Bitmask notReady,               /* Mask of cursors not available for index */
-  Bitmask notValid,               /* Cursors not valid for any purpose */
-  ExprList *pOrderBy,             /* The order by clause */
-  WhereCost *pCost,               /* Lowest cost query plan */
-  sqlite3_index_info **ppIdxInfo  /* Index information passed to xBestIndex */
-){
+static void bestVirtualIndex(WhereBestIdx *p){
+  Parse *pParse = p->pParse;      /* The parsing context */
+  WhereClause *pWC = p->pWC;      /* The WHERE clause */
+  struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
   Table *pTab = pSrc->pTab;
   sqlite3_index_info *pIdxInfo;
   struct sqlite3_index_constraint *pIdxCons;
@@ -103993,15 +104671,15 @@ static void bestVirtualIndex(
   ** malloc in allocateIndexInfo() fails and this function returns leaving
   ** wsFlags in an uninitialized state, the caller may behave unpredictably.
   */
-  memset(pCost, 0, sizeof(*pCost));
-  pCost->plan.wsFlags = WHERE_VIRTUALTABLE;
+  memset(&p->cost, 0, sizeof(p->cost));
+  p->cost.plan.wsFlags = WHERE_VIRTUALTABLE;
 
   /* If the sqlite3_index_info structure has not been previously
   ** allocated and initialized, then allocate and initialize it now.
   */
-  pIdxInfo = *ppIdxInfo;
+  pIdxInfo = *p->ppIdxInfo;
   if( pIdxInfo==0 ){
-    *ppIdxInfo = pIdxInfo = allocateIndexInfo(pParse, pWC, pSrc, pOrderBy);
+    *p->ppIdxInfo = pIdxInfo = allocateIndexInfo(p);
   }
   if( pIdxInfo==0 ){
     return;
@@ -104046,7 +104724,7 @@ static void bestVirtualIndex(
   for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
     j = pIdxCons->iTermOffset;
     pTerm = &pWC->a[j];
-    pIdxCons->usable = (pTerm->prereqRight&notReady) ? 0 : 1;
+    pIdxCons->usable = (pTerm->prereqRight&p->notReady) ? 0 : 1;
   }
   memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
   if( pIdxInfo->needToFreeIdxStr ){
@@ -104059,7 +104737,7 @@ static void bestVirtualIndex(
   /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */
   pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2);
   nOrderBy = pIdxInfo->nOrderBy;
-  if( !pOrderBy ){
+  if( !p->pOrderBy ){
     pIdxInfo->nOrderBy = 0;
   }
 
@@ -104070,7 +104748,7 @@ static void bestVirtualIndex(
   pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
   for(i=0; i<pIdxInfo->nConstraint; i++){
     if( pUsage[i].argvIndex>0 ){
-      pCost->used |= pWC->a[pIdxCons[i].iTermOffset].prereqRight;
+      p->cost.used |= pWC->a[pIdxCons[i].iTermOffset].prereqRight;
     }
   }
 
@@ -104079,7 +104757,7 @@ static void bestVirtualIndex(
   ** matches the processing for non-virtual tables in bestBtreeIndex().
   */
   rCost = pIdxInfo->estimatedCost;
-  if( pOrderBy && pIdxInfo->orderByConsumed==0 ){
+  if( p->pOrderBy && pIdxInfo->orderByConsumed==0 ){
     rCost += estLog(rCost)*rCost;
   }
 
@@ -104091,21 +104769,24 @@ static void bestVirtualIndex(
   ** is defined.
   */
   if( (SQLITE_BIG_DBL/((double)2))<rCost ){
-    pCost->rCost = (SQLITE_BIG_DBL/((double)2));
+    p->cost.rCost = (SQLITE_BIG_DBL/((double)2));
   }else{
-    pCost->rCost = rCost;
+    p->cost.rCost = rCost;
   }
-  pCost->plan.u.pVtabIdx = pIdxInfo;
+  p->cost.plan.u.pVtabIdx = pIdxInfo;
   if( pIdxInfo->orderByConsumed ){
-    pCost->plan.wsFlags |= WHERE_ORDERBY;
+    p->cost.plan.wsFlags |= WHERE_ORDERED;
+    p->cost.plan.nOBSat = nOrderBy;
+  }else{
+    p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0;
   }
-  pCost->plan.nEq = 0;
+  p->cost.plan.nEq = 0;
   pIdxInfo->nOrderBy = nOrderBy;
 
   /* Try to find a more efficient access pattern by using multiple indexes
   ** to optimize an OR expression within the WHERE clause. 
   */
-  bestOrClauseIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
+  bestOrClauseIndex(p);
 }
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
 
@@ -104193,10 +104874,8 @@ static int whereKeyStats(
         pColl = db->pDfltColl;
         assert( pColl->enc==SQLITE_UTF8 );
       }else{
-        pColl = sqlite3GetCollSeq(db, SQLITE_UTF8, 0, *pIdx->azColl);
+        pColl = sqlite3GetCollSeq(pParse, SQLITE_UTF8, 0, *pIdx->azColl);
         if( pColl==0 ){
-          sqlite3ErrorMsg(pParse, "no such collation sequence: %s",
-                          *pIdx->azColl);
           return SQLITE_ERROR;
         }
         z = (const u8 *)sqlite3ValueText(pVal, pColl->enc);
@@ -104504,11 +105183,275 @@ static int whereInScanEst(
 }
 #endif /* defined(SQLITE_ENABLE_STAT3) */
 
+/*
+** Check to see if column iCol of the table with cursor iTab will appear
+** in sorted order according to the current query plan.
+**
+** Return values:
+**
+**    0   iCol is not ordered
+**    1   iCol has only a single value
+**    2   iCol is in ASC order
+**    3   iCol is in DESC order
+*/
+static int isOrderedColumn(
+  WhereBestIdx *p,
+  int iTab,
+  int iCol
+){
+  int i, j;
+  WhereLevel *pLevel = &p->aLevel[p->i-1];
+  Index *pIdx;
+  u8 sortOrder;
+  for(i=p->i-1; i>=0; i--, pLevel--){
+    if( pLevel->iTabCur!=iTab ) continue;
+    if( (pLevel->plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
+      return 1;
+    }
+    assert( (pLevel->plan.wsFlags & WHERE_ORDERED)!=0 );
+    if( (pIdx = pLevel->plan.u.pIdx)!=0 ){
+      if( iCol<0 ){
+        sortOrder = 0;
+        testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
+      }else{
+        int n = pIdx->nColumn;
+        for(j=0; j<n; j++){
+          if( iCol==pIdx->aiColumn[j] ) break;
+        }
+        if( j>=n ) return 0;
+        sortOrder = pIdx->aSortOrder[j];
+        testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
+      }
+    }else{
+      if( iCol!=(-1) ) return 0;
+      sortOrder = 0;
+      testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
+    }
+    if( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ){
+      assert( sortOrder==0 || sortOrder==1 );
+      testcase( sortOrder==1 );
+      sortOrder = 1 - sortOrder;
+    }
+    return sortOrder+2;
+  }
+  return 0;
+}
+
+/*
+** This routine decides if pIdx can be used to satisfy the ORDER BY
+** clause, either in whole or in part.  The return value is the 
+** cumulative number of terms in the ORDER BY clause that are satisfied
+** by the index pIdx and other indices in outer loops.
+**
+** The table being queried has a cursor number of "base".  pIdx is the
+** index that is postulated for use to access the table.
+**
+** The *pbRev value is set to 0 order 1 depending on whether or not
+** pIdx should be run in the forward order or in reverse order.
+*/
+static int isSortingIndex(
+  WhereBestIdx *p,    /* Best index search context */
+  Index *pIdx,        /* The index we are testing */
+  int base,           /* Cursor number for the table to be sorted */
+  int *pbRev          /* Set to 1 for reverse-order scan of pIdx */
+){
+  int i;                        /* Number of pIdx terms used */
+  int j;                        /* Number of ORDER BY terms satisfied */
+  int sortOrder = 2;            /* 0: forward.  1: backward.  2: unknown */
+  int nTerm;                    /* Number of ORDER BY terms */
+  struct ExprList_item *pOBItem;/* A term of the ORDER BY clause */
+  Table *pTab = pIdx->pTable;   /* Table that owns index pIdx */
+  ExprList *pOrderBy;           /* The ORDER BY clause */
+  Parse *pParse = p->pParse;    /* Parser context */
+  sqlite3 *db = pParse->db;     /* Database connection */
+  int nPriorSat;                /* ORDER BY terms satisfied by outer loops */
+  int seenRowid = 0;            /* True if an ORDER BY rowid term is seen */
+  int uniqueNotNull;            /* pIdx is UNIQUE with all terms are NOT NULL */
+
+  if( p->i==0 ){
+    nPriorSat = 0;
+  }else{
+    nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
+    if( (p->aLevel[p->i-1].plan.wsFlags & WHERE_ORDERED)==0 ){
+      /* This loop cannot be ordered unless the next outer loop is
+      ** also ordered */
+      return nPriorSat;
+    }
+    if( OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ){
+      /* Only look at the outer-most loop if the OrderByIdxJoin
+      ** optimization is disabled */
+      return nPriorSat;
+    }
+  }
+  pOrderBy = p->pOrderBy;
+  assert( pOrderBy!=0 );
+  if( pIdx->bUnordered ){
+    /* Hash indices (indicated by the "unordered" tag on sqlite_stat1) cannot
+    ** be used for sorting */
+    return nPriorSat;
+  }
+  nTerm = pOrderBy->nExpr;
+  uniqueNotNull = pIdx->onError!=OE_None;
+  assert( nTerm>0 );
+
+  /* Argument pIdx must either point to a 'real' named index structure, 
+  ** or an index structure allocated on the stack by bestBtreeIndex() to
+  ** represent the rowid index that is part of every table.  */
+  assert( pIdx->zName || (pIdx->nColumn==1 && pIdx->aiColumn[0]==-1) );
+
+  /* Match terms of the ORDER BY clause against columns of
+  ** the index.
+  **
+  ** Note that indices have pIdx->nColumn regular columns plus
+  ** one additional column containing the rowid.  The rowid column
+  ** of the index is also allowed to match against the ORDER BY
+  ** clause.
+  */
+  j = nPriorSat;
+  for(i=0,pOBItem=&pOrderBy->a[j]; j<nTerm && i<=pIdx->nColumn; i++){
+    Expr *pOBExpr;          /* The expression of the ORDER BY pOBItem */
+    CollSeq *pColl;         /* The collating sequence of pOBExpr */
+    int termSortOrder;      /* Sort order for this term */
+    int iColumn;            /* The i-th column of the index.  -1 for rowid */
+    int iSortOrder;         /* 1 for DESC, 0 for ASC on the i-th index term */
+    int isEq;               /* Subject to an == or IS NULL constraint */
+    int isMatch;            /* ORDER BY term matches the index term */
+    const char *zColl;      /* Name of collating sequence for i-th index term */
+    WhereTerm *pConstraint; /* A constraint in the WHERE clause */
+
+    /* If the next term of the ORDER BY clause refers to anything other than
+    ** a column in the "base" table, then this index will not be of any
+    ** further use in handling the ORDER BY. */
+    pOBExpr = sqlite3ExprSkipCollate(pOBItem->pExpr);
+    if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){
+      break;
+    }
+
+    /* Find column number and collating sequence for the next entry
+    ** in the index */
+    if( pIdx->zName && i<pIdx->nColumn ){
+      iColumn = pIdx->aiColumn[i];
+      if( iColumn==pIdx->pTable->iPKey ){
+        iColumn = -1;
+      }
+      iSortOrder = pIdx->aSortOrder[i];
+      zColl = pIdx->azColl[i];
+      assert( zColl!=0 );
+    }else{
+      iColumn = -1;
+      iSortOrder = 0;
+      zColl = 0;
+    }
+
+    /* Check to see if the column number and collating sequence of the
+    ** index match the column number and collating sequence of the ORDER BY
+    ** clause entry.  Set isMatch to 1 if they both match. */
+    if( pOBExpr->iColumn==iColumn ){
+      if( zColl ){
+        pColl = sqlite3ExprCollSeq(pParse, pOBItem->pExpr);
+        if( !pColl ) pColl = db->pDfltColl;
+        isMatch = sqlite3StrICmp(pColl->zName, zColl)==0;
+      }else{
+        isMatch = 1;
+      }
+    }else{
+      isMatch = 0;
+    }
+
+    /* termSortOrder is 0 or 1 for whether or not the access loop should
+    ** run forward or backwards (respectively) in order to satisfy this 
+    ** term of the ORDER BY clause. */
+    assert( pOBItem->sortOrder==0 || pOBItem->sortOrder==1 );
+    assert( iSortOrder==0 || iSortOrder==1 );
+    termSortOrder = iSortOrder ^ pOBItem->sortOrder;
+
+    /* If X is the column in the index and ORDER BY clause, check to see
+    ** if there are any X= or X IS NULL constraints in the WHERE clause. */
+    pConstraint = findTerm(p->pWC, base, iColumn, p->notReady,
+                           WO_EQ|WO_ISNULL|WO_IN, pIdx);
+    if( pConstraint==0 ){
+      isEq = 0;
+    }else if( pConstraint->eOperator==WO_IN ){
+      /* Constraints of the form: "X IN ..." cannot be used with an ORDER BY
+      ** because we do not know in what order the values on the RHS of the IN
+      ** operator will occur. */
+      break;
+    }else if( pConstraint->eOperator==WO_ISNULL ){
+      uniqueNotNull = 0;
+      isEq = 1;  /* "X IS NULL" means X has only a single value */
+    }else if( pConstraint->prereqRight==0 ){
+      isEq = 1;  /* Constraint "X=constant" means X has only a single value */
+    }else{
+      Expr *pRight = pConstraint->pExpr->pRight;
+      if( pRight->op==TK_COLUMN ){
+        WHERETRACE(("       .. isOrderedColumn(tab=%d,col=%d)",
+                    pRight->iTable, pRight->iColumn));
+        isEq = isOrderedColumn(p, pRight->iTable, pRight->iColumn);
+        WHERETRACE((" -> isEq=%d\n", isEq));
+
+        /* If the constraint is of the form X=Y where Y is an ordered value
+        ** in an outer loop, then make sure the sort order of Y matches the
+        ** sort order required for X. */
+        if( isMatch && isEq>=2 && isEq!=pOBItem->sortOrder+2 ){
+          testcase( isEq==2 );
+          testcase( isEq==3 );
+          break;
+        }
+      }else{
+        isEq = 0;  /* "X=expr" places no ordering constraints on X */
+      }
+    }
+    if( !isMatch ){
+      if( isEq==0 ){
+        break;
+      }else{
+        continue;
+      }
+    }else if( isEq!=1 ){
+      if( sortOrder==2 ){
+        sortOrder = termSortOrder;
+      }else if( termSortOrder!=sortOrder ){
+        break;
+      }
+    }
+    j++;
+    pOBItem++;
+    if( iColumn<0 ){
+      seenRowid = 1;
+      break;
+    }else if( pTab->aCol[iColumn].notNull==0 && isEq!=1 ){
+      testcase( isEq==0 );
+      testcase( isEq==2 );
+      testcase( isEq==3 );
+      uniqueNotNull = 0;
+    }
+  }
+
+  /* If we have not found at least one ORDER BY term that matches the
+  ** index, then show no progress. */
+  if( pOBItem==&pOrderBy->a[nPriorSat] ) return nPriorSat;
+
+  /* Return the necessary scan order back to the caller */
+  *pbRev = sortOrder & 1;
+
+  /* If there was an "ORDER BY rowid" term that matched, or it is only
+  ** possible for a single row from this table to match, then skip over
+  ** any additional ORDER BY terms dealing with this table.
+  */
+  if( seenRowid || (uniqueNotNull && i>=pIdx->nColumn) ){
+    /* Advance j over additional ORDER BY terms associated with base */
+    WhereMaskSet *pMS = p->pWC->pMaskSet;
+    Bitmask m = ~getMask(pMS, base);
+    while( j<nTerm && (exprTableUsage(pMS, pOrderBy->a[j].pExpr)&m)==0 ){
+      j++;
+    }
+  }
+  return j;
+}
 
 /*
 ** Find the best query plan for accessing a particular table.  Write the
-** best query plan and its cost into the WhereCost object supplied as the
-** last parameter.
+** best query plan and its cost into the p->cost.
 **
 ** The lowest cost plan wins.  The cost is an estimate of the amount of
 ** CPU and disk I/O needed to process the requested result.
@@ -104528,21 +105471,15 @@ static int whereInScanEst(
 ** SQLITE_BIG_DBL. If a plan is found that uses the named index, 
 ** then the cost is calculated in the usual way.
 **
-** If a NOT INDEXED clause (pSrc->notIndexed!=0) was attached to the table 
+** If a NOT INDEXED clause was attached to the table 
 ** in the SELECT statement, then no indexes are considered. However, the 
 ** selected plan may still take advantage of the built-in rowid primary key
 ** index.
 */
-static void bestBtreeIndex(
-  Parse *pParse,              /* The parsing context */
-  WhereClause *pWC,           /* The WHERE clause */
-  struct SrcList_item *pSrc,  /* The FROM clause term to search */
-  Bitmask notReady,           /* Mask of cursors not available for indexing */
-  Bitmask notValid,           /* Cursors not available for any purpose */
-  ExprList *pOrderBy,         /* The ORDER BY clause */
-  ExprList *pDistinct,        /* The select-list if query is DISTINCT */
-  WhereCost *pCost            /* Lowest cost query plan */
-){
+static void bestBtreeIndex(WhereBestIdx *p){
+  Parse *pParse = p->pParse;  /* The parsing context */
+  WhereClause *pWC = p->pWC;  /* The WHERE clause */
+  struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
   int iCur = pSrc->iCursor;   /* The cursor of the table to be accessed */
   Index *pProbe;              /* An index we are evaluating */
   Index *pIdx;                /* Copy of pProbe, or zero for IPK index */
@@ -104551,11 +105488,16 @@ static void bestBtreeIndex(
   Index sPk;                  /* A fake index object for the primary key */
   tRowcnt aiRowEstPk[2];      /* The aiRowEst[] value for the sPk index */
   int aiColumnPk = -1;        /* The aColumn[] value for the sPk index */
-  int wsFlagMask;             /* Allowed flags in pCost->plan.wsFlag */
+  int wsFlagMask;             /* Allowed flags in p->cost.plan.wsFlag */
+  int nPriorSat;              /* ORDER BY terms satisfied by outer loops */
+  int nOrderBy;               /* Number of ORDER BY terms */
+  char bSortInit;             /* Initializer for bSort in inner loop */
+  char bDistInit;             /* Initializer for bDist in inner loop */
+
 
   /* Initialize the cost to a worst-case value */
-  memset(pCost, 0, sizeof(*pCost));
-  pCost->rCost = SQLITE_BIG_DBL;
+  memset(&p->cost, 0, sizeof(p->cost));
+  p->cost.rCost = SQLITE_BIG_DBL;
 
   /* If the pSrc table is the right table of a LEFT JOIN then we may not
   ** use an index to satisfy IS NULL constraints on that table.  This is
@@ -104601,22 +105543,29 @@ static void bestBtreeIndex(
     pIdx = 0;
   }
 
+  nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0;
+  if( p->i ){
+    nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
+    bSortInit = nPriorSat<nOrderBy;
+    bDistInit = 0;
+  }else{
+    nPriorSat = 0;
+    bSortInit = nOrderBy>0;
+    bDistInit = p->pDistinct!=0;
+  }
+
   /* Loop over all indices looking for the best one to use
   */
   for(; pProbe; pIdx=pProbe=pProbe->pNext){
     const tRowcnt * const aiRowEst = pProbe->aiRowEst;
-    double cost;                /* Cost of using pProbe */
-    double nRow;                /* Estimated number of rows in result set */
+    WhereCost pc;               /* Cost of using pProbe */
     double log10N = (double)1;  /* base-10 logarithm of nRow (inexact) */
-    int rev;                    /* True to scan in reverse order */
-    int wsFlags = 0;
-    Bitmask used = 0;
 
     /* The following variables are populated based on the properties of
     ** index being evaluated. They are then used to determine the expected
     ** cost and number of rows returned.
     **
-    **  nEq: 
+    **  pc.plan.nEq: 
     **    Number of equality terms that can be implemented using the index.
     **    In other words, the number of initial fields in the index that
     **    are used in == or IN or NOT NULL constraints of the WHERE clause.
@@ -104659,6 +105608,10 @@ static void bestBtreeIndex(
     **    external sort (i.e. scanning the index being evaluated will not 
     **    correctly order records).
     **
+    **  bDist:
+    **    Boolean. True if there is a DISTINCT clause that will require an 
+    **    external btree.
+    **
     **  bLookup: 
     **    Boolean. True if a table lookup is required for each index entry
     **    visited.  In other words, true if this is not a covering index.
@@ -104674,29 +105627,35 @@ static void bestBtreeIndex(
     **             SELECT a, b    FROM tbl WHERE a = 1;
     **             SELECT a, b, c FROM tbl WHERE a = 1;
     */
-    int nEq;                      /* Number of == or IN terms matching index */
     int bInEst = 0;               /* True if "x IN (SELECT...)" seen */
     int nInMul = 1;               /* Number of distinct equalities to lookup */
     double rangeDiv = (double)1;  /* Estimated reduction in search space */
     int nBound = 0;               /* Number of range constraints seen */
-    int bSort = !!pOrderBy;       /* True if external sort required */
-    int bDist = !!pDistinct;      /* True if index cannot help with DISTINCT */
-    int bLookup = 0;              /* True if not a covering index */
+    char bSort = bSortInit;       /* True if external sort required */
+    char bDist = bDistInit;       /* True if index cannot help with DISTINCT */
+    char bLookup = 0;             /* True if not a covering index */
     WhereTerm *pTerm;             /* A single term of the WHERE clause */
 #ifdef SQLITE_ENABLE_STAT3
     WhereTerm *pFirstTerm = 0;    /* First term matching the index */
 #endif
 
-    /* Determine the values of nEq and nInMul */
-    for(nEq=0; nEq<pProbe->nColumn; nEq++){
-      int j = pProbe->aiColumn[nEq];
-      pTerm = findTerm(pWC, iCur, j, notReady, eqTermMask, pIdx);
+    WHERETRACE((
+      "   %s(%s):\n",
+      pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk")
+    ));
+    memset(&pc, 0, sizeof(pc));
+    pc.plan.nOBSat = nPriorSat;
+
+    /* Determine the values of pc.plan.nEq and nInMul */
+    for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){
+      int j = pProbe->aiColumn[pc.plan.nEq];
+      pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx);
       if( pTerm==0 ) break;
-      wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ);
+      pc.plan.wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ);
       testcase( pTerm->pWC!=pWC );
       if( pTerm->eOperator & WO_IN ){
         Expr *pExpr = pTerm->pExpr;
-        wsFlags |= WHERE_COLUMN_IN;
+        pc.plan.wsFlags |= WHERE_COLUMN_IN;
         if( ExprHasProperty(pExpr, EP_xIsSelect) ){
           /* "x IN (SELECT ...)":  Assume the SELECT returns 25 rows */
           nInMul *= 25;
@@ -104706,12 +105665,12 @@ static void bestBtreeIndex(
           nInMul *= pExpr->x.pList->nExpr;
         }
       }else if( pTerm->eOperator & WO_ISNULL ){
-        wsFlags |= WHERE_COLUMN_NULL;
+        pc.plan.wsFlags |= WHERE_COLUMN_NULL;
       }
 #ifdef SQLITE_ENABLE_STAT3
-      if( nEq==0 && pProbe->aSample ) pFirstTerm = pTerm;
+      if( pc.plan.nEq==0 && pProbe->aSample ) pFirstTerm = pTerm;
 #endif
-      used |= pTerm->prereqRight;
+      pc.used |= pTerm->prereqRight;
     }
  
     /* If the index being considered is UNIQUE, and there is an equality 
@@ -104720,65 +105679,80 @@ static void bestBtreeIndex(
     ** indicate this to the caller.
     **
     ** Otherwise, if the search may find more than one row, test to see if
-    ** there is a range constraint on indexed column (nEq+1) that can be 
+    ** there is a range constraint on indexed column (pc.plan.nEq+1) that can be 
     ** optimized using the index. 
     */
-    if( nEq==pProbe->nColumn && pProbe->onError!=OE_None ){
-      testcase( wsFlags & WHERE_COLUMN_IN );
-      testcase( wsFlags & WHERE_COLUMN_NULL );
-      if( (wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){
-        wsFlags |= WHERE_UNIQUE;
+    if( pc.plan.nEq==pProbe->nColumn && pProbe->onError!=OE_None ){
+      testcase( pc.plan.wsFlags & WHERE_COLUMN_IN );
+      testcase( pc.plan.wsFlags & WHERE_COLUMN_NULL );
+      if( (pc.plan.wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){
+        pc.plan.wsFlags |= WHERE_UNIQUE;
+        if( p->i==0 || (p->aLevel[p->i-1].plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
+          pc.plan.wsFlags |= WHERE_ALL_UNIQUE;
+        }
       }
     }else if( pProbe->bUnordered==0 ){
-      int j = (nEq==pProbe->nColumn ? -1 : pProbe->aiColumn[nEq]);
-      if( findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){
-        WhereTerm *pTop = findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE, pIdx);
-        WhereTerm *pBtm = findTerm(pWC, iCur, j, notReady, WO_GT|WO_GE, pIdx);
-        whereRangeScanEst(pParse, pProbe, nEq, pBtm, pTop, &rangeDiv);
+      int j;
+      j = (pc.plan.nEq==pProbe->nColumn ? -1 : pProbe->aiColumn[pc.plan.nEq]);
+      if( findTerm(pWC, iCur, j, p->notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){
+        WhereTerm *pTop, *pBtm;
+        pTop = findTerm(pWC, iCur, j, p->notReady, WO_LT|WO_LE, pIdx);
+        pBtm = findTerm(pWC, iCur, j, p->notReady, WO_GT|WO_GE, pIdx);
+        whereRangeScanEst(pParse, pProbe, pc.plan.nEq, pBtm, pTop, &rangeDiv);
         if( pTop ){
           nBound = 1;
-          wsFlags |= WHERE_TOP_LIMIT;
-          used |= pTop->prereqRight;
+          pc.plan.wsFlags |= WHERE_TOP_LIMIT;
+          pc.used |= pTop->prereqRight;
           testcase( pTop->pWC!=pWC );
         }
         if( pBtm ){
           nBound++;
-          wsFlags |= WHERE_BTM_LIMIT;
-          used |= pBtm->prereqRight;
+          pc.plan.wsFlags |= WHERE_BTM_LIMIT;
+          pc.used |= pBtm->prereqRight;
           testcase( pBtm->pWC!=pWC );
         }
-        wsFlags |= (WHERE_COLUMN_RANGE|WHERE_ROWID_RANGE);
+        pc.plan.wsFlags |= (WHERE_COLUMN_RANGE|WHERE_ROWID_RANGE);
       }
     }
 
     /* If there is an ORDER BY clause and the index being considered will
     ** naturally scan rows in the required order, set the appropriate flags
-    ** in wsFlags. Otherwise, if there is an ORDER BY clause but the index
-    ** will scan rows in a different order, set the bSort variable.  */
-    if( isSortingIndex(
-          pParse, pWC->pMaskSet, pProbe, iCur, pOrderBy, nEq, wsFlags, &rev)
-    ){
-      bSort = 0;
-      wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_ORDERBY;
-      wsFlags |= (rev ? WHERE_REVERSE : 0);
+    ** in pc.plan.wsFlags. Otherwise, if there is an ORDER BY clause but
+    ** the index will scan rows in a different order, set the bSort
+    ** variable.  */
+    if( bSort && (pSrc->jointype & JT_LEFT)==0 ){
+      int bRev = 2;
+      WHERETRACE(("      --> before isSortingIndex: nPriorSat=%d\n",nPriorSat));
+      pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev);
+      WHERETRACE(("      --> after  isSortingIndex: bRev=%d nOBSat=%d\n",
+                  bRev, pc.plan.nOBSat));
+      if( nPriorSat<pc.plan.nOBSat || (pc.plan.wsFlags & WHERE_UNIQUE)!=0 ){
+        pc.plan.wsFlags |= WHERE_ORDERED;
+      }
+      if( nOrderBy==pc.plan.nOBSat ){
+        bSort = 0;
+        pc.plan.wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE;
+      }
+      if( bRev & 1 ) pc.plan.wsFlags |= WHERE_REVERSE;
     }
 
     /* If there is a DISTINCT qualifier and this index will scan rows in
     ** order of the DISTINCT expressions, clear bDist and set the appropriate
-    ** flags in wsFlags. */
-    if( isDistinctIndex(pParse, pWC, pProbe, iCur, pDistinct, nEq)
-     && (wsFlags & WHERE_COLUMN_IN)==0
+    ** flags in pc.plan.wsFlags. */
+    if( bDist
+     && isDistinctIndex(pParse, pWC, pProbe, iCur, p->pDistinct, pc.plan.nEq)
+     && (pc.plan.wsFlags & WHERE_COLUMN_IN)==0
     ){
       bDist = 0;
-      wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT;
+      pc.plan.wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT;
     }
 
     /* If currently calculating the cost of using an index (not the IPK
     ** index), determine if all required column data may be obtained without 
     ** using the main table (i.e. if the index is a covering
     ** index for this query). If it is, set the WHERE_IDX_ONLY flag in
-    ** wsFlags. Otherwise, set the bLookup variable to true.  */
-    if( pIdx && wsFlags ){
+    ** pc.plan.wsFlags. Otherwise, set the bLookup variable to true.  */
+    if( pIdx ){
       Bitmask m = pSrc->colUsed;
       int j;
       for(j=0; j<pIdx->nColumn; j++){
@@ -104788,7 +105762,7 @@ static void bestBtreeIndex(
         }
       }
       if( m==0 ){
-        wsFlags |= WHERE_IDX_ONLY;
+        pc.plan.wsFlags |= WHERE_IDX_ONLY;
       }else{
         bLookup = 1;
       }
@@ -104798,10 +105772,10 @@ static void bestBtreeIndex(
     ** Estimate the number of rows of output.  For an "x IN (SELECT...)"
     ** constraint, do not let the estimate exceed half the rows in the table.
     */
-    nRow = (double)(aiRowEst[nEq] * nInMul);
-    if( bInEst && nRow*2>aiRowEst[0] ){
-      nRow = aiRowEst[0]/2;
-      nInMul = (int)(nRow / aiRowEst[nEq]);
+    pc.plan.nRow = (double)(aiRowEst[pc.plan.nEq] * nInMul);
+    if( bInEst && pc.plan.nRow*2>aiRowEst[0] ){
+      pc.plan.nRow = aiRowEst[0]/2;
+      nInMul = (int)(pc.plan.nRow / aiRowEst[pc.plan.nEq]);
     }
 
 #ifdef SQLITE_ENABLE_STAT3
@@ -104811,15 +105785,18 @@ static void bestBtreeIndex(
     ** to get a better estimate on the number of rows based on
     ** VALUE and how common that value is according to the histogram.
     */
-    if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 && aiRowEst[1]>1 ){
+    if( pc.plan.nRow>(double)1 && pc.plan.nEq==1
+     && pFirstTerm!=0 && aiRowEst[1]>1 ){
       assert( (pFirstTerm->eOperator & (WO_EQ|WO_ISNULL|WO_IN))!=0 );
       if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
         testcase( pFirstTerm->eOperator==WO_EQ );
         testcase( pFirstTerm->eOperator==WO_ISNULL );
-        whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, &nRow);
+        whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight,
+                          &pc.plan.nRow);
       }else if( bInEst==0 ){
         assert( pFirstTerm->eOperator==WO_IN );
-        whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList, &nRow);
+        whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList,
+                       &pc.plan.nRow);
       }
     }
 #endif /* SQLITE_ENABLE_STAT3 */
@@ -104827,8 +105804,8 @@ static void bestBtreeIndex(
     /* Adjust the number of output rows and downward to reflect rows
     ** that are excluded by range constraints.
     */
-    nRow = nRow/rangeDiv;
-    if( nRow<1 ) nRow = 1;
+    pc.plan.nRow = pc.plan.nRow/rangeDiv;
+    if( pc.plan.nRow<1 ) pc.plan.nRow = 1;
 
     /* Experiments run on real SQLite databases show that the time needed
     ** to do a binary search to locate a row in a table or index is roughly
@@ -104843,7 +105820,18 @@ static void bestBtreeIndex(
     ** So this computation assumes table records are about twice as big
     ** as index records
     */
-    if( (wsFlags & WHERE_NOT_FULLSCAN)==0 ){
+    if( (pc.plan.wsFlags&~(WHERE_REVERSE|WHERE_ORDERED))==WHERE_IDX_ONLY
+     && (pWC->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
+     && sqlite3GlobalConfig.bUseCis
+     && OptimizationEnabled(pParse->db, SQLITE_CoverIdxScan)
+    ){
+      /* This index is not useful for indexing, but it is a covering index.
+      ** A full-scan of the index might be a little faster than a full-scan
+      ** of the table, so give this case a cost slightly less than a table
+      ** scan. */
+      pc.rCost = aiRowEst[0]*3 + pProbe->nColumn;
+      pc.plan.wsFlags |= WHERE_COVER_SCAN|WHERE_COLUMN_RANGE;
+    }else if( (pc.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
       /* The cost of a full table scan is a number of move operations equal
       ** to the number of rows in the table.
       **
@@ -104853,10 +105841,15 @@ static void bestBtreeIndex(
       ** decision and one which we expect to revisit in the future.  But
       ** it seems to be working well enough at the moment.
       */
-      cost = aiRowEst[0]*4;
+      pc.rCost = aiRowEst[0]*4;
+      pc.plan.wsFlags &= ~WHERE_IDX_ONLY;
+      if( pIdx ){
+        pc.plan.wsFlags &= ~WHERE_ORDERED;
+        pc.plan.nOBSat = nPriorSat;
+      }
     }else{
       log10N = estLog(aiRowEst[0]);
-      cost = nRow;
+      pc.rCost = pc.plan.nRow;
       if( pIdx ){
         if( bLookup ){
           /* For an index lookup followed by a table lookup:
@@ -104864,20 +105857,20 @@ static void bestBtreeIndex(
           **  + nRow steps through the index
           **  + nRow table searches to lookup the table entry using the rowid
           */
-          cost += (nInMul + nRow)*log10N;
+          pc.rCost += (nInMul + pc.plan.nRow)*log10N;
         }else{
           /* For a covering index:
           **     nInMul index searches to find the initial entry 
           **   + nRow steps through the index
           */
-          cost += nInMul*log10N;
+          pc.rCost += nInMul*log10N;
         }
       }else{
         /* For a rowid primary key lookup:
         **    nInMult table searches to find the initial entry for each range
         **  + nRow steps through the table
         */
-        cost += nInMul*log10N;
+        pc.rCost += nInMul*log10N;
       }
     }
 
@@ -104888,10 +105881,12 @@ static void bestBtreeIndex(
     ** difference and select C of 3.0.
     */
     if( bSort ){
-      cost += nRow*estLog(nRow)*3;
+      double m = estLog(pc.plan.nRow*(nOrderBy - pc.plan.nOBSat)/nOrderBy);
+      m *= (double)(pc.plan.nOBSat ? 2 : 3);
+      pc.rCost += pc.plan.nRow*m;
     }
     if( bDist ){
-      cost += nRow*estLog(nRow)*3;
+      pc.rCost += pc.plan.nRow*estLog(pc.plan.nRow)*3;
     }
 
     /**** Cost of using this index has now been computed ****/
@@ -104912,25 +105907,25 @@ static void bestBtreeIndex(
     ** might be selected even when there exists an optimal index that has
     ** no such dependency.
     */
-    if( nRow>2 && cost<=pCost->rCost ){
+    if( pc.plan.nRow>2 && pc.rCost<=p->cost.rCost ){
       int k;                       /* Loop counter */
-      int nSkipEq = nEq;           /* Number of == constraints to skip */
+      int nSkipEq = pc.plan.nEq;   /* Number of == constraints to skip */
       int nSkipRange = nBound;     /* Number of < constraints to skip */
       Bitmask thisTab;             /* Bitmap for pSrc */
 
       thisTab = getMask(pWC->pMaskSet, iCur);
-      for(pTerm=pWC->a, k=pWC->nTerm; nRow>2 && k; k--, pTerm++){
+      for(pTerm=pWC->a, k=pWC->nTerm; pc.plan.nRow>2 && k; k--, pTerm++){
         if( pTerm->wtFlags & TERM_VIRTUAL ) continue;
-        if( (pTerm->prereqAll & notValid)!=thisTab ) continue;
+        if( (pTerm->prereqAll & p->notValid)!=thisTab ) continue;
         if( pTerm->eOperator & (WO_EQ|WO_IN|WO_ISNULL) ){
           if( nSkipEq ){
-            /* Ignore the first nEq equality matches since the index
+            /* Ignore the first pc.plan.nEq equality matches since the index
             ** has already accounted for these */
             nSkipEq--;
           }else{
             /* Assume each additional equality match reduces the result
             ** set size by a factor of 10 */
-            nRow /= 10;
+            pc.plan.nRow /= 10;
           }
         }else if( pTerm->eOperator & (WO_LT|WO_LE|WO_GT|WO_GE) ){
           if( nSkipRange ){
@@ -104944,37 +105939,33 @@ static void bestBtreeIndex(
             ** more selective intentionally because of the subjective 
             ** observation that indexed range constraints really are more
             ** selective in practice, on average. */
-            nRow /= 3;
+            pc.plan.nRow /= 3;
           }
         }else if( pTerm->eOperator!=WO_NOOP ){
           /* Any other expression lowers the output row count by half */
-          nRow /= 2;
+          pc.plan.nRow /= 2;
         }
       }
-      if( nRow<2 ) nRow = 2;
+      if( pc.plan.nRow<2 ) pc.plan.nRow = 2;
     }
 
 
     WHERETRACE((
-      "%s(%s): nEq=%d nInMul=%d rangeDiv=%d bSort=%d bLookup=%d wsFlags=0x%x\n"
-      "         notReady=0x%llx log10N=%.1f nRow=%.1f cost=%.1f used=0x%llx\n",
-      pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk"), 
-      nEq, nInMul, (int)rangeDiv, bSort, bLookup, wsFlags,
-      notReady, log10N, nRow, cost, used
+      "      nEq=%d nInMul=%d rangeDiv=%d bSort=%d bLookup=%d wsFlags=0x%08x\n"
+      "      notReady=0x%llx log10N=%.1f nRow=%.1f cost=%.1f\n"
+      "      used=0x%llx nOBSat=%d\n",
+      pc.plan.nEq, nInMul, (int)rangeDiv, bSort, bLookup, pc.plan.wsFlags,
+      p->notReady, log10N, pc.plan.nRow, pc.rCost, pc.used,
+      pc.plan.nOBSat
     ));
 
     /* If this index is the best we have seen so far, then record this
-    ** index and its cost in the pCost structure.
+    ** index and its cost in the p->cost structure.
     */
-    if( (!pIdx || wsFlags)
-     && (cost<pCost->rCost || (cost<=pCost->rCost && nRow<pCost->plan.nRow))
-    ){
-      pCost->rCost = cost;
-      pCost->used = used;
-      pCost->plan.nRow = nRow;
-      pCost->plan.wsFlags = (wsFlags&wsFlagMask);
-      pCost->plan.nEq = nEq;
-      pCost->plan.u.pIdx = pIdx;
+    if( (!pIdx || pc.plan.wsFlags) && compareCost(&pc, &p->cost) ){
+      p->cost = pc;
+      p->cost.plan.wsFlags &= wsFlagMask;
+      p->cost.plan.u.pIdx = pIdx;
     }
 
     /* If there was an INDEXED BY clause, then only that one index is
@@ -104991,25 +105982,23 @@ static void bestBtreeIndex(
   ** in. This is used for application testing, to help find cases
   ** where application behaviour depends on the (undefined) order that
   ** SQLite outputs rows in in the absence of an ORDER BY clause.  */
-  if( !pOrderBy && pParse->db->flags & SQLITE_ReverseOrder ){
-    pCost->plan.wsFlags |= WHERE_REVERSE;
+  if( !p->pOrderBy && pParse->db->flags & SQLITE_ReverseOrder ){
+    p->cost.plan.wsFlags |= WHERE_REVERSE;
   }
 
-  assert( pOrderBy || (pCost->plan.wsFlags&WHERE_ORDERBY)==0 );
-  assert( pCost->plan.u.pIdx==0 || (pCost->plan.wsFlags&WHERE_ROWID_EQ)==0 );
+  assert( p->pOrderBy || (p->cost.plan.wsFlags&WHERE_ORDERED)==0 );
+  assert( p->cost.plan.u.pIdx==0 || (p->cost.plan.wsFlags&WHERE_ROWID_EQ)==0 );
   assert( pSrc->pIndex==0 
-       || pCost->plan.u.pIdx==0 
-       || pCost->plan.u.pIdx==pSrc->pIndex 
+       || p->cost.plan.u.pIdx==0 
+       || p->cost.plan.u.pIdx==pSrc->pIndex 
   );
 
-  WHERETRACE(("best index is: %s\n", 
-    ((pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ? "none" : 
-         pCost->plan.u.pIdx ? pCost->plan.u.pIdx->zName : "ipk")
-  ));
+  WHERETRACE(("   best index is: %s\n",
+         p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk"));
   
-  bestOrClauseIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
-  bestAutomaticIndex(pParse, pWC, pSrc, notReady, pCost);
-  pCost->plan.wsFlags |= eqTermMask;
+  bestOrClauseIndex(p);
+  bestAutomaticIndex(p);
+  p->cost.plan.wsFlags |= eqTermMask;
 }
 
 /*
@@ -105017,28 +106006,27 @@ static void bestBtreeIndex(
 ** best query plan and its cost into the WhereCost object supplied 
 ** as the last parameter. This function may calculate the cost of
 ** both real and virtual table scans.
+**
+** This function does not take ORDER BY or DISTINCT into account.  Nor
+** does it remember the virtual table query plan.  All it does is compute
+** the cost while determining if an OR optimization is applicable.  The
+** details will be reconsidered later if the optimization is found to be
+** applicable.
 */
-static void bestIndex(
-  Parse *pParse,              /* The parsing context */
-  WhereClause *pWC,           /* The WHERE clause */
-  struct SrcList_item *pSrc,  /* The FROM clause term to search */
-  Bitmask notReady,           /* Mask of cursors not available for indexing */
-  Bitmask notValid,           /* Cursors not available for any purpose */
-  ExprList *pOrderBy,         /* The ORDER BY clause */
-  WhereCost *pCost            /* Lowest cost query plan */
-){
+static void bestIndex(WhereBestIdx *p){
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  if( IsVirtual(pSrc->pTab) ){
-    sqlite3_index_info *p = 0;
-    bestVirtualIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost,&p);
-    if( p->needToFreeIdxStr ){
-      sqlite3_free(p->idxStr);
-    }
-    sqlite3DbFree(pParse->db, p);
+  if( IsVirtual(p->pSrc->pTab) ){
+    sqlite3_index_info *pIdxInfo = 0;
+    p->ppIdxInfo = &pIdxInfo;
+    bestVirtualIndex(p);
+    if( pIdxInfo->needToFreeIdxStr ){
+      sqlite3_free(pIdxInfo->idxStr);
+    }
+    sqlite3DbFree(p->pParse->db, pIdxInfo);
   }else
 #endif
   {
-    bestBtreeIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, 0, pCost);
+    bestBtreeIndex(p);
   }
 }
 
@@ -105516,6 +106504,16 @@ static Bitmask codeOneLoopStart(
     VdbeComment((v, "init LEFT JOIN no-match flag"));
   }
 
+  /* Special case of a FROM clause subquery implemented as a co-routine */
+  if( pTabItem->viaCoroutine ){
+    int regYield = pTabItem->regReturn;
+    sqlite3VdbeAddOp2(v, OP_Integer, pTabItem->addrFillSub-1, regYield);
+    pLevel->p2 =  sqlite3VdbeAddOp1(v, OP_Yield, regYield);
+    VdbeComment((v, "next row of co-routine %s", pTabItem->pTab->zName));
+    sqlite3VdbeAddOp2(v, OP_If, regYield+1, addrBrk);
+    pLevel->op = OP_Goto;
+  }else
+
 #ifndef SQLITE_OMIT_VIRTUALTABLE
   if(  (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
     /* Case 0:  The table is a virtual-table.  Use the VFilter and VNext
@@ -105734,7 +106732,7 @@ static Bitmask codeOneLoopStart(
     ** this requires some special handling.
     */
     if( (wctrlFlags&WHERE_ORDERBY_MIN)!=0
-     && (pLevel->plan.wsFlags&WHERE_ORDERBY)
+     && (pLevel->plan.wsFlags&WHERE_ORDERED)
      && (pIdx->nColumn>nEq)
     ){
       /* assert( pOrderBy->nExpr==1 ); */
@@ -105897,6 +106895,11 @@ static Bitmask codeOneLoopStart(
       pLevel->op = OP_Next;
     }
     pLevel->p1 = iIdxCur;
+    if( pLevel->plan.wsFlags & WHERE_COVER_SCAN ){
+      pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
+    }else{
+      assert( pLevel->p5==0 );
+    }
   }else
 
 #ifndef SQLITE_OMIT_OR_OPTIMIZATION
@@ -106291,42 +107294,46 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
 **
 ** ORDER BY CLAUSE PROCESSING
 **
-** *ppOrderBy is a pointer to the ORDER BY clause of a SELECT statement,
+** pOrderBy is a pointer to the ORDER BY clause of a SELECT statement,
 ** if there is one.  If there is no ORDER BY clause or if this routine
-** is called from an UPDATE or DELETE statement, then ppOrderBy is NULL.
+** is called from an UPDATE or DELETE statement, then pOrderBy is NULL.
 **
 ** If an index can be used so that the natural output order of the table
 ** scan is correct for the ORDER BY clause, then that index is used and
-** *ppOrderBy is set to NULL.  This is an optimization that prevents an
-** unnecessary sort of the result set if an index appropriate for the
-** ORDER BY clause already exists.
+** the returned WhereInfo.nOBSat field is set to pOrderBy->nExpr.  This
+** is an optimization that prevents an unnecessary sort of the result set
+** if an index appropriate for the ORDER BY clause already exists.
 **
 ** If the where clause loops cannot be arranged to provide the correct
-** output order, then the *ppOrderBy is unchanged.
+** output order, then WhereInfo.nOBSat is 0.
 */
 SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   Parse *pParse,        /* The parser context */
   SrcList *pTabList,    /* A list of all tables to be scanned */
   Expr *pWhere,         /* The WHERE clause */
-  ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
+  ExprList *pOrderBy,   /* An ORDER BY clause, or NULL */
   ExprList *pDistinct,  /* The select-list for DISTINCT queries - or NULL */
   u16 wctrlFlags,       /* One of the WHERE_* flags defined in sqliteInt.h */
   int iIdxCur           /* If WHERE_ONETABLE_ONLY is set, index cursor number */
 ){
-  int i;                     /* Loop counter */
   int nByteWInfo;            /* Num. bytes allocated for WhereInfo struct */
   int nTabList;              /* Number of elements in pTabList */
   WhereInfo *pWInfo;         /* Will become the return value of this function */
   Vdbe *v = pParse->pVdbe;   /* The virtual database engine */
   Bitmask notReady;          /* Cursors that are not yet positioned */
+  WhereBestIdx sWBI;         /* Best index search context */
   WhereMaskSet *pMaskSet;    /* The expression mask set */
-  WhereClause *pWC;               /* Decomposition of the WHERE clause */
-  struct SrcList_item *pTabItem;  /* A single entry from pTabList */
-  WhereLevel *pLevel;             /* A single level in the pWInfo list */
-  int iFrom;                      /* First unused FROM clause element */
+  WhereLevel *pLevel;        /* A single level in pWInfo->a[] */
+  int iFrom;                 /* First unused FROM clause element */
   int andFlags;              /* AND-ed combination of all pWC->a[].wtFlags */
+  int ii;                    /* Loop counter */
   sqlite3 *db;               /* Database connection */
 
+
+  /* Variable initialization */
+  memset(&sWBI, 0, sizeof(sWBI));
+  sWBI.pParse = pParse;
+
   /* The number of tables in the FROM clause is limited by the number of
   ** bits in a Bitmask 
   */
@@ -106366,22 +107373,23 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   pWInfo->pParse = pParse;
   pWInfo->pTabList = pTabList;
   pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
-  pWInfo->pWC = pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
+  pWInfo->pWC = sWBI.pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
   pWInfo->wctrlFlags = wctrlFlags;
   pWInfo->savedNQueryLoop = pParse->nQueryLoop;
-  pMaskSet = (WhereMaskSet*)&pWC[1];
+  pMaskSet = (WhereMaskSet*)&sWBI.pWC[1];
+  sWBI.aLevel = pWInfo->a;
 
   /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
   ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
-  if( db->flags & SQLITE_DistinctOpt ) pDistinct = 0;
+  if( OptimizationDisabled(db, SQLITE_DistinctOpt) ) pDistinct = 0;
 
   /* Split the WHERE clause into separate subexpressions where each
   ** subexpression is separated by an AND operator.
   */
   initMaskSet(pMaskSet);
-  whereClauseInit(pWC, pParse, pMaskSet, wctrlFlags);
+  whereClauseInit(sWBI.pWC, pParse, pMaskSet, wctrlFlags);
   sqlite3ExprCodeConstants(pParse, pWhere);
-  whereSplit(pWC, pWhere, TK_AND);   /* IMP: R-15842-53296 */
+  whereSplit(sWBI.pWC, pWhere, TK_AND);   /* IMP: R-15842-53296 */
     
   /* Special case: a WHERE clause that is constant.  Evaluate the
   ** expression and either jump over all of the code or fall thru.
@@ -106412,20 +107420,20 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   ** equal to pTabList->nSrc but might be shortened to 1 if the
   ** WHERE_ONETABLE_ONLY flag is set.
   */
-  assert( pWC->vmask==0 && pMaskSet->n==0 );
-  for(i=0; i<pTabList->nSrc; i++){
-    createMask(pMaskSet, pTabList->a[i].iCursor);
+  assert( sWBI.pWC->vmask==0 && pMaskSet->n==0 );
+  for(ii=0; ii<pTabList->nSrc; ii++){
+    createMask(pMaskSet, pTabList->a[ii].iCursor);
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-    if( ALWAYS(pTabList->a[i].pTab) && IsVirtual(pTabList->a[i].pTab) ){
-      pWC->vmask |= ((Bitmask)1 << i);
+    if( ALWAYS(pTabList->a[ii].pTab) && IsVirtual(pTabList->a[ii].pTab) ){
+      sWBI.pWC->vmask |= ((Bitmask)1 << ii);
     }
 #endif
   }
 #ifndef NDEBUG
   {
     Bitmask toTheLeft = 0;
-    for(i=0; i<pTabList->nSrc; i++){
-      Bitmask m = getMask(pMaskSet, pTabList->a[i].iCursor);
+    for(ii=0; ii<pTabList->nSrc; ii++){
+      Bitmask m = getMask(pMaskSet, pTabList->a[ii].iCursor);
       assert( (m-1)==toTheLeft );
       toTheLeft |= m;
     }
@@ -106437,7 +107445,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   ** want to analyze these virtual terms, so start analyzing at the end
   ** and work forward so that the added virtual terms are never processed.
   */
-  exprAnalyzeAll(pTabList, pWC);
+  exprAnalyzeAll(pTabList, sWBI.pWC);
   if( db->mallocFailed ){
     goto whereBeginError;
   }
@@ -106446,7 +107454,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   ** If it is, then set pDistinct to NULL and WhereInfo.eDistinct to
   ** WHERE_DISTINCT_UNIQUE to tell the caller to ignore the DISTINCT.
   */
-  if( pDistinct && isDistinctRedundant(pParse, pTabList, pWC, pDistinct) ){
+  if( pDistinct && isDistinctRedundant(pParse, pTabList, sWBI.pWC, pDistinct) ){
     pDistinct = 0;
     pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
   }
@@ -106466,10 +107474,13 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   ** This loop also figures out the nesting order of tables in the FROM
   ** clause.
   */
-  notReady = ~(Bitmask)0;
+  sWBI.notValid = ~(Bitmask)0;
+  sWBI.pOrderBy = pOrderBy;
+  sWBI.n = nTabList;
+  sWBI.pDistinct = pDistinct;
   andFlags = ~0;
   WHERETRACE(("*** Optimizer Start ***\n"));
-  for(i=iFrom=0, pLevel=pWInfo->a; i<nTabList; i++, pLevel++){
+  for(sWBI.i=iFrom=0, pLevel=pWInfo->a; sWBI.i<nTabList; sWBI.i++, pLevel++){
     WhereCost bestPlan;         /* Most efficient plan seen so far */
     Index *pIdx;                /* Index for FROM table at pTabItem */
     int j;                      /* For looping over FROM tables */
@@ -106481,7 +107492,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
 
     memset(&bestPlan, 0, sizeof(bestPlan));
     bestPlan.rCost = SQLITE_BIG_DBL;
-    WHERETRACE(("*** Begin search for loop %d ***\n", i));
+    WHERETRACE(("*** Begin search for loop %d ***\n", sWBI.i));
 
     /* Loop through the remaining entries in the FROM clause to find the
     ** next nested loop. The loop tests all FROM clause entries
@@ -106497,8 +107508,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
     ** by waiting for other tables to run first.  This "optimal" test works
     ** by first assuming that the FROM clause is on the inner loop and finding
     ** its query plan, then checking to see if that query plan uses any
-    ** other FROM clause terms that are notReady.  If no notReady terms are
-    ** used then the "optimal" query plan works.
+    ** other FROM clause terms that are sWBI.notValid.  If no notValid terms
+    ** are used then the "optimal" query plan works.
     **
     ** Note that the WhereCost.nRow parameter for an optimal scan might
     ** not be as small as it would be if the table really were the innermost
@@ -106529,58 +107540,64 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
     nUnconstrained = 0;
     notIndexed = 0;
     for(isOptimal=(iFrom<nTabList-1); isOptimal>=0 && bestJ<0; isOptimal--){
-      Bitmask mask;             /* Mask of tables not yet ready */
-      for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){
+      for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){
         int doNotReorder;    /* True if this table should not be reordered */
-        WhereCost sCost;     /* Cost information from best[Virtual]Index() */
-        ExprList *pOrderBy;  /* ORDER BY clause for index to optimize */
-        ExprList *pDist;     /* DISTINCT clause for index to optimize */
   
-        doNotReorder =  (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0;
+        doNotReorder =  (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0;
         if( j!=iFrom && doNotReorder ) break;
-        m = getMask(pMaskSet, pTabItem->iCursor);
-        if( (m & notReady)==0 ){
+        m = getMask(pMaskSet, sWBI.pSrc->iCursor);
+        if( (m & sWBI.notValid)==0 ){
           if( j==iFrom ) iFrom++;
           continue;
         }
-        mask = (isOptimal ? m : notReady);
-        pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0);
-        pDist = (i==0 ? pDistinct : 0);
-        if( pTabItem->pIndex==0 ) nUnconstrained++;
+        sWBI.notReady = (isOptimal ? m : sWBI.notValid);
+        if( sWBI.pSrc->pIndex==0 ) nUnconstrained++;
   
-        WHERETRACE(("=== trying table %d with isOptimal=%d ===\n",
-                    j, isOptimal));
-        assert( pTabItem->pTab );
+        WHERETRACE(("   === trying table %d (%s) with isOptimal=%d ===\n",
+                    j, sWBI.pSrc->pTab->zName, isOptimal));
+        assert( sWBI.pSrc->pTab );
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-        if( IsVirtual(pTabItem->pTab) ){
-          sqlite3_index_info **pp = &pWInfo->a[j].pIdxInfo;
-          bestVirtualIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
-                           &sCost, pp);
+        if( IsVirtual(sWBI.pSrc->pTab) ){
+          sWBI.ppIdxInfo = &pWInfo->a[j].pIdxInfo;
+          bestVirtualIndex(&sWBI);
         }else 
 #endif
         {
-          bestBtreeIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
-              pDist, &sCost);
+          bestBtreeIndex(&sWBI);
         }
-        assert( isOptimal || (sCost.used&notReady)==0 );
+        assert( isOptimal || (sWBI.cost.used&sWBI.notValid)==0 );
 
         /* If an INDEXED BY clause is present, then the plan must use that
         ** index if it uses any index at all */
-        assert( pTabItem->pIndex==0 
-                  || (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
-                  || sCost.plan.u.pIdx==pTabItem->pIndex );
+        assert( sWBI.pSrc->pIndex==0 
+                  || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
+                  || sWBI.cost.plan.u.pIdx==sWBI.pSrc->pIndex );
 
-        if( isOptimal && (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
+        if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
           notIndexed |= m;
         }
+        if( isOptimal ){
+          pWInfo->a[j].rOptCost = sWBI.cost.rCost;
+        }else if( iFrom<nTabList-1 ){
+          /* If two or more tables have nearly the same outer loop cost,
+          ** very different inner loop (optimal) cost, we want to choose
+          ** for the outer loop that table which benefits the least from
+          ** being in the inner loop.  The following code scales the 
+          ** outer loop cost estimate to accomplish that. */
+          WHERETRACE(("   scaling cost from %.1f to %.1f\n",
+                      sWBI.cost.rCost,
+                      sWBI.cost.rCost/pWInfo->a[j].rOptCost));
+          sWBI.cost.rCost /= pWInfo->a[j].rOptCost;
+        }
 
         /* Conditions under which this table becomes the best so far:
         **
         **   (1) The table must not depend on other tables that have not
-        **       yet run.
+        **       yet run.  (In other words, it must not depend on tables
+        **       in inner loops.)
         **
-        **   (2) A full-table-scan plan cannot supercede indexed plan unless
-        **       the full-table-scan is an "optimal" plan as defined above.
+        **   (2) (This rule was removed on 2012-11-09.  The scaling of the
+        **       cost using the optimal scan cost made this rule obsolete.)
         **
         **   (3) All tables have an INDEXED BY clause or this table lacks an
         **       INDEXED BY clause or this table uses the specific
@@ -106591,43 +107608,39 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
         **       The NEVER() comes about because rule (2) above prevents
         **       An indexable full-table-scan from reaching rule (3).
         **
-        **   (4) The plan cost must be lower than prior plans or else the
-        **       cost must be the same and the number of rows must be lower.
+        **   (4) The plan cost must be lower than prior plans, where "cost"
+        **       is defined by the compareCost() function above. 
         */
-        if( (sCost.used&notReady)==0                       /* (1) */
-            && (bestJ<0 || (notIndexed&m)!=0               /* (2) */
-                || (bestPlan.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
-                || (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)
-            && (nUnconstrained==0 || pTabItem->pIndex==0   /* (3) */
-                || NEVER((sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))
-            && (bestJ<0 || sCost.rCost<bestPlan.rCost      /* (4) */
-                || (sCost.rCost<=bestPlan.rCost 
-                 && sCost.plan.nRow<bestPlan.plan.nRow))
+        if( (sWBI.cost.used&sWBI.notValid)==0                    /* (1) */
+            && (nUnconstrained==0 || sWBI.pSrc->pIndex==0        /* (3) */
+                || NEVER((sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))
+            && (bestJ<0 || compareCost(&sWBI.cost, &bestPlan))   /* (4) */
         ){
-          WHERETRACE(("=== table %d is best so far"
-                      " with cost=%g and nRow=%g\n",
-                      j, sCost.rCost, sCost.plan.nRow));
-          bestPlan = sCost;
+          WHERETRACE(("   === table %d (%s) is best so far\n"
+                      "       cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=%08x\n",
+                      j, sWBI.pSrc->pTab->zName,
+                      sWBI.cost.rCost, sWBI.cost.plan.nRow,
+                      sWBI.cost.plan.nOBSat, sWBI.cost.plan.wsFlags));
+          bestPlan = sWBI.cost;
           bestJ = j;
         }
         if( doNotReorder ) break;
       }
     }
     assert( bestJ>=0 );
-    assert( notReady & getMask(pMaskSet, pTabList->a[bestJ].iCursor) );
-    WHERETRACE(("*** Optimizer selects table %d for loop %d"
-                " with cost=%g and nRow=%g\n",
-                bestJ, pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow));
-    /* The ALWAYS() that follows was added to hush up clang scan-build */
-    if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 && ALWAYS(ppOrderBy) ){
-      *ppOrderBy = 0;
-    }
+    assert( sWBI.notValid & getMask(pMaskSet, pTabList->a[bestJ].iCursor) );
+    WHERETRACE(("*** Optimizer selects table %d (%s) for loop %d with:\n"
+                "    cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=0x%08x\n",
+                bestJ, pTabList->a[bestJ].pTab->zName,
+                pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow,
+                bestPlan.plan.nOBSat, bestPlan.plan.wsFlags));
     if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){
       assert( pWInfo->eDistinct==0 );
       pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
     }
     andFlags &= bestPlan.plan.wsFlags;
     pLevel->plan = bestPlan.plan;
+    pLevel->iTabCur = pTabList->a[bestJ].iCursor;
     testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
     testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
     if( bestPlan.plan.wsFlags & (WHERE_INDEXED|WHERE_TEMP_INDEX) ){
@@ -106641,7 +107654,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
     }else{
       pLevel->iIdxCur = -1;
     }
-    notReady &= ~getMask(pMaskSet, pTabList->a[bestJ].iCursor);
+    sWBI.notValid &= ~getMask(pMaskSet, pTabList->a[bestJ].iCursor);
     pLevel->iFrom = (u8)bestJ;
     if( bestPlan.plan.nRow>=(double)1 ){
       pParse->nQueryLoop *= bestPlan.plan.nRow;
@@ -106669,12 +107682,19 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   if( pParse->nErr || db->mallocFailed ){
     goto whereBeginError;
   }
+  if( nTabList ){
+    pLevel--;
+    pWInfo->nOBSat = pLevel->plan.nOBSat;
+  }else{
+    pWInfo->nOBSat = 0;
+  }
 
   /* If the total query only selects a single row, then the ORDER BY
   ** clause is irrelevant.
   */
-  if( (andFlags & WHERE_UNIQUE)!=0 && ppOrderBy ){
-    *ppOrderBy = 0;
+  if( (andFlags & WHERE_UNIQUE)!=0 && pOrderBy ){
+    assert( nTabList==0 || (pLevel->plan.wsFlags & WHERE_ALL_UNIQUE)!=0 );
+    pWInfo->nOBSat = pOrderBy->nExpr;
   }
 
   /* If the caller is an UPDATE or DELETE statement that is requesting
@@ -106694,13 +107714,13 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
   notReady = ~(Bitmask)0;
   pWInfo->nRowOut = (double)1;
-  for(i=0, pLevel=pWInfo->a; i<nTabList; i++, pLevel++){
+  for(ii=0, pLevel=pWInfo->a; ii<nTabList; ii++, pLevel++){
     Table *pTab;     /* Table to open */
     int iDb;         /* Index of database containing table/index */
+    struct SrcList_item *pTabItem;
 
     pTabItem = &pTabList->a[pLevel->iFrom];
     pTab = pTabItem->pTab;
-    pLevel->iTabCur = pTabItem->iCursor;
     pWInfo->nRowOut *= pLevel->plan.nRow;
     iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
     if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
@@ -106711,6 +107731,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
       const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
       int iCur = pTabItem->iCursor;
       sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB);
+    }else if( IsVirtual(pTab) ){
+      /* noop */
     }else
 #endif
     if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0
@@ -106732,7 +107754,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
     }
 #ifndef SQLITE_OMIT_AUTOMATIC_INDEX
     if( (pLevel->plan.wsFlags & WHERE_TEMP_INDEX)!=0 ){
-      constructAutomaticIndex(pParse, pWC, pTabItem, notReady, pLevel);
+      constructAutomaticIndex(pParse, sWBI.pWC, pTabItem, notReady, pLevel);
     }else
 #endif
     if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){
@@ -106746,7 +107768,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
       VdbeComment((v, "%s", pIx->zName));
     }
     sqlite3CodeVerifySchema(pParse, iDb);
-    notReady &= ~getMask(pWC->pMaskSet, pTabItem->iCursor);
+    notReady &= ~getMask(sWBI.pWC->pMaskSet, pTabItem->iCursor);
   }
   pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
   if( db->mallocFailed ) goto whereBeginError;
@@ -106756,10 +107778,10 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   ** program.
   */
   notReady = ~(Bitmask)0;
-  for(i=0; i<nTabList; i++){
-    pLevel = &pWInfo->a[i];
-    explainOneScan(pParse, pTabList, pLevel, i, pLevel->iFrom, wctrlFlags);
-    notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady);
+  for(ii=0; ii<nTabList; ii++){
+    pLevel = &pWInfo->a[ii];
+    explainOneScan(pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags);
+    notReady = codeOneLoopStart(pWInfo, ii, wctrlFlags, notReady);
     pWInfo->iContinue = pLevel->addrCont;
   }
 
@@ -106770,16 +107792,20 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   ** the index is listed as "{}".  If the primary key is used the
   ** index name is '*'.
   */
-  for(i=0; i<nTabList; i++){
+  for(ii=0; ii<nTabList; ii++){
     char *z;
     int n;
-    pLevel = &pWInfo->a[i];
+    int w;
+    struct SrcList_item *pTabItem;
+
+    pLevel = &pWInfo->a[ii];
+    w = pLevel->plan.wsFlags;
     pTabItem = &pTabList->a[pLevel->iFrom];
     z = pTabItem->zAlias;
     if( z==0 ) z = pTabItem->pTab->zName;
     n = sqlite3Strlen30(z);
     if( n+nQPlan < sizeof(sqlite3_query_plan)-10 ){
-      if( pLevel->plan.wsFlags & WHERE_IDX_ONLY ){
+      if( (w & WHERE_IDX_ONLY)!=0 && (w & WHERE_COVER_SCAN)==0 ){
         memcpy(&sqlite3_query_plan[nQPlan], "{}", 2);
         nQPlan += 2;
       }else{
@@ -106788,12 +107814,12 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
       }
       sqlite3_query_plan[nQPlan++] = ' ';
     }
-    testcase( pLevel->plan.wsFlags & WHERE_ROWID_EQ );
-    testcase( pLevel->plan.wsFlags & WHERE_ROWID_RANGE );
-    if( pLevel->plan.wsFlags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
+    testcase( w & WHERE_ROWID_EQ );
+    testcase( w & WHERE_ROWID_RANGE );
+    if( w & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
       memcpy(&sqlite3_query_plan[nQPlan], "* ", 2);
       nQPlan += 2;
-    }else if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){
+    }else if( (w & WHERE_INDEXED)!=0 && (w & WHERE_COVER_SCAN)==0 ){
       n = sqlite3Strlen30(pLevel->plan.u.pIdx->zName);
       if( n+nQPlan < sizeof(sqlite3_query_plan)-2 ){
         memcpy(&sqlite3_query_plan[nQPlan], pLevel->plan.u.pIdx->zName, n);
@@ -109652,7 +110678,7 @@ static void yy_reduce(
         break;
       case 194: /* expr ::= expr COLLATE ids */
 {
-  yygotominor.yy342.pExpr = sqlite3ExprSetCollByToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0);
+  yygotominor.yy342.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0);
   yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
   yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
 }
@@ -109911,11 +110937,7 @@ static void yy_reduce(
         break;
       case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */
 {
-  Expr *p = 0;
-  if( yymsp[-1].minor.yy0.n>0 ){
-    p = sqlite3Expr(pParse->db, TK_COLUMN, 0);
-    sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
-  }
+  Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0);
   yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, p);
   sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1);
   sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
@@ -109924,11 +110946,7 @@ static void yy_reduce(
         break;
       case 248: /* idxlist ::= nm collate sortorder */
 {
-  Expr *p = 0;
-  if( yymsp[-1].minor.yy0.n>0 ){
-    p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
-    sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
-  }
+  Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0);
   yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, p);
   sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
   sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
@@ -110177,6 +111195,7 @@ static void yy_reduce(
       /* (326) anylist ::= anylist ANY */ yytestcase(yyruleno==326);
         break;
   };
+  assert( yyruleno>=0 && yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
   yygoto = yyRuleInfo[yyruleno].lhs;
   yysize = yyRuleInfo[yyruleno].nrhs;
   yypParser->yyidx -= yysize;
@@ -111742,6 +112761,13 @@ SQLITE_API int sqlite3_initialize(void){
   */
   if( sqlite3GlobalConfig.isInit ) return SQLITE_OK;
 
+#ifdef SQLITE_ENABLE_SQLLOG
+  {
+    extern void sqlite3_init_sqllog(void);
+    sqlite3_init_sqllog();
+  }
+#endif
+
   /* Make sure the mutex subsystem is initialized.  If unable to 
   ** initialize the mutex subsystem, return early with the error.
   ** If the system is so sick that we are unable to allocate a mutex,
@@ -112085,6 +113111,20 @@ SQLITE_API int sqlite3_config(int op, ...){
       break;
     }
 
+    case SQLITE_CONFIG_COVERING_INDEX_SCAN: {
+      sqlite3GlobalConfig.bUseCis = va_arg(ap, int);
+      break;
+    }
+
+#ifdef SQLITE_ENABLE_SQLLOG
+    case SQLITE_CONFIG_SQLLOG: {
+      typedef void(*SQLLOGFUNC_t)(void*, sqlite3*, const char*, int);
+      sqlite3GlobalConfig.xSqllog = va_arg(ap, SQLLOGFUNC_t);
+      sqlite3GlobalConfig.pSqllogArg = va_arg(ap, void *);
+      break;
+    }
+#endif
+
     default: {
       rc = SQLITE_ERROR;
       break;
@@ -112424,6 +113464,13 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){
     return SQLITE_BUSY;
   }
 
+#ifdef SQLITE_ENABLE_SQLLOG
+  if( sqlite3GlobalConfig.xSqllog ){
+    /* Closing the handle. Fourth parameter is passed the value 2. */
+    sqlite3GlobalConfig.xSqllog(sqlite3GlobalConfig.pSqllogArg, db, 0, 2);
+  }
+#endif
+
   /* Convert the connection into a zombie and then close it.
   */
   db->magic = SQLITE_MAGIC_ZOMBIE;
@@ -112726,6 +113773,7 @@ SQLITE_API int sqlite3_busy_handler(
   db->busyHandler.xFunc = xBusy;
   db->busyHandler.pArg = pArg;
   db->busyHandler.nBusy = 0;
+  db->busyTimeout = 0;
   sqlite3_mutex_leave(db->mutex);
   return SQLITE_OK;
 }
@@ -112763,8 +113811,8 @@ SQLITE_API void sqlite3_progress_handler(
 */
 SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){
   if( ms>0 ){
-    db->busyTimeout = ms;
     sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db);
+    db->busyTimeout = ms;
   }else{
     sqlite3_busy_handler(db, 0, 0);
   }
@@ -113377,6 +114425,15 @@ SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){
   return db->errCode;
 }
 
+/*
+** Return a string that describes the kind of error specified in the
+** argument.  For now, this simply calls the internal sqlite3ErrStr()
+** function.
+*/
+SQLITE_API const char *sqlite3_errstr(int rc){
+  return sqlite3ErrStr(rc);
+}
+
 /*
 ** Create a new collating function for database "db".  The name is zName
 ** and the encoding is enc.
@@ -114046,6 +115103,13 @@ opendb_out:
     db->magic = SQLITE_MAGIC_SICK;
   }
   *ppDb = db;
+#ifdef SQLITE_ENABLE_SQLLOG
+  if( sqlite3GlobalConfig.xSqllog ){
+    /* Opening a db handle. Fourth parameter is passed 0. */
+    void *pArg = sqlite3GlobalConfig.pSqllogArg;
+    sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0);
+  }
+#endif
   return sqlite3ApiExit(0, rc);
 }
 
@@ -114351,7 +115415,7 @@ SQLITE_API int sqlite3_table_column_metadata(
     zDataType = pCol->zType;
     zCollSeq = pCol->zColl;
     notnull = pCol->notNull!=0;
-    primarykey  = pCol->isPrimKey!=0;
+    primarykey  = (pCol->colFlags & COLFLAG_PRIMKEY)!=0;
     autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0;
   }else{
     zDataType = "INTEGER";
@@ -114614,8 +115678,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){
     */
     case SQLITE_TESTCTRL_OPTIMIZATIONS: {
       sqlite3 *db = va_arg(ap, sqlite3*);
-      int x = va_arg(ap,int);
-      db->flags = (x & SQLITE_OptMask) | (db->flags & ~SQLITE_OptMask);
+      db->dbOptFlags = (u16)(va_arg(ap, int) & 0xffff);
       break;
     }
 
@@ -120687,35 +121750,39 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
       nTmp += p->pRight->pPhrase->doclist.nList;
     }
     nTmp += p->pPhrase->doclist.nList;
-    aTmp = sqlite3_malloc(nTmp*2);
-    if( !aTmp ){
-      *pRc = SQLITE_NOMEM;
+    if( nTmp==0 ){
       res = 0;
     }else{
-      char *aPoslist = p->pPhrase->doclist.pList;
-      int nToken = p->pPhrase->nToken;
+      aTmp = sqlite3_malloc(nTmp*2);
+      if( !aTmp ){
+        *pRc = SQLITE_NOMEM;
+        res = 0;
+      }else{
+        char *aPoslist = p->pPhrase->doclist.pList;
+        int nToken = p->pPhrase->nToken;
 
-      for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
-        Fts3Phrase *pPhrase = p->pRight->pPhrase;
-        int nNear = p->nNear;
-        res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
-      }
-  
-      aPoslist = pExpr->pRight->pPhrase->doclist.pList;
-      nToken = pExpr->pRight->pPhrase->nToken;
-      for(p=pExpr->pLeft; p && res; p=p->pLeft){
-        int nNear;
-        Fts3Phrase *pPhrase;
-        assert( p->pParent && p->pParent->pLeft==p );
-        nNear = p->pParent->nNear;
-        pPhrase = (
-            p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
-        );
-        res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
+        for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
+          Fts3Phrase *pPhrase = p->pRight->pPhrase;
+          int nNear = p->nNear;
+          res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
+        }
+
+        aPoslist = pExpr->pRight->pPhrase->doclist.pList;
+        nToken = pExpr->pRight->pPhrase->nToken;
+        for(p=pExpr->pLeft; p && res; p=p->pLeft){
+          int nNear;
+          Fts3Phrase *pPhrase;
+          assert( p->pParent && p->pParent->pLeft==p );
+          nNear = p->pParent->nNear;
+          pPhrase = (
+              p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
+              );
+          res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
+        }
       }
-    }
 
-    sqlite3_free(aTmp);
+      sqlite3_free(aTmp);
+    }
   }
 
   return res;
@@ -121953,7 +123020,7 @@ static int getNextToken(
   rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor);
   if( rc==SQLITE_OK ){
     const char *zToken;
-    int nToken, iStart, iEnd, iPosition;
+    int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
     int nByte;                               /* total space to allocate */
 
     rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
@@ -122068,7 +123135,7 @@ static int getNextString(
     int ii;
     for(ii=0; rc==SQLITE_OK; ii++){
       const char *zByte;
-      int nByte, iBegin, iEnd, iPos;
+      int nByte = 0, iBegin = 0, iEnd = 0, iPos = 0;
       rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos);
       if( rc==SQLITE_OK ){
         Fts3PhraseToken *pToken;
@@ -124065,10 +125132,10 @@ static void testFunc(
   const char *azArg[64];
 
   const char *zToken;
-  int nToken;
-  int iStart;
-  int iEnd;
-  int iPos;
+  int nToken = 0;
+  int iStart = 0;
+  int iEnd = 0;
+  int iPos = 0;
   int i;
 
   Tcl_Obj *pRet;
@@ -125315,16 +126382,16 @@ static int fts3PendingTermsAdd(
   int iLangid,                    /* Language id to use */
   const char *zText,              /* Text of document to be inserted */
   int iCol,                       /* Column into which text is being inserted */
-  u32 *pnWord                     /* OUT: Number of tokens inserted */
+  u32 *pnWord                     /* IN/OUT: Incr. by number tokens inserted */
 ){
   int rc;
-  int iStart;
-  int iEnd;
-  int iPos;
+  int iStart = 0;
+  int iEnd = 0;
+  int iPos = 0;
   int nWord = 0;
 
   char const *zToken;
-  int nToken;
+  int nToken = 0;
 
   sqlite3_tokenizer *pTokenizer = p->pTokenizer;
   sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
@@ -125379,7 +126446,7 @@ static int fts3PendingTermsAdd(
   }
 
   pModule->xClose(pCsr);
-  *pnWord = nWord;
+  *pnWord += nWord;
   return (rc==SQLITE_DONE ? SQLITE_OK : rc);
 }
 
@@ -125583,11 +126650,13 @@ static void fts3DeleteTerms(
   int *pRC,               /* Result code */
   Fts3Table *p,           /* The FTS table to delete from */
   sqlite3_value *pRowid,  /* The docid to be deleted */
-  u32 *aSz                /* Sizes of deleted document written here */
+  u32 *aSz,               /* Sizes of deleted document written here */
+  int *pbFound            /* OUT: Set to true if row really does exist */
 ){
   int rc;
   sqlite3_stmt *pSelect;
 
+  assert( *pbFound==0 );
   if( *pRC ) return;
   rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid);
   if( rc==SQLITE_OK ){
@@ -125605,6 +126674,7 @@ static void fts3DeleteTerms(
         *pRC = rc;
         return;
       }
+      *pbFound = 1;
     }
     rc = sqlite3_reset(pSelect);
   }else{
@@ -127829,7 +128899,7 @@ static int fts3DoRebuild(Fts3Table *p){
       int iCol;
       int iLangid = langidFromSelect(p, pStmt);
       rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0));
-      aSz[p->nColumn] = 0;
+      memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1));
       for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
         const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1);
         rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]);
@@ -129473,9 +130543,9 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
         rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText, &pT);
         while( rc==SQLITE_OK ){
           char const *zToken;       /* Buffer containing token */
-          int nToken;               /* Number of bytes in token */
-          int iDum1, iDum2;         /* Dummy variables */
-          int iPos;                 /* Position of token in zText */
+          int nToken = 0;           /* Number of bytes in token */
+          int iDum1 = 0, iDum2 = 0; /* Dummy variables */
+          int iPos = 0;             /* Position of token in zText */
 
           rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos);
           if( rc==SQLITE_OK ){
@@ -129642,9 +130712,9 @@ SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *pCsr){
       rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC);
       while( rc==SQLITE_OK ){
         char const *zToken;       /* Buffer containing token */
-        int nToken;               /* Number of bytes in token */
-        int iDum1, iDum2;         /* Dummy variables */
-        int iPos;                 /* Position of token in zText */
+        int nToken = 0;           /* Number of bytes in token */
+        int iDum1 = 0, iDum2 = 0; /* Dummy variables */
+        int iPos = 0;             /* Position of token in zText */
   
         rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos);
         for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
@@ -129733,28 +130803,32 @@ SQLITE_PRIVATE int sqlite3Fts3DeferToken(
 static int fts3DeleteByRowid(
   Fts3Table *p, 
   sqlite3_value *pRowid, 
-  int *pnDoc,
+  int *pnChng,                    /* IN/OUT: Decrement if row is deleted */
   u32 *aSzDel
 ){
-  int isEmpty = 0;
-  int rc = fts3IsEmpty(p, pRowid, &isEmpty);
-  if( rc==SQLITE_OK ){
-    if( isEmpty ){
-      /* Deleting this row means the whole table is empty. In this case
-      ** delete the contents of all three tables and throw away any
-      ** data in the pendingTerms hash table.  */
-      rc = fts3DeleteAll(p, 1);
-      *pnDoc = *pnDoc - 1;
-    }else{
-      fts3DeleteTerms(&rc, p, pRowid, aSzDel);
-      if( p->zContentTbl==0 ){
-        fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid);
-        if( sqlite3_changes(p->db) ) *pnDoc = *pnDoc - 1;
+  int rc = SQLITE_OK;             /* Return code */
+  int bFound = 0;                 /* True if *pRowid really is in the table */
+
+  fts3DeleteTerms(&rc, p, pRowid, aSzDel, &bFound);
+  if( bFound && rc==SQLITE_OK ){
+    int isEmpty = 0;              /* Deleting *pRowid leaves the table empty */
+    rc = fts3IsEmpty(p, pRowid, &isEmpty);
+    if( rc==SQLITE_OK ){
+      if( isEmpty ){
+        /* Deleting this row means the whole table is empty. In this case
+        ** delete the contents of all three tables and throw away any
+        ** data in the pendingTerms hash table.  */
+        rc = fts3DeleteAll(p, 1);
+        *pnChng = 0;
+        memset(aSzDel, 0, sizeof(u32) * (p->nColumn+1) * 2);
       }else{
-        *pnDoc = *pnDoc - 1;
-      }
-      if( p->bHasDocsize ){
-        fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, &pRowid);
+        *pnChng = *pnChng - 1;
+        if( p->zContentTbl==0 ){
+          fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid);
+        }
+        if( p->bHasDocsize ){
+          fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, &pRowid);
+        }
       }
     }
   }
@@ -129785,7 +130859,7 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
   int rc = SQLITE_OK;             /* Return Code */
   int isRemove = 0;               /* True for an UPDATE or DELETE */
   u32 *aSzIns = 0;                /* Sizes of inserted documents */
-  u32 *aSzDel;                    /* Sizes of deleted documents */
+  u32 *aSzDel = 0;                /* Sizes of deleted documents */
   int nChng = 0;                  /* Net change in number of documents */
   int bInsertDone = 0;
 
@@ -129813,13 +130887,13 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
   }
 
   /* Allocate space to hold the change in document sizes */
-  aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 );
-  if( aSzIns==0 ){
+  aSzDel = sqlite3_malloc( sizeof(aSzDel[0])*(p->nColumn+1)*2 );
+  if( aSzDel==0 ){
     rc = SQLITE_NOMEM;
     goto update_out;
   }
-  aSzDel = &aSzIns[p->nColumn+1];
-  memset(aSzIns, 0, sizeof(aSzIns[0])*(p->nColumn+1)*2);
+  aSzIns = &aSzDel[p->nColumn+1];
+  memset(aSzDel, 0, sizeof(aSzDel[0])*(p->nColumn+1)*2);
 
   /* If this is an INSERT operation, or an UPDATE that modifies the rowid
   ** value, then this operation requires constraint handling.
@@ -129904,7 +130978,7 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
   }
 
  update_out:
-  sqlite3_free(aSzIns);
+  sqlite3_free(aSzDel);
   sqlite3Fts3SegmentsClose(p);
   return rc;
 }
@@ -130512,7 +131586,7 @@ static int fts3SnippetShift(
         return rc;
       }
       while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){
-        const char *ZDUMMY; int DUMMY1, DUMMY2, DUMMY3;
+        const char *ZDUMMY; int DUMMY1 = 0, DUMMY2 = 0, DUMMY3 = 0;
         rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent);
       }
       pMod->xClose(pC);
@@ -130556,8 +131630,6 @@ static int fts3SnippetText(
   int iCol = pFragment->iCol+1;   /* Query column to extract text from */
   sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */
   sqlite3_tokenizer_cursor *pC;   /* Tokenizer cursor open on zDoc/nDoc */
-  const char *ZDUMMY;             /* Dummy argument used with tokenizer */
-  int DUMMY1;                     /* Dummy argument used with tokenizer */
   
   zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol);
   if( zDoc==0 ){
@@ -130576,10 +131648,23 @@ static int fts3SnippetText(
   }
 
   while( rc==SQLITE_OK ){
-    int iBegin;                   /* Offset in zDoc of start of token */
-    int iFin;                     /* Offset in zDoc of end of token */
-    int isHighlight;              /* True for highlighted terms */
-
+    const char *ZDUMMY;           /* Dummy argument used with tokenizer */
+    int DUMMY1 = -1;              /* Dummy argument used with tokenizer */
+    int iBegin = 0;               /* Offset in zDoc of start of token */
+    int iFin = 0;                 /* Offset in zDoc of end of token */
+    int isHighlight = 0;          /* True for highlighted terms */
+
+    /* Variable DUMMY1 is initialized to a negative value above. Elsewhere
+    ** in the FTS code the variable that the third argument to xNext points to
+    ** is initialized to zero before the first (*but not necessarily
+    ** subsequent*) call to xNext(). This is done for a particular application
+    ** that needs to know whether or not the tokenizer is being used for
+    ** snippet generation or for some other purpose.
+    **
+    ** Extreme care is required when writing code to depend on this
+    ** initialization. It is not a documented part of the tokenizer interface.
+    ** If a tokenizer is used directly by any code outside of FTS, this
+    ** convention might not be respected.  */
     rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &iBegin, &iFin, &iCurrent);
     if( rc!=SQLITE_OK ){
       if( rc==SQLITE_DONE ){
@@ -131269,8 +132354,6 @@ SQLITE_PRIVATE void sqlite3Fts3Offsets(
 ){
   Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
   sqlite3_tokenizer_module const *pMod = pTab->pTokenizer->pModule;
-  const char *ZDUMMY;             /* Dummy argument used with xNext() */
-  int NDUMMY;                     /* Dummy argument used with xNext() */
   int rc;                         /* Return Code */
   int nToken;                     /* Number of tokens in query */
   int iCol;                       /* Column currently being processed */
@@ -131303,9 +132386,11 @@ SQLITE_PRIVATE void sqlite3Fts3Offsets(
   */
   for(iCol=0; iCol<pTab->nColumn; iCol++){
     sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */
-    int iStart;
-    int iEnd;
-    int iCurrent;
+    const char *ZDUMMY;           /* Dummy argument used with xNext() */
+    int NDUMMY = 0;               /* Dummy argument used with xNext() */
+    int iStart = 0;
+    int iEnd = 0;
+    int iCurrent = 0;
     const char *zDoc;
     int nDoc;
 
@@ -134869,7 +135954,7 @@ static int newRowid(Rtree *pRtree, i64 *piRowid){
 */
 static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
   int rc;                         /* Return code */
-  RtreeNode *pLeaf;               /* Leaf node containing record iDelete */
+  RtreeNode *pLeaf = 0;           /* Leaf node containing record iDelete */
   int iCell;                      /* Index of iDelete cell in pLeaf */
   RtreeNode *pRoot;               /* Root node of rtree structure */
 
@@ -135072,7 +136157,7 @@ static int rtreeUpdate(
   */
   if( rc==SQLITE_OK && nData>1 ){
     /* Insert the new record into the r-tree */
-    RtreeNode *pLeaf;
+    RtreeNode *pLeaf = 0;
 
     /* Figure out the rowid of the new row. */
     if( bHaveRowid==0 ){
@@ -136188,7 +137273,7 @@ static int icuOpen(
   nChar = nInput+1;
   pCsr = (IcuCursor *)sqlite3_malloc(
       sizeof(IcuCursor) +                /* IcuCursor */
-      nChar * sizeof(UChar) +            /* IcuCursor.aChar[] */
+      ((nChar+3)&~3) * sizeof(UChar) +   /* IcuCursor.aChar[] */
       (nChar+1) * sizeof(int)            /* IcuCursor.aOffset[] */
   );
   if( !pCsr ){
@@ -136196,7 +137281,7 @@ static int icuOpen(
   }
   memset(pCsr, 0, sizeof(IcuCursor));
   pCsr->aChar = (UChar *)&pCsr[1];
-  pCsr->aOffset = (int *)&pCsr->aChar[nChar];
+  pCsr->aOffset = (int *)&pCsr->aChar[(nChar+3)&~3];
 
   pCsr->aOffset[iOut] = iInput;
   U8_NEXT(zInput, iInput, nInput, c); 
index 5a1f9d462a8101beddfba098530756e04f3cdc7f..2cbf621047b91111b8318d5035f3f17a0d7f5ab9 100644 (file)
@@ -107,9 +107,9 @@ extern "C" {
 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
 ** [sqlite_version()] and [sqlite_source_id()].
 */
-#define SQLITE_VERSION        "3.7.14.1"
-#define SQLITE_VERSION_NUMBER 3007014
-#define SQLITE_SOURCE_ID      "2012-10-04 19:37:12 091570e46d04e84b67228e0bdbcd6e1fb60c6bdb"
+#define SQLITE_VERSION        "3.7.15"
+#define SQLITE_VERSION_NUMBER 3007015
+#define SQLITE_SOURCE_ID      "2012-12-12 13:36:53 cd0b37c52658bfdf992b1e3dc467bae1835a94ae"
 
 /*
 ** CAPI3REF: Run-Time Library Version Numbers
@@ -474,10 +474,12 @@ SQLITE_API int sqlite3_exec(
 #define SQLITE_IOERR_SHMLOCK           (SQLITE_IOERR | (20<<8))
 #define SQLITE_IOERR_SHMMAP            (SQLITE_IOERR | (21<<8))
 #define SQLITE_IOERR_SEEK              (SQLITE_IOERR | (22<<8))
+#define SQLITE_IOERR_DELETE_NOENT      (SQLITE_IOERR | (23<<8))
 #define SQLITE_LOCKED_SHAREDCACHE      (SQLITE_LOCKED |  (1<<8))
 #define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
 #define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))
 #define SQLITE_CANTOPEN_ISDIR          (SQLITE_CANTOPEN | (2<<8))
+#define SQLITE_CANTOPEN_FULLPATH       (SQLITE_CANTOPEN | (3<<8))
 #define SQLITE_CORRUPT_VTAB            (SQLITE_CORRUPT | (1<<8))
 #define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
 #define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))
@@ -855,6 +857,26 @@ struct sqlite3_io_methods {
 ** compilation of the PRAGMA fails with an error.  ^The [SQLITE_FCNTL_PRAGMA]
 ** file control occurs at the beginning of pragma statement analysis and so
 ** it is able to override built-in [PRAGMA] statements.
+**
+** <li>[[SQLITE_FCNTL_BUSYHANDLER]]
+** ^This file-control may be invoked by SQLite on the database file handle
+** shortly after it is opened in order to provide a custom VFS with access
+** to the connections busy-handler callback. The argument is of type (void **)
+** - an array of two (void *) values. The first (void *) actually points
+** to a function of type (int (*)(void *)). In order to invoke the connections
+** busy-handler, this function should be invoked with the second (void *) in
+** the array as the only argument. If it returns non-zero, then the operation
+** should be retried. If it returns zero, the custom VFS should abandon the
+** current operation.
+**
+** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
+** ^Application can invoke this file-control to have SQLite generate a
+** temporary filename using the same algorithm that is followed to generate
+** temporary filenames for TEMP tables and other internal uses.  The
+** argument should be a char** which will be filled with the filename
+** written into memory obtained from [sqlite3_malloc()].  The caller should
+** invoke [sqlite3_free()] on the result to avoid a memory leak.
+**
 ** </ul>
 */
 #define SQLITE_FCNTL_LOCKSTATE               1
@@ -871,6 +893,8 @@ struct sqlite3_io_methods {
 #define SQLITE_FCNTL_VFSNAME                12
 #define SQLITE_FCNTL_POWERSAFE_OVERWRITE    13
 #define SQLITE_FCNTL_PRAGMA                 14
+#define SQLITE_FCNTL_BUSYHANDLER            15
+#define SQLITE_FCNTL_TEMPFILENAME           16
 
 /*
 ** CAPI3REF: Mutex Handle
@@ -1567,11 +1591,39 @@ struct sqlite3_mem_methods {
 ** disabled. The default value may be changed by compiling with the
 ** [SQLITE_USE_URI] symbol defined.
 **
+** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
+** <dd> This option takes a single integer argument which is interpreted as
+** a boolean in order to enable or disable the use of covering indices for
+** full table scans in the query optimizer.  The default setting is determined
+** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
+** if that compile-time option is omitted.
+** The ability to disable the use of covering indices for full table scans
+** is because some incorrectly coded legacy applications might malfunction
+** malfunction when the optimization is enabled.  Providing the ability to
+** disable the optimization allows the older, buggy application code to work
+** without change even with newer versions of SQLite.
+**
 ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
 ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE
 ** <dd> These options are obsolete and should not be used by new code.
 ** They are retained for backwards compatibility but are now no-ops.
 ** </dl>
+**
+** [[SQLITE_CONFIG_SQLLOG]]
+** <dt>SQLITE_CONFIG_SQLLOG
+** <dd>This option is only available if sqlite is compiled with the
+** SQLITE_ENABLE_SQLLOG pre-processor macro defined. The first argument should
+** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int).
+** The second should be of type (void*). The callback is invoked by the library
+** in three separate circumstances, identified by the value passed as the
+** fourth parameter. If the fourth parameter is 0, then the database connection
+** passed as the second argument has just been opened. The third argument
+** points to a buffer containing the name of the main database file. If the
+** fourth parameter is 1, then the SQL statement that the third parameter
+** points to has just been executed. Or, if the fourth parameter is 2, then
+** the connection being passed as the second parameter is being closed. The
+** third parameter is passed NULL In this case.
+** </dl>
 */
 #define SQLITE_CONFIG_SINGLETHREAD  1  /* nil */
 #define SQLITE_CONFIG_MULTITHREAD   2  /* nil */
@@ -1592,6 +1644,8 @@ struct sqlite3_mem_methods {
 #define SQLITE_CONFIG_URI          17  /* int */
 #define SQLITE_CONFIG_PCACHE2      18  /* sqlite3_pcache_methods2* */
 #define SQLITE_CONFIG_GETPCACHE2   19  /* sqlite3_pcache_methods2* */
+#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20  /* int */
+#define SQLITE_CONFIG_SQLLOG       21  /* xSqllog, void* */
 
 /*
 ** CAPI3REF: Database Connection Configuration Options
@@ -2600,7 +2654,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **     an error)^. 
 **     ^If "ro" is specified, then the database is opened for read-only 
 **     access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the 
-**     third argument to sqlite3_prepare_v2(). ^If the mode option is set to 
+**     third argument to sqlite3_open_v2(). ^If the mode option is set to 
 **     "rw", then the database is opened for read-write (but not create) 
 **     access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had 
 **     been set. ^Value "rwc" is equivalent to setting both 
@@ -2752,6 +2806,11 @@ SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int
 ** However, the error string might be overwritten or deallocated by
 ** subsequent calls to other SQLite interface functions.)^
 **
+** ^The sqlite3_errstr() interface returns the English-language text
+** that describes the [result code], as UTF-8.
+** ^(Memory to hold the error message string is managed internally
+** and must not be freed by the application)^.
+**
 ** When the serialized [threading mode] is in use, it might be the
 ** case that a second error occurs on a separate thread in between
 ** the time of the first error and the call to these interfaces.
@@ -2770,6 +2829,7 @@ SQLITE_API int sqlite3_errcode(sqlite3 *db);
 SQLITE_API int sqlite3_extended_errcode(sqlite3 *db);
 SQLITE_API const char *sqlite3_errmsg(sqlite3*);
 SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
+SQLITE_API const char *sqlite3_errstr(int);
 
 /*
 ** CAPI3REF: SQL Statement Object
@@ -4732,6 +4792,9 @@ SQLITE_API void *sqlite3_update_hook(
 ** future releases of SQLite.  Applications that care about shared
 ** cache setting should set it explicitly.
 **
+** This interface is threadsafe on processors where writing a
+** 32-bit integer is atomic.
+**
 ** See Also:  [SQLite Shared-Cache Mode]
 */
 SQLITE_API int sqlite3_enable_shared_cache(int);
index d4d401ee32a7a8240a4bc5f1eca3fcbf936b8ba0..73f81686e23ed835eb8c5b71b9b31fb92d0b00ad 100644 (file)
@@ -18,7 +18,7 @@ DIR_sparc := sparc
 SRC_CC      = manager.cc l4.cc
 SRC_C      += spinlock.c mutex.c condvar.c rwlock.c errno.c specific.c \
               semaphore.c attr.c barrier.c join.c pthread.c \
-              cancel.c ptcleanup.c errno-loc.c \
+              cancel.c ptcleanup.c errno-loc.c signals.c \
               sysdeps/$(DIR_$(ARCH))/pspinlock.c
 SRC_C_libpthread.a += libc_pthread_init.c
 SRC_S       = tramp-$(ARCH).S
diff --git a/l4/pkg/uclibc/lib/libpthread/src/signals.c b/l4/pkg/uclibc/lib/libpthread/src/signals.c
new file mode 100644 (file)
index 0000000..3ee847c
--- /dev/null
@@ -0,0 +1,34 @@
+/* Handling of signals */
+
+#include <signal.h>
+#include <errno.h>
+#include <pthread-l4.h>
+#include <l4/sys/thread.h>
+
+int pthread_kill(pthread_t thread, int signo);
+int pthread_kill(pthread_t thread, int signo)
+{
+  l4_cap_idx_t c = pthread_getl4cap(thread);
+
+  if (signo >= _NSIG)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  if (l4_is_invalid_cap(c))
+    {
+      errno = ESRCH;
+      return -1;
+    }
+
+  int x = l4_error(l4_thread_ex_regs(c, ~0UL, ~0UL,
+                                     L4_THREAD_EX_REGS_TRIGGER_EXCEPTION));
+  if (x)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  return x ? -1 : 0;
+}
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e44eadf3d5fb17c8c5abe2dd6117dc131767617c 100644 (file)
@@ -0,0 +1,12 @@
+
+// prototype from
+// pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigthread.h
+
+#pragma once
+
+#if !defined _SIGNAL_H && !defined _PTHREAD_H
+# error "Never include this file directly.  Use <pthread.h> instead"
+#endif
+
+/* Send signal SIGNO to the given thread. */
+extern int pthread_kill (pthread_t __threadid, int __signo) __THROW;
index ee29788dd622298c0523cf2325e64e52f77db638..980b33758e7df62883ebc7579c5334d467f887b3 100644 (file)
@@ -880,7 +880,7 @@ distcheck: dist
        *.zip*) \
          unzip $(distdir).zip ;;\
        esac
-       chmod -R a-w $(distdir); chmod a+w $(distdir)
+       chmod -R a-w $(distdir); chmod u+w $(distdir)
        mkdir $(distdir)/_build
        mkdir $(distdir)/_inst
        chmod a-w $(distdir)
index c565ae059bd4066d9a298690976730a42e34fcc1..cc8a266ff302d1d380839b9929a8d3f1b80ec349 100644 (file)
@@ -1,8 +1,8 @@
 VERSION = 3
-PATCHLEVEL = 5
+PATCHLEVEL = 7
 SUBLEVEL = 0
 EXTRAVERSION =
-NAME = Saber-toothed Squirrel
+NAME = Terrified Chipmunk
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
@@ -350,12 +350,22 @@ AFLAGS_KERNEL     =
 CFLAGS_GCOV    = -fprofile-arcs -ftest-coverage
 
 
+# Use USERINCLUDE when you must reference the UAPI directories only.
+USERINCLUDE    := \
+               -I$(srctree)/arch/$(hdr-arch)/include/uapi \
+               -Iarch/$(hdr-arch)/include/generated/uapi \
+               -I$(srctree)/include/uapi \
+               -Iinclude/generated/uapi \
+                -include $(srctree)/include/linux/kconfig.h
+
 # Use LINUXINCLUDE when you must reference the include/ directory.
 # Needed to be compatible with the O= option
-LINUXINCLUDE    := -I$(srctree)/arch/$(hdr-arch)/include \
-                   -Iarch/$(hdr-arch)/include/generated -Iinclude \
-                   $(if $(KBUILD_SRC), -I$(srctree)/include) \
-                   -include $(srctree)/include/linux/kconfig.h
+LINUXINCLUDE    := \
+               -I$(srctree)/arch/$(hdr-arch)/include \
+               -Iarch/$(hdr-arch)/include/generated \
+               $(if $(KBUILD_SRC), -I$(srctree)/include) \
+               -Iinclude \
+               $(USERINCLUDE)
 
 KBUILD_CPPFLAGS := -D__KERNEL__
 
@@ -427,7 +437,9 @@ endif
 PHONY += asm-generic
 asm-generic:
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.asm-generic \
-                   obj=arch/$(SRCARCH)/include/generated/asm
+                   src=asm obj=arch/$(SRCARCH)/include/generated/asm
+       $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.asm-generic \
+                   src=uapi/asm obj=arch/$(SRCARCH)/include/generated/uapi/asm
 
 # To make sure we do not include .config for any of the *config targets
 # catch them early, and hand them over to scripts/kconfig/Makefile
@@ -437,9 +449,11 @@ asm-generic:
 # Detect when mixed targets is specified, and make a second invocation
 # of make so .config is not included in this case either (for *config).
 
+version_h := include/generated/uapi/linux/version.h
+
 no-dot-config-targets := clean mrproper distclean \
                         cscope gtags TAGS tags help %docs check% coccicheck \
-                        include/linux/version.h headers_% archheaders archscripts \
+                        $(version_h) headers_% archheaders archscripts \
                         kernelversion %src-pkg
 
 config-targets := 0
@@ -535,11 +549,11 @@ PHONY += include/config/auto.conf
 
 include/config/auto.conf:
        $(Q)test -e include/generated/autoconf.h -a -e $@ || (          \
-       echo;                                                           \
-       echo "  ERROR: Kernel configuration is invalid.";               \
-       echo "         include/generated/autoconf.h or $@ are missing.";\
-       echo "         Run 'make oldconfig && make prepare' on kernel src to fix it.";  \
-       echo;                                                           \
+       echo >&2;                                                       \
+       echo >&2 "  ERROR: Kernel configuration is invalid.";           \
+       echo >&2 "         include/generated/autoconf.h or $@ are missing.";\
+       echo >&2 "         Run 'make oldconfig && make prepare' on kernel src to fix it.";      \
+       echo >&2 ;                                                      \
        /bin/false)
 
 endif # KBUILD_EXTMOD
@@ -609,7 +623,11 @@ KBUILD_CFLAGS      += $(call cc-option, -femit-struct-debug-baseonly)
 endif
 
 ifdef CONFIG_FUNCTION_TRACER
-KBUILD_CFLAGS  += -pg
+ifdef CONFIG_HAVE_FENTRY
+CC_USING_FENTRY        := $(call cc-option, -mfentry -DCC_USING_FENTRY)
+endif
+KBUILD_CFLAGS  += -pg $(CC_USING_FENTRY)
+KBUILD_AFLAGS  += $(CC_USING_FENTRY)
 ifdef CONFIG_DYNAMIC_FTRACE
        ifdef CONFIG_HAVE_C_RECORDMCOUNT
                BUILD_C_RECORDMCOUNT := y
@@ -648,22 +666,9 @@ ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC)), y)
 endif
 
 # Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments
-# But warn user when we do so
-warn-assign = \
-$(warning "WARNING: Appending $$K$(1) ($(K$(1))) from $(origin K$(1)) to kernel $$$(1)")
-
-ifneq ($(KCPPFLAGS),)
-        $(call warn-assign,CPPFLAGS)
-        KBUILD_CPPFLAGS += $(KCPPFLAGS)
-endif
-ifneq ($(KAFLAGS),)
-        $(call warn-assign,AFLAGS)
-        KBUILD_AFLAGS += $(KAFLAGS)
-endif
-ifneq ($(KCFLAGS),)
-        $(call warn-assign,CFLAGS)
-        KBUILD_CFLAGS += $(KCFLAGS)
-endif
+KBUILD_CPPFLAGS += $(KCPPFLAGS)
+KBUILD_AFLAGS += $(KAFLAGS)
+KBUILD_CFLAGS += $(KCFLAGS)
 
 # Use --build-id when available.
 LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\
@@ -714,6 +719,17 @@ endif # INSTALL_MOD_STRIP
 export mod_strip_cmd
 
 
+ifeq ($(CONFIG_MODULE_SIG),y)
+MODSECKEY = ./signing_key.priv
+MODPUBKEY = ./signing_key.x509
+export MODPUBKEY
+mod_sign_cmd = perl $(srctree)/scripts/sign-file $(MODSECKEY) $(MODPUBKEY)
+else
+mod_sign_cmd = true
+endif
+export mod_sign_cmd
+
+
 ifeq ($(KBUILD_EXTMOD),)
 core-y         += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
 
@@ -796,8 +812,8 @@ prepare3: include/config/kernel.release
 ifneq ($(KBUILD_SRC),)
        @$(kecho) '  Using $(srctree) as source for kernel'
        $(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \
-               echo "  $(srctree) is not clean, please run 'make mrproper'"; \
-               echo "  in the '$(srctree)' directory.";\
+               echo >&2 "  $(srctree) is not clean, please run 'make mrproper'"; \
+               echo >&2 "  in the '$(srctree)' directory.";\
                /bin/false; \
        fi;
 endif
@@ -805,7 +821,7 @@ endif
 # prepare2 creates a makefile if using a separate output directory
 prepare2: prepare3 outputmakefile asm-generic
 
-prepare1: prepare2 include/linux/version.h include/generated/utsrelease.h \
+prepare1: prepare2 $(version_h) include/generated/utsrelease.h \
                    include/config/auto.conf
        $(cmd_crmodverdir)
 
@@ -838,7 +854,7 @@ define filechk_version.h
        echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';)
 endef
 
-include/linux/version.h: $(srctree)/Makefile FORCE
+$(version_h): $(srctree)/Makefile FORCE
        $(call filechk,version.h)
 
 include/generated/utsrelease.h: include/config/kernel.release FORCE
@@ -883,7 +899,7 @@ PHONY += archscripts
 archscripts:
 
 PHONY += __headers
-__headers: include/linux/version.h scripts_basic asm-generic archheaders archscripts FORCE
+__headers: $(version_h) scripts_basic asm-generic archheaders archscripts FORCE
        $(Q)$(MAKE) $(build)=scripts build_unifdef
 
 PHONY += headers_install_all
@@ -892,10 +908,10 @@ headers_install_all:
 
 PHONY += headers_install
 headers_install: __headers
-       $(if $(wildcard $(srctree)/arch/$(hdr-arch)/include/asm/Kbuild),, \
-       $(error Headers not exportable for the $(SRCARCH) architecture))
-       $(Q)$(MAKE) $(hdr-inst)=include
-       $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/asm $(hdr-dst)
+       $(if $(wildcard $(srctree)/arch/$(hdr-arch)/include/uapi/asm/Kbuild),, \
+         $(error Headers not exportable for the $(SRCARCH) architecture))
+       $(Q)$(MAKE) $(hdr-inst)=include/uapi
+       $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi/asm $(hdr-dst)
 
 PHONY += headers_check_all
 headers_check_all: headers_install_all
@@ -903,8 +919,8 @@ headers_check_all: headers_install_all
 
 PHONY += headers_check
 headers_check: headers_install
-       $(Q)$(MAKE) $(hdr-inst)=include HDRCHECK=1
-       $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/asm $(hdr-dst) HDRCHECK=1
+       $(Q)$(MAKE) $(hdr-inst)=include/uapi HDRCHECK=1
+       $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi/asm $(hdr-dst) HDRCHECK=1
 
 # ---------------------------------------------------------------------------
 # Modules
@@ -971,11 +987,11 @@ else # CONFIG_MODULES
 # ---------------------------------------------------------------------------
 
 modules modules_install: FORCE
-       @echo
-       @echo "The present kernel configuration has modules disabled."
-       @echo "Type 'make config' and enable loadable module support."
-       @echo "Then build a kernel with module support enabled."
-       @echo
+       @echo >&2
+       @echo >&2 "The present kernel configuration has modules disabled."
+       @echo >&2 "Type 'make config' and enable loadable module support."
+       @echo >&2 "Then build a kernel with module support enabled."
+       @echo >&2
        @exit 1
 
 endif # CONFIG_MODULES
@@ -993,9 +1009,11 @@ CLEAN_DIRS  += $(MODVERDIR)
 # Directories & files removed with 'make mrproper'
 MRPROPER_DIRS  += include/config usr/include include/generated          \
                   arch/*/include/generated
-MRPROPER_FILES += .config .config.old .version .old_version             \
-                  include/linux/version.h                               \
-                 Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS
+MRPROPER_FILES += .config .config.old .version .old_version $(version_h) \
+                 Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS \
+                 signing_key.priv signing_key.x509 x509.genkey         \
+                 extra_certificates signing_key.x509.keyid             \
+                 signing_key.x509.signer
 
 # clean - Delete most, but leave enough to build external modules
 #
@@ -1239,6 +1257,7 @@ clean: $(clean-dirs)
        $(call cmd,rmfiles)
        @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
                \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
+               -o -name '*.ko.*' \
                -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
                -o -name '*.symtypes' -o -name 'modules.order' \
                -o -name modules.builtin -o -name '.tmp_*.o.*' \
@@ -1302,10 +1321,12 @@ kernelversion:
 
 # Clear a bunch of variables before executing the submake
 tools/: FORCE
-       $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= -C $(src)/tools/
+       $(Q)mkdir -p $(objtree)/tools
+       $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= O=$(objtree) subdir=tools -C $(src)/tools/
 
 tools/%: FORCE
-       $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= -C $(src)/tools/ $*
+       $(Q)mkdir -p $(objtree)/tools
+       $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= O=$(objtree) subdir=tools -C $(src)/tools/ $*
 
 # Single targets
 # ---------------------------------------------------------------------------
index cebd46b7d860f58c014e25f615075920fade1ec5..3d87ce199d0032571691fc5e715282f2d832f85b 100644 (file)
@@ -1,3 +1,3 @@
 
-kconfig taken from vanilla Linux 3.5, and slightly patched.
+kconfig taken from vanilla Linux 3.7, and slightly patched.
 
index 6a3ee981931d3c2b4438cff1d220ec2e8039bd7e..978416dd31ca0efeacfd938e961b241aca7633af 100644 (file)
@@ -98,24 +98,24 @@ try-run = $(shell set -e;           \
 # Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,)
 
 as-option = $(call try-run,\
-       $(CC) $(KBUILD_CFLAGS) $(1) -c -xassembler /dev/null -o "$$TMP",$(1),$(2))
+       $(CC) $(KBUILD_CFLAGS) $(1) -c -x assembler /dev/null -o "$$TMP",$(1),$(2))
 
 # as-instr
 # Usage: cflags-y += $(call as-instr,instr,option1,option2)
 
 as-instr = $(call try-run,\
-       printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" -,$(2),$(3))
+       printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3))
 
 # cc-option
 # Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)
 
 cc-option = $(call try-run,\
-       $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",$(1),$(2))
+       $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2))
 
 # cc-option-yn
 # Usage: flag := $(call cc-option-yn,-march=winchip-c6)
 cc-option-yn = $(call try-run,\
-       $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",y,n)
+       $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n)
 
 # cc-option-align
 # Prefix align with either -falign or -malign
@@ -125,7 +125,7 @@ cc-option-align = $(subst -functions=0,,\
 # cc-disable-warning
 # Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable)
 cc-disable-warning = $(call try-run,\
-       $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -xc /dev/null -o "$$TMP",-Wno-$(strip $(1)))
+       $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1)))
 
 # cc-version
 # Usage gcc-ver := $(call cc-version)
@@ -143,7 +143,7 @@ cc-ifversion = $(shell [ $(call cc-version, $(CC)) $(1) $(2) ] && echo $(3))
 # cc-ldoption
 # Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both)
 cc-ldoption = $(call try-run,\
-       $(CC) $(1) -nostdlib -xc /dev/null -o "$$TMP",$(1),$(2))
+       $(CC) $(1) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2))
 
 # ld-option
 # Usage: LDFLAGS += $(call ld-option, -X)
@@ -209,7 +209,7 @@ endif
 # >$< substitution to preserve $ when reloading .cmd file
 # note: when using inline perl scripts [perl -e '...$$t=1;...']
 # in $(cmd_xxx) double $$ your perl vars
-make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))
+make-cmd = $(subst \\,\\\\,$(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))))
 
 # Find any prerequisites that is newer than target or that does not exist.
 # PHONY targets skipped in both cases.
index a55b0067758a0fb5b35115dbc5f1affa35e69719..01e7adb838d93287d391ec4fee925936115877c1 100644 (file)
@@ -16,8 +16,10 @@ hostprogs-$(CONFIG_VT)           += conmakehash
 hostprogs-$(CONFIG_IKCONFIG)     += bin2c
 hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount
 hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable
+hostprogs-$(CONFIG_ASN1)        += asn1_compiler
 
 HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include
+HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include
 
 always         := $(hostprogs-y) $(hostprogs-m)
 
index ff1720d28d0c80be0df2e1d0ae8f5697794e36e9..0e801c3cdaf8f4173ce5abbf9cee0554374bfbc7 100644 (file)
@@ -354,6 +354,17 @@ quiet_cmd_cpp_lds_S = LDS     $@
 $(obj)/%.lds: $(src)/%.lds.S FORCE
        $(call if_changed_dep,cpp_lds_S)
 
+# ASN.1 grammar
+# ---------------------------------------------------------------------------
+quiet_cmd_asn1_compiler = ASN.1   $@
+      cmd_asn1_compiler = $(objtree)/scripts/asn1_compiler $< \
+                               $(subst .h,.c,$@) $(subst .c,.h,$@)
+
+.PRECIOUS: $(objtree)/$(obj)/%-asn1.c $(objtree)/$(obj)/%-asn1.h
+
+$(obj)/%-asn1.c $(obj)/%-asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
+       $(call cmd,asn1_compiler)
+
 # Build the compiled-in targets
 # ---------------------------------------------------------------------------
 
index d3bae5e7b6018d7429c518681a706179e00c6d81..06ba4a70bd4d0db666a4b50b90b73f33e7c6b81e 100644 (file)
@@ -3,13 +3,12 @@
 #
 # header-y  - list files to be installed. They are preprocessed
 #             to remove __KERNEL__ section of the file
-# objhdr-y  - Same as header-y but for generated files
-# genhdr-y  - Same as objhdr-y but in a generated/ directory
+# genhdr-y  - Same as header-y but in a generated/ directory
 #
 # ==========================================================================
 
 # called may set destination dir (when installing to asm/)
-_dst := $(if $(dst),$(dst),$(obj))
+_dst := $(or $(destination-y),$(dst),$(obj))
 
 # generated header directory
 gen := $(if $(gen),$(gen),$(subst include/,include/generated/,$(obj)))
@@ -17,49 +16,64 @@ gen := $(if $(gen),$(gen),$(subst include/,include/generated/,$(obj)))
 kbuild-file := $(srctree)/$(obj)/Kbuild
 include $(kbuild-file)
 
-_dst := $(if $(destination-y),$(destination-y),$(_dst))
+old-kbuild-file := $(srctree)/$(subst uapi/,,$(obj))/Kbuild
+ifneq ($(wildcard $(old-kbuild-file)),)
+include $(old-kbuild-file)
+endif
 
 include scripts/Kbuild.include
 
-install       := $(INSTALL_HDR_PATH)/$(_dst)
+installdir    := $(INSTALL_HDR_PATH)/$(subst uapi/,,$(_dst))
 
 header-y      := $(sort $(header-y))
 subdirs       := $(patsubst %/,%,$(filter %/, $(header-y)))
 header-y      := $(filter-out %/, $(header-y))
 
 # files used to track state of install/check
-install-file  := $(install)/.install
-check-file    := $(install)/.check
+install-file  := $(installdir)/.install
+check-file    := $(installdir)/.check
 
 # generic-y list all files an architecture uses from asm-generic
 # Use this to build a list of headers which require a wrapper
 wrapper-files := $(filter $(header-y), $(generic-y))
 
+srcdir        := $(srctree)/$(obj)
+gendir        := $(objtree)/$(gen)
+
+oldsrcdir     := $(srctree)/$(subst /uapi,,$(obj))
+
 # all headers files for this dir
 header-y      := $(filter-out $(generic-y), $(header-y))
-all-files     := $(header-y) $(objhdr-y) $(genhdr-y) $(wrapper-files)
-input-files   := $(addprefix $(srctree)/$(obj)/,$(header-y)) \
-                 $(addprefix $(objtree)/$(obj)/,$(objhdr-y)) \
-                 $(addprefix $(objtree)/$(gen)/,$(genhdr-y))
-output-files  := $(addprefix $(install)/, $(all-files))
+all-files     := $(header-y) $(genhdr-y) $(wrapper-files)
+output-files  := $(addprefix $(installdir)/, $(all-files))
+
+input-files   := $(foreach hdr, $(header-y), \
+                  $(or \
+                       $(wildcard $(srcdir)/$(hdr)), \
+                       $(wildcard $(oldsrcdir)/$(hdr)), \
+                       $(error Missing UAPI file $(srcdir)/$(hdr)) \
+                  )) \
+                $(foreach hdr, $(genhdr-y), \
+                  $(or \
+                       $(wildcard $(gendir)/$(hdr)), \
+                       $(error Missing generated UAPI file $(gendir)/$(hdr)) \
+                  ))
 
 # Work out what needs to be removed
-oldheaders    := $(patsubst $(install)/%,%,$(wildcard $(install)/*.h))
+oldheaders    := $(patsubst $(installdir)/%,%,$(wildcard $(installdir)/*.h))
 unwanted      := $(filter-out $(all-files),$(oldheaders))
 
 # Prefix unwanted with full paths to $(INSTALL_HDR_PATH)
-unwanted-file := $(addprefix $(install)/, $(unwanted))
+unwanted-file := $(addprefix $(installdir)/, $(unwanted))
 
 printdir = $(patsubst $(INSTALL_HDR_PATH)/%/,%,$(dir $@))
 
 quiet_cmd_install = INSTALL $(printdir) ($(words $(all-files))\
                             file$(if $(word 2, $(all-files)),s))
       cmd_install = \
-        $(PERL) $< $(srctree)/$(obj) $(install) $(SRCARCH) $(header-y); \
-        $(PERL) $< $(objtree)/$(obj) $(install) $(SRCARCH) $(objhdr-y); \
-        $(PERL) $< $(objtree)/$(gen) $(install) $(SRCARCH) $(genhdr-y); \
+        $(PERL) $< $(installdir) $(SRCARCH) $(input-files); \
         for F in $(wrapper-files); do                                   \
-                echo "\#include <asm-generic/$$F>" > $(install)/$$F;    \
+                echo "\#include <asm-generic/$$F>" > $(installdir)/$$F;    \
         done;                                                           \
         touch $@
 
@@ -70,7 +84,7 @@ quiet_cmd_check = CHECK   $(printdir) ($(words $(all-files)) files)
 # Headers list can be pretty long, xargs helps to avoid
 # the "Argument list too long" error.
       cmd_check = for f in $(all-files); do                          \
-                  echo "$(install)/$${f}"; done                      \
+                  echo "$(installdir)/$${f}"; done                      \
                   | xargs                                            \
                   $(PERL) $< $(INSTALL_HDR_PATH)/include $(SRCARCH); \
                  touch $@
index efa5d940e6324caa0aa120343043b89475502e74..ecbb44797e28226e85027c277435d053415aec8c 100644 (file)
@@ -9,15 +9,16 @@ include scripts/Kbuild.include
 
 #
 
-__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
+__modules := $(sort $(shell grep -h '\.ko$$' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
 modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o)))
 
 PHONY += $(modules)
 __modinst: $(modules)
        @:
 
+# Don't stop modules_install if we can't sign external modules.
 quiet_cmd_modules_install = INSTALL $@
-      cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@)
+      cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@) $(patsubst %,|| true,$(KBUILD_EXTMOD))
 
 # Modules built outside the kernel source tree go into extra by default
 INSTALL_MOD_DIR ?= extra
index 08dce14f2dc862d78d30744e0e7cd7b4e915cc64..a1cb0222ebe642b6fd91093f2a01bd301b026e6e 100644 (file)
@@ -60,7 +60,7 @@ kernelsymfile := $(objtree)/Module.symvers
 modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers
 
 # Step 1), find all modules listed in $(MODVERDIR)/
-__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
+__modules := $(sort $(shell grep -h '\.ko$$' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
 modules   := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o)))
 
 # Stop after building .o files if NOFINAL is set. Makes compile tests quicker
index ee120d441565422f0a6283b55ab5258fb61de9e7..be603c4fef624669ea2bac84e1f41311713a8065 100644 (file)
@@ -7,7 +7,6 @@ config*
 *.tab.h
 zconf.hash.c
 *.moc
-lkc_defs.h
 gconf.glade.h
 *.pot
 *.mo
index 79662658fb9158af1d7b3ee43dba0cfab0aa42cf..3091794e935488c797e73207e6d0b82a7dbf99b4 100644 (file)
@@ -76,11 +76,17 @@ PHONY += allnoconfig allyesconfig allmodconfig alldefconfig randconfig
 allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf
        $< --$@ $(Kconfig)
 
-PHONY += listnewconfig oldnoconfig savedefconfig defconfig
+PHONY += listnewconfig olddefconfig oldnoconfig savedefconfig defconfig
 
-listnewconfig oldnoconfig: $(obj)/conf
+listnewconfig olddefconfig: $(obj)/conf
        $< --$@ $(Kconfig)
 
+# oldnoconfig is an alias of olddefconfig, because people already are dependent
+# on its behavior(sets new symbols to their default value but not 'n') with the
+# counter-intuitive name.
+oldnoconfig: $(obj)/conf
+       $< --olddefconfig $(Kconfig)
+
 savedefconfig: $(obj)/conf
        $< --$@=defconfig $(Kconfig)
 
@@ -114,7 +120,7 @@ help:
        @echo  '  alldefconfig    - New config with all symbols set to default'
        @echo  '  randconfig      - New config with random answer to all options'
        @echo  '  listnewconfig   - List new options'
-       @echo  '  oldnoconfig     - Same as silentoldconfig but set new symbols to n (unset)'
+       @echo  '  olddefconfig    - Same as silentoldconfig but sets new symbols to their default value'
 
 # lxdialog stuff
 check-lxdialog  := $(srctree)/$(src)/lxdialog/check-lxdialog.sh
@@ -234,12 +240,12 @@ $(obj)/.tmp_qtcheck:
                if [ -f $$d/include/qconfig.h ]; then dir=$$d; break; fi; \
              done; \
              if [ -z "$$dir" ]; then \
-               echo "*"; \
-               echo "* Unable to find any QT installation. Please make sure that"; \
-               echo "* the QT4 or QT3 development package is correctly installed and"; \
-               echo "* either qmake can be found or install pkg-config or set"; \
-               echo "* the QTDIR environment variable to the correct location."; \
-               echo "*"; \
+               echo >&2 "*"; \
+               echo >&2 "* Unable to find any QT installation. Please make sure that"; \
+               echo >&2 "* the QT4 or QT3 development package is correctly installed and"; \
+               echo >&2 "* either qmake can be found or install pkg-config or set"; \
+               echo >&2 "* the QTDIR environment variable to the correct location."; \
+               echo >&2 "*"; \
                false; \
              fi; \
              libpath=$$dir/lib; lib=qt; osdir=""; \
@@ -260,8 +266,8 @@ $(obj)/.tmp_qtcheck:
        else \
          cflags="\$$(shell pkg-config QtCore QtGui Qt3Support --cflags)"; \
          libs="\$$(shell pkg-config QtCore QtGui Qt3Support --libs)"; \
-         binpath="\$$(shell pkg-config QtCore --variable=prefix)"; \
-         moc="$$binpath/bin/moc"; \
+         moc="\$$(shell pkg-config QtCore --variable=moc_location)"; \
+         [ -n "$$moc" ] || moc="\$$(shell pkg-config QtCore --variable=prefix)/bin/moc"; \
        fi; \
        echo "KC_QT_CFLAGS=$$cflags" > $@; \
        echo "KC_QT_LIBS=$$libs" >> $@; \
@@ -279,17 +285,17 @@ $(obj)/.tmp_gtkcheck:
                if `pkg-config --atleast-version=2.0.0 gtk+-2.0`; then                  \
                        touch $@;                                                               \
                else                                                                    \
-                       echo "*";                                                       \
-                       echo "* GTK+ is present but version >= 2.0.0 is required.";     \
-                       echo "*";                                                       \
+                       echo >&2 "*";                                                   \
+                       echo >&2 "* GTK+ is present but version >= 2.0.0 is required."; \
+                       echo >&2 "*";                                                   \
                        false;                                                          \
                fi                                                                      \
        else                                                                            \
-               echo "*";                                                               \
-               echo "* Unable to find the GTK+ installation. Please make sure that";   \
-               echo "* the GTK+ 2.0 development package is correctly installed...";    \
-               echo "* You need gtk+-2.0, glib-2.0 and libglade-2.0.";                 \
-               echo "*";                                                               \
+               echo >&2 "*";                                                           \
+               echo >&2 "* Unable to find the GTK+ installation. Please make sure that";       \
+               echo >&2 "* the GTK+ 2.0 development package is correctly installed...";        \
+               echo >&2 "* You need gtk+-2.0, glib-2.0 and libglade-2.0.";             \
+               echo >&2 "*";                                                           \
                false;                                                                  \
        fi
 endif
@@ -298,8 +304,11 @@ $(obj)/zconf.tab.o: $(obj)/zconf.lex.c $(obj)/zconf.hash.c
 
 $(obj)/qconf.o: $(obj)/qconf.moc
 
-$(obj)/%.moc: $(src)/%.h
-       $(KC_QT_MOC) -i $< -o $@
+quiet_cmd_moc = MOC     $@
+      cmd_moc = $(KC_QT_MOC) -i $< -o $@
+
+$(obj)/%.moc: $(src)/%.h $(obj)/.tmp_qtcheck
+       $(call cmd,moc)
 
 # Extract gconf menu items for I18N support
 $(obj)/gconf.glade.h: $(obj)/gconf.glade
index fa59cbf9d62cf464515662c8ae1e98e82eafc99d..854d9c7c675ca4782702e83e1fa04b17aa47d6f8 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 # Needed for systems without gettext
-$* -xc -o /dev/null - > /dev/null 2>&1 << EOF
+$* -x c -o /dev/null - > /dev/null 2>&1 << EOF
 #include <libintl.h>
 int main()
 {
index 0dc4a2c779b119ec51e2eb5b3f17c5a4d02645fb..4da3b4adfad233cb97728b0e0278f8143919cee3 100644 (file)
@@ -32,7 +32,7 @@ enum input_mode {
        defconfig,
        savedefconfig,
        listnewconfig,
-       oldnoconfig,
+       olddefconfig,
 } input_mode = oldaskconfig;
 
 static int indent = 1;
@@ -365,7 +365,7 @@ static void conf(struct menu *menu)
                case P_MENU:
                        if ((input_mode == silentoldconfig ||
                             input_mode == listnewconfig ||
-                            input_mode == oldnoconfig) &&
+                            input_mode == olddefconfig) &&
                            rootEntry != menu) {
                                check_conf(menu);
                                return;
@@ -429,7 +429,7 @@ static void check_conf(struct menu *menu)
                                if (sym->name && !sym_is_choice_value(sym)) {
                                        printf("%s%s\n", CONFIG_, sym->name);
                                }
-                       } else if (input_mode != oldnoconfig) {
+                       } else if (input_mode != olddefconfig) {
                                if (!conf_cnt++)
                                        printf(_("*\n* Restart config...\n*\n"));
                                rootEntry = menu_get_parent_menu(menu);
@@ -454,7 +454,13 @@ static struct option long_opts[] = {
        {"alldefconfig",    no_argument,       NULL, alldefconfig},
        {"randconfig",      no_argument,       NULL, randconfig},
        {"listnewconfig",   no_argument,       NULL, listnewconfig},
-       {"oldnoconfig",     no_argument,       NULL, oldnoconfig},
+       {"olddefconfig",    no_argument,       NULL, olddefconfig},
+       /*
+        * oldnoconfig is an alias of olddefconfig, because people already
+        * are dependent on its behavior(sets new symbols to their default
+        * value but not 'n') with the counter-intuitive name.
+        */
+       {"oldnoconfig",     no_argument,       NULL, olddefconfig},
        {NULL, 0, NULL, 0}
 };
 
@@ -467,7 +473,8 @@ static void conf_usage(const char *progname)
        printf("  --oldaskconfig          Start a new configuration using a line-oriented program\n");
        printf("  --oldconfig             Update a configuration using a provided .config as base\n");
        printf("  --silentoldconfig       Same as oldconfig, but quietly, additionally update deps\n");
-       printf("  --oldnoconfig           Same as silentoldconfig but set new symbols to no\n");
+       printf("  --olddefconfig          Same as silentoldconfig but sets new symbols to their default value\n");
+       printf("  --oldnoconfig           An alias of olddefconfig\n");
        printf("  --defconfig <file>      New config with default defined in <file>\n");
        printf("  --savedefconfig <file>  Save the minimal current configuration to <file>\n");
        printf("  --allnoconfig           New config where all options are answered with no\n");
@@ -520,7 +527,7 @@ int main(int ac, char **av)
                case allmodconfig:
                case alldefconfig:
                case listnewconfig:
-               case oldnoconfig:
+               case olddefconfig:
                        break;
                case '?':
                        conf_usage(progname);
@@ -565,7 +572,7 @@ int main(int ac, char **av)
        case oldaskconfig:
        case oldconfig:
        case listnewconfig:
-       case oldnoconfig:
+       case olddefconfig:
                conf_read(NULL);
                break;
        case allnoconfig:
@@ -645,7 +652,7 @@ int main(int ac, char **av)
                /* fall through */
        case oldconfig:
        case listnewconfig:
-       case oldnoconfig:
+       case olddefconfig:
        case silentoldconfig:
                /* Update until a loop caused no more changes */
                do {
@@ -653,7 +660,7 @@ int main(int ac, char **av)
                        check_conf(&rootmenu);
                } while (conf_cnt &&
                         (input_mode != listnewconfig &&
-                         input_mode != oldnoconfig));
+                         input_mode != olddefconfig));
                break;
        }
 
index bcc2719d9c1222207370a9ca4f796837098d2636..13d89e32a14895c7c5a5a134327489c6d085d840 100644 (file)
@@ -182,10 +182,66 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
        return 0;
 }
 
+#define LINE_GROWTH 16
+static int add_byte(int c, char **lineptr, size_t slen, size_t *n)
+{
+       char *nline;
+       size_t new_size = slen + 1;
+       if (new_size > *n) {
+               new_size += LINE_GROWTH - 1;
+               new_size *= 2;
+               nline = realloc(*lineptr, new_size);
+               if (!nline)
+                       return -1;
+
+               *lineptr = nline;
+               *n = new_size;
+       }
+
+       (*lineptr)[slen] = c;
+
+       return 0;
+}
+
+static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream)
+{
+       char *line = *lineptr;
+       size_t slen = 0;
+
+       for (;;) {
+               int c = getc(stream);
+
+               switch (c) {
+               case '\n':
+                       if (add_byte(c, &line, slen, n) < 0)
+                               goto e_out;
+                       slen++;
+                       /* fall through */
+               case EOF:
+                       if (add_byte('\0', &line, slen, n) < 0)
+                               goto e_out;
+                       *lineptr = line;
+                       if (slen == 0)
+                               return -1;
+                       return slen;
+               default:
+                       if (add_byte(c, &line, slen, n) < 0)
+                               goto e_out;
+                       slen++;
+               }
+       }
+
+e_out:
+       line[slen-1] = '\0';
+       *lineptr = line;
+       return -1;
+}
+
 int conf_read_simple(const char *name, int def)
 {
        FILE *in = NULL;
-       char line[1024];
+       char   *line = NULL;
+       size_t  line_asize = 0;
        char *p, *p2;
        struct symbol *sym;
        int i, def_flags;
@@ -247,7 +303,7 @@ load:
                }
        }
 
-       while (fgets(line, sizeof(line), in)) {
+       while (compat_getline(&line, &line_asize, in) != -1) {
                conf_lineno++;
                sym = NULL;
                if (line[0] == '#') {
@@ -335,6 +391,7 @@ setsym:
                        cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);
                }
        }
+       free(line);
        fclose(in);
 
        if (modules_sym)
index d4ecce8bc3a689daa2157e4f47e65e7c62192bd4..cdd48600e02a9bd842f2e43ab6b7f263949451ec 100644 (file)
@@ -12,6 +12,7 @@ extern "C" {
 
 #include <assert.h>
 #include <stdio.h>
+#include "list.h"
 #ifndef __cplusplus
 #include <stdbool.h>
 #endif
@@ -173,6 +174,15 @@ struct menu {
 #define MENU_CHANGED           0x0001
 #define MENU_ROOT              0x0002
 
+struct jump_key {
+       struct list_head entries;
+       size_t offset;
+       struct menu *target;
+       int index;
+};
+
+#define JUMP_NB                        9
+
 extern struct file *file_list;
 extern struct file *current_file;
 struct file *lookup_file(const char *name);
diff --git a/l4/tool/kconfig/scripts/kconfig/list.h b/l4/tool/kconfig/scripts/kconfig/list.h
new file mode 100644 (file)
index 0000000..0ae730b
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef LIST_H
+#define LIST_H
+
+/*
+ * Copied from include/linux/...
+ */
+
+#undef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr:        the pointer to the member.
+ * @type:       the type of the container struct this is embedded in.
+ * @member:     the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({                      \
+       const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
+       (type *)( (char *)__mptr - offsetof(type,member) );})
+
+
+struct list_head {
+       struct list_head *next, *prev;
+};
+
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+       struct list_head name = LIST_HEAD_INIT(name)
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:       the &struct list_head pointer.
+ * @type:      the type of the struct this is embedded in.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+       container_of(ptr, type, member)
+
+/**
+ * list_for_each_entry -       iterate over list of given type
+ * @pos:       the type * to use as a loop cursor.
+ * @head:      the head for your list.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member)                         \
+       for (pos = list_entry((head)->next, typeof(*pos), member);      \
+            &pos->member != (head);    \
+            pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(const struct list_head *head)
+{
+       return head->next == head;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *_new,
+                             struct list_head *prev,
+                             struct list_head *next)
+{
+       next->prev = _new;
+       _new->next = next;
+       _new->prev = prev;
+       prev->next = _new;
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *_new, struct list_head *head)
+{
+       __list_add(_new, head->prev, head);
+}
+
+#endif
index 47fe9c340f9a20b9b6bd9871d18d79ea9ddc7d1d..ef1a7381f956d5e7d0ebb8d3ba6af2361a0c3c74 100644 (file)
@@ -21,8 +21,10 @@ P(menu_get_root_menu,struct menu *,(struct menu *menu));
 P(menu_get_parent_menu,struct menu *,(struct menu *menu));
 P(menu_has_help,bool,(struct menu *menu));
 P(menu_get_help,const char *,(struct menu *menu));
-P(get_symbol_str, void, (struct gstr *r, struct symbol *sym));
-P(get_relations_str, struct gstr, (struct symbol **sym_arr));
+P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct list_head
+                        *head));
+P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct list_head
+                                  *head));
 P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help));
 
 /* symbol.c */
index 82cc3a85e7f885e2c7ab52aa99a6f76242899aa5..c8e8a7154753b858e9f51e9c3d6816962d8f549b 100644 (file)
@@ -4,7 +4,7 @@
 # What library to link
 ldflags()
 {
-       for ext in so a dylib ; do
+       for ext in so a dll.a dylib ; do
                for lib in ncursesw ncurses curses ; do
                        $cc -print-file-name=lib${lib}.${ext} | grep -q /
                        if [ $? -eq 0 ]; then
@@ -19,12 +19,12 @@ ldflags()
 # Where is ncurses.h?
 ccflags()
 {
-       if [ -f /usr/include/ncurses/ncurses.h ]; then
+       if [ -f /usr/include/ncursesw/curses.h ]; then
+               echo '-I/usr/include/ncursesw -DCURSES_LOC="<ncursesw/curses.h>"'
+       elif [ -f /usr/include/ncurses/ncurses.h ]; then
                echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"'
        elif [ -f /usr/include/ncurses/curses.h ]; then
                echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"'
-       elif [ -f /usr/include/ncursesw/curses.h ]; then
-               echo '-I/usr/include/ncursesw -DCURSES_LOC="<ncursesw/curses.h>"'
        elif [ -f /usr/include/ncurses.h ]; then
                echo '-DCURSES_LOC="<ncurses.h>"'
        else
@@ -38,7 +38,7 @@ trap "rm -f $tmp" 0 1 2 3 15
 
 # Check if we can link to ncurses
 check() {
-        $cc -xc - -o $tmp 2>/dev/null <<'EOF'
+        $cc -x c - -o $tmp 2>/dev/null <<'EOF'
 #include CURSES_LOC
 main() {}
 EOF
index b5211fce0d946ab90eaf1ba239f3b20b40039b11..ee17a5264d5b456c0672a77b06964bfc1ccd29d7 100644 (file)
@@ -144,6 +144,7 @@ struct dialog_info {
  */
 extern struct dialog_info dlg;
 extern char dialog_input_result[];
+extern int saved_x, saved_y;           /* Needed in signal handler in mconf.c */
 
 /*
  * Function prototypes
@@ -209,7 +210,13 @@ int first_alpha(const char *string, const char *exempt);
 int dialog_yesno(const char *title, const char *prompt, int height, int width);
 int dialog_msgbox(const char *title, const char *prompt, int height,
                  int width, int pause);
-int dialog_textbox(const char *title, const char *file, int height, int width);
+
+
+typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void
+                              *_data);
+int dialog_textbox(const char *title, char *tbuf, int initial_height,
+                  int initial_width, int *keys, int *_vscroll, int *_hscroll,
+                  update_text_fn update_text, void *data);
 int dialog_menu(const char *title, const char *prompt,
                const void *selected, int *s_scroll);
 int dialog_checklist(const char *title, const char *prompt, int height,
index 154c2dd245b77536de60fd344d46e49dfbe41520..a48bb93e09073f05ea14786fea9370202f5039f9 100644 (file)
 #include "dialog.h"
 
 static void back_lines(int n);
-static void print_page(WINDOW * win, int height, int width);
-static void print_line(WINDOW * win, int row, int width);
+static void print_page(WINDOW *win, int height, int width, update_text_fn
+                      update_text, void *data);
+static void print_line(WINDOW *win, int row, int width);
 static char *get_line(void);
 static void print_position(WINDOW * win);
 
 static int hscroll;
 static int begin_reached, end_reached, page_length;
-static const char *buf;
-static const char *page;
+static char *buf;
+static char *page;
 
 /*
  * refresh window content
  */
 static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
-                                                         int cur_y, int cur_x)
+                            int cur_y, int cur_x, update_text_fn update_text,
+                            void *data)
 {
-       print_page(box, boxh, boxw);
+       print_page(box, boxh, boxw, update_text, data);
        print_position(dialog);
        wmove(dialog, cur_y, cur_x);    /* Restore cursor position */
        wrefresh(dialog);
@@ -47,14 +49,18 @@ static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
 
 /*
  * Display text from a file in a dialog box.
+ *
+ * keys is a null-terminated array
+ * update_text() may not add or remove any '\n' or '\0' in tbuf
  */
-int dialog_textbox(const char *title, const char *tbuf,
-                  int initial_height, int initial_width)
+int dialog_textbox(const char *title, char *tbuf, int initial_height,
+                  int initial_width, int *keys, int *_vscroll, int *_hscroll,
+                  update_text_fn update_text, void *data)
 {
        int i, x, y, cur_x, cur_y, key = 0;
        int height, width, boxh, boxw;
-       int passed_end;
        WINDOW *dialog, *box;
+       bool done = false;
 
        begin_reached = 1;
        end_reached = 0;
@@ -63,6 +69,15 @@ int dialog_textbox(const char *title, const char *tbuf,
        buf = tbuf;
        page = buf;     /* page is pointer to start of page to be displayed */
 
+       if (_vscroll && *_vscroll) {
+               begin_reached = 0;
+
+               for (i = 0; i < *_vscroll; i++)
+                       get_line();
+       }
+       if (_hscroll)
+               hscroll = *_hscroll;
+
 do_resize:
        getmaxyx(stdscr, height, width);
        if (height < 8 || width < 8)
@@ -120,25 +135,28 @@ do_resize:
 
        /* Print first page of text */
        attr_clear(box, boxh, boxw, dlg.dialog.atr);
-       refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
+       refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text,
+                        data);
 
-       while ((key != KEY_ESC) && (key != '\n')) {
+       while (!done) {
                key = wgetch(dialog);
                switch (key) {
                case 'E':       /* Exit */
                case 'e':
                case 'X':
                case 'x':
-                       delwin(box);
-                       delwin(dialog);
-                       return 0;
+               case 'q':
+               case '\n':
+                       done = true;
+                       break;
                case 'g':       /* First page */
                case KEY_HOME:
                        if (!begin_reached) {
                                begin_reached = 1;
                                page = buf;
                                refresh_text_box(dialog, box, boxh, boxw,
-                                                cur_y, cur_x);
+                                                cur_y, cur_x, update_text,
+                                                data);
                        }
                        break;
                case 'G':       /* Last page */
@@ -148,78 +166,48 @@ do_resize:
                        /* point to last char in buf */
                        page = buf + strlen(buf);
                        back_lines(boxh);
-                       refresh_text_box(dialog, box, boxh, boxw,
-                                        cur_y, cur_x);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case 'K':       /* Previous line */
                case 'k':
                case KEY_UP:
-                       if (!begin_reached) {
-                               back_lines(page_length + 1);
-
-                               /* We don't call print_page() here but use
-                                * scrolling to ensure faster screen update.
-                                * However, 'end_reached' and 'page_length'
-                                * should still be updated, and 'page' should
-                                * point to start of next page. This is done
-                                * by calling get_line() in the following
-                                * 'for' loop. */
-                               scrollok(box, TRUE);
-                               wscrl(box, -1); /* Scroll box region down one line */
-                               scrollok(box, FALSE);
-                               page_length = 0;
-                               passed_end = 0;
-                               for (i = 0; i < boxh; i++) {
-                                       if (!i) {
-                                               /* print first line of page */
-                                               print_line(box, 0, boxw);
-                                               wnoutrefresh(box);
-                                       } else
-                                               /* Called to update 'end_reached' and 'page' */
-                                               get_line();
-                                       if (!passed_end)
-                                               page_length++;
-                                       if (end_reached && !passed_end)
-                                               passed_end = 1;
-                               }
+                       if (begin_reached)
+                               break;
 
-                               print_position(dialog);
-                               wmove(dialog, cur_y, cur_x);    /* Restore cursor position */
-                               wrefresh(dialog);
-                       }
+                       back_lines(page_length + 1);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case 'B':       /* Previous page */
                case 'b':
+               case 'u':
                case KEY_PPAGE:
                        if (begin_reached)
                                break;
                        back_lines(page_length + boxh);
-                       refresh_text_box(dialog, box, boxh, boxw,
-                                        cur_y, cur_x);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case 'J':       /* Next line */
                case 'j':
                case KEY_DOWN:
-                       if (!end_reached) {
-                               begin_reached = 0;
-                               scrollok(box, TRUE);
-                               scroll(box);    /* Scroll box region up one line */
-                               scrollok(box, FALSE);
-                               print_line(box, boxh - 1, boxw);
-                               wnoutrefresh(box);
-                               print_position(dialog);
-                               wmove(dialog, cur_y, cur_x);    /* Restore cursor position */
-                               wrefresh(dialog);
-                       }
+                       if (end_reached)
+                               break;
+
+                       back_lines(page_length - 1);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case KEY_NPAGE: /* Next page */
                case ' ':
+               case 'd':
                        if (end_reached)
                                break;
 
                        begin_reached = 0;
-                       refresh_text_box(dialog, box, boxh, boxw,
-                                        cur_y, cur_x);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case '0':       /* Beginning of line */
                case 'H':       /* Scroll left */
@@ -234,8 +222,8 @@ do_resize:
                                hscroll--;
                        /* Reprint current page to scroll horizontally */
                        back_lines(page_length);
-                       refresh_text_box(dialog, box, boxh, boxw,
-                                        cur_y, cur_x);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case 'L':       /* Scroll right */
                case 'l':
@@ -245,11 +233,12 @@ do_resize:
                        hscroll++;
                        /* Reprint current page to scroll horizontally */
                        back_lines(page_length);
-                       refresh_text_box(dialog, box, boxh, boxw,
-                                        cur_y, cur_x);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case KEY_ESC:
-                       key = on_key_esc(dialog);
+                       if (on_key_esc(dialog) == KEY_ESC)
+                               done = true;
                        break;
                case KEY_RESIZE:
                        back_lines(height);
@@ -257,11 +246,31 @@ do_resize:
                        delwin(dialog);
                        on_key_resize();
                        goto do_resize;
+               default:
+                       for (i = 0; keys[i]; i++) {
+                               if (key == keys[i]) {
+                                       done = true;
+                                       break;
+                               }
+                       }
                }
        }
        delwin(box);
        delwin(dialog);
-       return key;             /* ESC pressed */
+       if (_vscroll) {
+               const char *s;
+
+               s = buf;
+               *_vscroll = 0;
+               back_lines(page_length);
+               while (s < page && (s = strchr(s, '\n'))) {
+                       (*_vscroll)++;
+                       s++;
+               }
+       }
+       if (_hscroll)
+               *_hscroll = hscroll;
+       return key;
 }
 
 /*
@@ -298,12 +307,23 @@ static void back_lines(int n)
 }
 
 /*
- * Print a new page of text. Called by dialog_textbox().
+ * Print a new page of text.
  */
-static void print_page(WINDOW * win, int height, int width)
+static void print_page(WINDOW *win, int height, int width, update_text_fn
+                      update_text, void *data)
 {
        int i, passed_end = 0;
 
+       if (update_text) {
+               char *end;
+
+               for (i = 0; i < height; i++)
+                       get_line();
+               end = page;
+               back_lines(height);
+               update_text(buf, page - buf, end - buf, data);
+       }
+
        page_length = 0;
        for (i = 0; i < height; i++) {
                print_line(win, i, width);
@@ -316,7 +336,7 @@ static void print_page(WINDOW * win, int height, int width)
 }
 
 /*
- * Print a new line of text. Called by dialog_textbox() and print_page().
+ * Print a new line of text.
  */
 static void print_line(WINDOW * win, int row, int width)
 {
@@ -354,10 +374,8 @@ static char *get_line(void)
        end_reached = 0;
        while (*page != '\n') {
                if (*page == '\0') {
-                       if (!end_reached) {
-                               end_reached = 1;
-                               break;
-                       }
+                       end_reached = 1;
+                       break;
                } else if (i < MAX_LEN)
                        line[i++] = *(page++);
                else {
@@ -370,7 +388,7 @@ static char *get_line(void)
        if (i <= MAX_LEN)
                line[i] = '\0';
        if (!end_reached)
-               page++;         /* move pass '\n' */
+               page++;         /* move past '\n' */
 
        return line;
 }
index f2375ad7ebc9bf07d306fc8de611f631b36cd7bf..109d53117d223682254502b51b6414d7404852e2 100644 (file)
@@ -23,6 +23,9 @@
 
 #include "dialog.h"
 
+/* Needed in signal handler in mconf.c */
+int saved_x, saved_y;
+
 struct dialog_info dlg;
 
 static void set_mono_theme(void)
@@ -273,6 +276,10 @@ int init_dialog(const char *backtitle)
        int height, width;
 
        initscr();              /* Init curses */
+
+       /* Get current cursor position for signal handler in mconf.c */
+       getyx(stdscr, saved_y, saved_x);
+
        getmaxyx(stdscr, height, width);
        if (height < 19 || width < 80) {
                endwin();
index f606738d421d99c29f7321236e3eebcd2ac6a760..53975cf876083ecba455a7033222b2ccc3690686 100644 (file)
@@ -105,10 +105,10 @@ static const char mconf_readme[] = N_(
 "Text Box    (Help Window)\n"
 "--------\n"
 "o  Use the cursor keys to scroll up/down/left/right.  The VI editor\n"
-"   keys h,j,k,l function here as do <SPACE BAR> and <B> for those\n"
-"   who are familiar with less and lynx.\n"
+"   keys h,j,k,l function here as do <u>, <d>, <SPACE BAR> and <B> for \n"
+"   those who are familiar with less and lynx.\n"
 "\n"
-"o  Press <E>, <X>, <Enter> or <Esc><Esc> to exit.\n"
+"o  Press <E>, <X>, <q>, <Enter> or <Esc><Esc> to exit.\n"
 "\n"
 "\n"
 "Alternate Configuration Files\n"
@@ -236,16 +236,19 @@ search_help[] = N_(
        "Result:\n"
        "-----------------------------------------------------------------\n"
        "Symbol: FOO [=m]\n"
+       "Type  : tristate\n"
        "Prompt: Foo bus is used to drive the bar HW\n"
-       "Defined at drivers/pci/Kconfig:47\n"
-       "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
-       "Location:\n"
-       "  -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
-       "    -> PCI support (PCI [=y])\n"
-       "      -> PCI access mode (<choice> [=y])\n"
-       "Selects: LIBCRC32\n"
-       "Selected by: BAR\n"
+       "  Defined at drivers/pci/Kconfig:47\n"
+       "  Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
+       "  Location:\n"
+       "    -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
+       "      -> PCI support (PCI [=y])\n"
+       "(1)     -> PCI access mode (<choice> [=y])\n"
+       "  Selects: LIBCRC32\n"
+       "  Selected by: BAR\n"
        "-----------------------------------------------------------------\n"
+       "o The line 'Type:' shows the type of the configuration option for\n"
+       "  this symbol (boolean, tristate, string, ...)\n"
        "o The line 'Prompt:' shows the text used in the menu structure for\n"
        "  this symbol\n"
        "o The 'Defined at' line tell at what file / line number the symbol\n"
@@ -254,8 +257,12 @@ search_help[] = N_(
        "  this symbol to be visible in the menu (selectable)\n"
        "o The 'Location:' lines tell where in the menu structure this symbol\n"
        "  is located\n"
-       "    A location followed by a [=y] indicate that this is a selectable\n"
-       "    menu item - and current value is displayed inside brackets.\n"
+       "    A location followed by a [=y] indicates that this is a\n"
+       "    selectable menu item - and the current value is displayed inside\n"
+       "    brackets.\n"
+       "    Press the key in the (#) prefix to jump directly to that\n"
+       "    location. You will be returned to the current search results\n"
+       "    after exiting this new menu.\n"
        "o The 'Selects:' line tell what symbol will be automatically\n"
        "  selected if this symbol is selected (y or m)\n"
        "o The 'Selected by' line tell what symbol has selected this symbol\n"
@@ -273,13 +280,15 @@ static struct menu *current_menu;
 static int child_count;
 static int single_menu_mode;
 static int show_all_options;
-static int saved_x, saved_y;
 
-static void conf(struct menu *menu);
+static void conf(struct menu *menu, struct menu *active_menu);
 static void conf_choice(struct menu *menu);
 static void conf_string(struct menu *menu);
 static void conf_load(void);
 static void conf_save(void);
+static int show_textbox_ext(const char *title, char *text, int r, int c,
+                           int *keys, int *vscroll, int *hscroll,
+                           update_text_fn update_text, void *data);
 static void show_textbox(const char *title, const char *text, int r, int c);
 static void show_helptext(const char *title, const char *text);
 static void show_help(struct menu *menu);
@@ -302,12 +311,47 @@ static void set_config_filename(const char *config_filename)
 }
 
 
+struct search_data {
+       struct list_head *head;
+       struct menu **targets;
+       int *keys;
+};
+
+static void update_text(char *buf, size_t start, size_t end, void *_data)
+{
+       struct search_data *data = _data;
+       struct jump_key *pos;
+       int k = 0;
+
+       list_for_each_entry(pos, data->head, entries) {
+               if (pos->offset >= start && pos->offset < end) {
+                       char header[4];
+
+                       if (k < JUMP_NB) {
+                               int key = '0' + (pos->index % JUMP_NB) + 1;
+
+                               sprintf(header, "(%c)", key);
+                               data->keys[k] = key;
+                               data->targets[k] = pos->target;
+                               k++;
+                       } else {
+                               sprintf(header, "   ");
+                       }
+
+                       memcpy(buf + pos->offset, header, sizeof(header) - 1);
+               }
+       }
+       data->keys[k] = 0;
+}
+
 static void search_conf(void)
 {
        struct symbol **sym_arr;
        struct gstr res;
        char *dialog_input;
-       int dres;
+       int dres, vscroll = 0, hscroll = 0;
+       bool again;
+
 again:
        dialog_clear();
        dres = dialog_inputbox(_("Search Configuration Parameter"),
@@ -330,10 +374,30 @@ again:
                dialog_input += strlen(CONFIG_);
 
        sym_arr = sym_re_search(dialog_input);
-       res = get_relations_str(sym_arr);
+       do {
+               LIST_HEAD(head);
+               struct menu *targets[JUMP_NB];
+               int keys[JUMP_NB + 1], i;
+               struct search_data data = {
+                       .head = &head,
+                       .targets = targets,
+                       .keys = keys,
+               };
+
+               res = get_relations_str(sym_arr, &head);
+               dres = show_textbox_ext(_("Search Results"), (char *)
+                                       str_get(&res), 0, 0, keys, &vscroll,
+                                       &hscroll, &update_text, (void *)
+                                       &data);
+               again = false;
+               for (i = 0; i < JUMP_NB && keys[i]; i++)
+                       if (dres == keys[i]) {
+                               conf(targets[i]->parent, targets[i]);
+                               again = true;
+                       }
+               str_free(&res);
+       } while (again);
        free(sym_arr);
-       show_textbox(_("Search Results"), str_get(&res), 0, 0);
-       str_free(&res);
 }
 
 static void build_conf(struct menu *menu)
@@ -514,12 +578,11 @@ conf_childs:
        indent -= doint;
 }
 
-static void conf(struct menu *menu)
+static void conf(struct menu *menu, struct menu *active_menu)
 {
        struct menu *submenu;
        const char *prompt = menu_get_prompt(menu);
        struct symbol *sym;
-       struct menu *active_menu = NULL;
        int res;
        int s_scroll = 0;
 
@@ -562,13 +625,13 @@ static void conf(struct menu *menu)
                                if (single_menu_mode)
                                        submenu->data = (void *) (long) !submenu->data;
                                else
-                                       conf(submenu);
+                                       conf(submenu, NULL);
                                break;
                        case 't':
                                if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
                                        conf_choice(submenu);
                                else if (submenu->prompt->type == P_MENU)
-                                       conf(submenu);
+                                       conf(submenu, NULL);
                                break;
                        case 's':
                                conf_string(submenu);
@@ -607,7 +670,7 @@ static void conf(struct menu *menu)
                        if (item_is_tag('t'))
                                sym_toggle_tristate_value(sym);
                        else if (item_is_tag('m'))
-                               conf(submenu);
+                               conf(submenu, NULL);
                        break;
                case 7:
                        search_conf();
@@ -619,10 +682,19 @@ static void conf(struct menu *menu)
        }
 }
 
-static void show_textbox(const char *title, const char *text, int r, int c)
+static int show_textbox_ext(const char *title, char *text, int r, int c, int
+                           *keys, int *vscroll, int *hscroll, update_text_fn
+                           update_text, void *data)
 {
        dialog_clear();
-       dialog_textbox(title, text, r, c);
+       return dialog_textbox(title, text, r, c, keys, vscroll, hscroll,
+                             update_text, data);
+}
+
+static void show_textbox(const char *title, const char *text, int r, int c)
+{
+       show_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL,
+                        NULL, NULL);
 }
 
 static void show_helptext(const char *title, const char *text)
@@ -862,9 +934,6 @@ int main(int ac, char **av)
                        single_menu_mode = 1;
        }
 
-       initscr();
-
-       getyx(stdscr, saved_y, saved_x);
        if (init_dialog(NULL)) {
                fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
                fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
@@ -873,7 +942,7 @@ int main(int ac, char **av)
 
        set_config_filename(conf_get_configname());
        do {
-               conf(&rootmenu);
+               conf(&rootmenu, NULL);
                res = handle_exit();
        } while (res == KEY_ESC);
 
index 8c2a97e60fafa701331949152261d162541482a1..e98a05c8e50882d3b2833a2f4d05761dcffd22d3 100644 (file)
@@ -507,10 +507,12 @@ const char *menu_get_help(struct menu *menu)
                return "";
 }
 
-static void get_prompt_str(struct gstr *r, struct property *prop)
+static void get_prompt_str(struct gstr *r, struct property *prop,
+                          struct list_head *head)
 {
        int i, j;
-       struct menu *submenu[8], *menu;
+       struct menu *submenu[8], *menu, *location = NULL;
+       struct jump_key *jump;
 
        str_printf(r, _("Prompt: %s\n"), _(prop->text));
        str_printf(r, _("  Defined at %s:%d\n"), prop->menu->file->name,
@@ -521,13 +523,44 @@ static void get_prompt_str(struct gstr *r, struct property *prop)
                str_append(r, "\n");
        }
        menu = prop->menu->parent;
-       for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
+       for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
+               bool accessible = menu_is_visible(menu);
+
                submenu[i++] = menu;
+               if (location == NULL && accessible)
+                       location = menu;
+       }
+       if (head && location) {
+               jump = malloc(sizeof(struct jump_key));
+
+               if (menu_is_visible(prop->menu)) {
+                       /*
+                        * There is not enough room to put the hint at the
+                        * beginning of the "Prompt" line. Put the hint on the
+                        * last "Location" line even when it would belong on
+                        * the former.
+                        */
+                       jump->target = prop->menu;
+               } else
+                       jump->target = location;
+
+               if (list_empty(head))
+                       jump->index = 0;
+               else
+                       jump->index = list_entry(head->prev, struct jump_key,
+                                                entries)->index + 1;
+
+               list_add_tail(&jump->entries, head);
+       }
+
        if (i > 0) {
                str_printf(r, _("  Location:\n"));
                for (j = 4; --i >= 0; j += 2) {
                        menu = submenu[i];
-                       str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu)));
+                       if (head && location && menu == location)
+                               jump->offset = r->len - 1;
+                       str_printf(r, "%*c-> %s", j, ' ',
+                                  _(menu_get_prompt(menu)));
                        if (menu->sym) {
                                str_printf(r, " (%s [=%s])", menu->sym->name ?
                                        menu->sym->name : _("<choice>"),
@@ -538,7 +571,11 @@ static void get_prompt_str(struct gstr *r, struct property *prop)
        }
 }
 
-void get_symbol_str(struct gstr *r, struct symbol *sym)
+/*
+ * head is optional and may be NULL
+ */
+void get_symbol_str(struct gstr *r, struct symbol *sym,
+                   struct list_head *head)
 {
        bool hit;
        struct property *prop;
@@ -557,7 +594,7 @@ void get_symbol_str(struct gstr *r, struct symbol *sym)
                }
        }
        for_all_prompts(sym, prop)
-               get_prompt_str(r, prop);
+               get_prompt_str(r, prop, head);
        hit = false;
        for_all_properties(sym, prop, P_SELECT) {
                if (!hit) {
@@ -577,14 +614,14 @@ void get_symbol_str(struct gstr *r, struct symbol *sym)
        str_append(r, "\n\n");
 }
 
-struct gstr get_relations_str(struct symbol **sym_arr)
+struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
 {
        struct symbol *sym;
        struct gstr res = str_new();
        int i;
 
        for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
-               get_symbol_str(&res, sym);
+               get_symbol_str(&res, sym, head);
        if (!i)
                str_append(&res, _("No matches found.\n"));
        return res;
@@ -603,5 +640,5 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help)
        }
        str_printf(help, "%s\n", _(help_text));
        if (sym)
-               get_symbol_str(help, sym);
+               get_symbol_str(help, sym, NULL);
 }
index 8c0eb65978c95aecedb73a7e71c6c4d788fe2255..87d4b15da951031896868789df7a992d21fcc73b 100644 (file)
@@ -83,10 +83,10 @@ static const char nconf_readme[] = N_(
 "Text Box    (Help Window)\n"
 "--------\n"
 "o  Use the cursor keys to scroll up/down/left/right.  The VI editor\n"
-"   keys h,j,k,l function here as do <SPACE BAR> for those\n"
-"   who are familiar with less and lynx.\n"
+"   keys h,j,k,l function here as do <u>, <d> and <SPACE BAR> for\n"
+"   those who are familiar with less and lynx.\n"
 "\n"
-"o  Press <Enter>, <F1>, <F5>, <F7> or <Esc> to exit.\n"
+"o  Press <Enter>, <F1>, <F5>, <F9>, <q> or <Esc> to exit.\n"
 "\n"
 "\n"
 "Alternate Configuration Files\n"
@@ -721,7 +721,7 @@ again:
                dialog_input += strlen(CONFIG_);
 
        sym_arr = sym_re_search(dialog_input);
-       res = get_relations_str(sym_arr);
+       res = get_relations_str(sym_arr, NULL);
        free(sym_arr);
        show_scroll_win(main_window,
                        _("Search Results"), str_get(&res));
@@ -1503,7 +1503,11 @@ int main(int ac, char **av)
        }
 
        notimeout(stdscr, FALSE);
+#if NCURSES_REENTRANT
+       set_escdelay(1);
+#else
        ESCDELAY = 1;
+#endif
 
        /* set btns menu */
        curses_menu = new_menu(curses_menu_items);
index 3b18dd839668b295cd3d06b1c4cac3d4c941ddf3..379003c7a2b4d8cef60e25548fcb9567ca3656c5 100644 (file)
@@ -604,9 +604,11 @@ void show_scroll_win(WINDOW *main_window,
                switch (res) {
                case KEY_NPAGE:
                case ' ':
+               case 'd':
                        start_y += text_lines-2;
                        break;
                case KEY_PPAGE:
+               case 'u':
                        start_y -= text_lines+2;
                        break;
                case KEY_HOME:
@@ -632,10 +634,10 @@ void show_scroll_win(WINDOW *main_window,
                        start_x++;
                        break;
                }
-               if (res == 10 || res == 27 || res == 'q'
-                   || res == KEY_F(F_BACK) || res == KEY_F(F_EXIT)) {
+               if (res == 10 || res == 27 || res == 'q' ||
+                       res == KEY_F(F_HELP) || res == KEY_F(F_BACK) ||
+                       res == KEY_F(F_EXIT))
                        break;
-               }
                if (start_y < 0)
                        start_y = 0;
                if (start_y >= total_lines-text_lines)
index 345013ac08812e30b15fffc90b9fe641f59a3960..7abbe61de7aec319ae4ff28bba83896a2d478ca3 100755 (executable)
@@ -164,6 +164,7 @@ our $print_indent = 0;
 clear_head();
 
 my %classes = ();
+my %functions = ();
 my %sections = ();
 my %impl_parts = ();
 my %includes = ();
@@ -733,7 +734,8 @@ sub parse_file
            }
   
          # Member function definition?
-         if (/^([^\{\(]*?)             # pretext, maybe w template decl tag
+#          if (/^([^\{\(]*?)             # pretext, maybe w template decl tag
+          if (/^((?:[^\{\(]|\(\()*?)             # pretext, maybe w template decl tag
               \b ($identifier (?: $s :: $s $identifier)*) # class name
               ($s $template_arg)?      # optional class-template args
               $s :: $s
@@ -744,7 +746,7 @@ sub parse_file
            {
              my ($pretext, $class, $templateargs, $name, $args, $posttext)
                = ($1, $2, (defined $3 ? $3 : ''), $4, $5, $6);
-#print "P<$pretext> C<$class> T<$templateargs> N<$name> A<$args> P<$posttext>\n";
+#print "Member: P<$pretext> C<$class> T<$templateargs> N<$name> A<$args> P<$posttext>\n";
              # Canonify operator names
              $name =~ s/(?<=\w)(?:$s_once)+(?=\W)//gs;
              $name =~ s/(?<=\W)(?:$s_once)+(?=\w)//gs;
@@ -768,6 +770,7 @@ sub parse_file
                $s( \( $paren_expr \) [^:\{\(\)=]*) # arg list
                (\{.*)$/sx)              # body
            {
+#print "Free function: $2 T(" . (defined $3 ? $3 : "") . ") PRE($1) ARGS($4) POST($5)\n";
              my $function = { class => '',
                               name => $2,
                               templateargs => (defined $3
@@ -868,7 +871,7 @@ sub read_more ()    # Read one more line of code. Stow away
          s/\003/$saved/s;
        }
 
-      while (s|(//(?!-\s*\n).*)$|\001$number\001|m) # Do not match magic "//-"
+      while (s|(//(?!-\s*\n).*\n)|\001$number\001|m) # Do not match magic "//-"
        {                       # The \001 signifies whitespace.
          push @comments, $1;
          $number++;
@@ -1066,6 +1069,14 @@ sub handle_function
          $func->{visibility} = "implementation_only";
           $func->{pretext} =~ s|IMPLEMENT[ \t]*||s;
         }
+      elsif (s/^($s)IMPLEMENT_DEFAULT([\s\n])/$1$2/s)
+        {
+         # Use a visibility attribute that is never used in adding
+         # declarations to classes in print_classdecl.
+         $func->{visibility} = "implementation_only";
+         $func->{default_impl} = 1;
+          $func->{pretext} =~ s|IMPLEMENT_DEFAULT[ \t]*||s;
+        }
 
       if ($func->{posttext} =~ s/$s=${s}0$s;$s$//s)
         {
@@ -1136,7 +1147,6 @@ sub handle_function
            if ($match =~ /^(?:${s}template$s<${s}>)+${s}$/s);
 
           $func->{pretext} =~ s/\Q$match//s;
-#         $func->{pretext} =~ s|$template[ \t]*||s;
          next;
         }
 
@@ -1211,6 +1221,18 @@ sub handle_function
 
          next;
         }
+      if (s/^($s)IMPLEMENT_DEFAULT([\s\n])/$1$2/s)
+        {
+          $func->{pretext} =~ s/IMPLEMENT_DEFAULT[ \t]*//s;
+
+         if ($func->{class} eq '')
+           {
+             $func->{visibility} = "implementation_only";
+              $func->{default_impl} = 1;
+           }
+
+         next;
+        }
 
       if (s/^($s)explicit([\s\n])/$1$2/s)
         {
@@ -1242,6 +1264,23 @@ sub handle_function
           . " in INTERFACE section;";
     }
 
+  if (defined $functions{"$func->{class}::$func->{name}"})
+    {
+      my $f = $functions{"$func->{class}::$func->{name}"};
+      if (defined $f->{default_impl})
+        {
+          $f->{printed} = 1;
+        }
+      elsif (defined $func->{default_impl})
+        {
+          $func->{printed} = 1;
+        }
+    }
+  else
+    {
+      $functions{"$func->{class}::$func->{name}"} = $func;
+    }
+
   push @{$classes{$func->{class}}->{funcs}}, $func;
 
   $verbose && print "FUNC: " . ($func->{class} ne '' 
index 652866c642ba3677858a85d7f73f5bd56110e4fe..3d48137ab24edde0497f77a2d90dfd4a75e24b51 100644 (file)
@@ -13,7 +13,7 @@ TOOL_TESTS = mapping mapping_inline random random_inline extern_c static \
   parser parser_noinline \
   multifile variable line line_not line_nh interface comment_in_string \
   default_args drop_single1 drop_single2 drop_single3 drop_multi1 \
-  drop_multi2
+  drop_multi2 implement_template
 
 mapping_inline_src = mapping
 mapping_inline_flags = -i
diff --git a/tools/preprocess/test/implement_template.cpp b/tools/preprocess/test/implement_template.cpp
new file mode 100644 (file)
index 0000000..ae81de0
--- /dev/null
@@ -0,0 +1,31 @@
+INTERFACE:
+
+template< typename T >
+class Test
+{
+public:
+  void test_func();
+};
+
+
+IMPLEMENTATION:
+
+IMPLEMENT
+template< typename T >
+// comment
+void __attribute__((deprecated))
+Test<T>::test_func()
+{
+}
+
+PUBLIC
+template< typename T > // comment 1
+template<
+  typename X, // comment within template args list
+  typename X2 // another comment in tl args
+>
+// comment 2
+void __attribute__((deprecated))
+Test<T>::test_func2<X, X2>()
+{
+}
diff --git a/tools/preprocess/test/verify/implement_template.cc b/tools/preprocess/test/verify/implement_template.cc
new file mode 100644 (file)
index 0000000..89fa57e
--- /dev/null
@@ -0,0 +1,5 @@
+// AUTOMATICALLY GENERATED -- DO NOT EDIT!         -*- c++ -*-
+
+#include "implement_template.h"
+#include "implement_template_i.h"
+
diff --git a/tools/preprocess/test/verify/implement_template.h b/tools/preprocess/test/verify/implement_template.h
new file mode 100644 (file)
index 0000000..4cd4433
--- /dev/null
@@ -0,0 +1,58 @@
+// AUTOMATICALLY GENERATED -- DO NOT EDIT!         -*- c++ -*-
+
+#ifndef implement_template_h
+#define implement_template_h
+
+//
+// INTERFACE definition follows 
+//
+
+#line 2 "implement_template.cpp"
+
+template< typename T >
+class Test
+{
+public:
+  void test_func();
+
+public:  
+#line 23 "implement_template.cpp"
+  // comment 2
+   // comment 1
+  template<
+    typename X, // comment within template args list
+    typename X2 // another comment in tl args
+  > void __attribute__((deprecated))
+  test_func2<X,X2>();
+};
+
+//
+// IMPLEMENTATION of function templates
+//
+
+
+#line 12 "implement_template.cpp"
+
+
+
+// comment
+template< typename T > void __attribute__((deprecated))
+Test<T>::test_func()
+{
+}
+
+#line 20 "implement_template.cpp"
+
+
+
+// comment 2
+ // comment 1
+template< typename T > template<
+  typename X, // comment within template args list
+  typename X2 // another comment in tl args
+> void __attribute__((deprecated))
+Test<T>::test_func2<X,X2>()
+{
+}
+
+#endif // implement_template_h
diff --git a/tools/preprocess/test/verify/implement_template_i.h b/tools/preprocess/test/verify/implement_template_i.h
new file mode 100644 (file)
index 0000000..da19d7d
--- /dev/null
@@ -0,0 +1,6 @@
+// AUTOMATICALLY GENERATED -- DO NOT EDIT!         -*- c++ -*-
+
+#ifndef implement_template_i_h
+#define implement_template_i_h
+
+#endif // implement_template_i_h
index bbe70c07280505b4a81fa7209065ef4d36ebabae..154804e2ade21528260db94b5dbaed6149ffd4ed 100644 (file)
@@ -15,6 +15,7 @@ class Foo
 public:  
   // A long, multiline comment in front of this function definition.
   // Also, a lot of specifiers that need to be handled.
+  
   static void func1();
 };
 
index eb1d7ca68943a05b022901495df692708810082c..ff1bbb81fb354422c2e7168e8c37ba014de32ed2 100644 (file)
@@ -8,6 +8,7 @@
 // A long, multiline comment in front of this function definition.
 // Also, a lot of specifiers that need to be handled.
 
+
 void
 Foo::func1()
 {
index 11ab555d22fd011a4d879aa5a6f7abc04d609167..f563d556edd46504eedfc8f215725b7659bc05f5 100644 (file)
@@ -15,6 +15,7 @@ class Foo
 public:  
   // A long, multiline comment in front of this function definition.
   // Also, a lot of specifiers that need to be handled.
+  
   static void func1();
 };
 
index 1ce3cf4f236cb261ba57049ff4a9b1e70c936a37..4d63c04e8ac8460162e6cf2a79ca2f351bb9d0de 100644 (file)
@@ -17,17 +17,21 @@ public:
   void * 
   operator new(size_t);        // funny comment
   
+  
 #line 16 "operator.cpp"
   Foo&
   operator+(const Foo&);       // funny comment
   
+  
 #line 22 "operator.cpp"
   Foo&
   operator=(const Foo&);       // funny comment
   
+  
 #line 28 "operator.cpp"
   Foo&
   operator*(const Foo&);       // funny comment
+  
 };
 
 #line 34 "operator.cpp"
index 2e60849fa44b157d5404b6428a4b89171ae50323..f3fd7d6bef5370e313c5316dd7ace426102ff59c 100644 (file)
@@ -12,13 +12,3 @@ create_stack<int>()
 {
   return new stack<int>();
 }
-
-#line 192 "template.cpp"
-
-
-
-template <> stack_t<bool>*
-create_stack<bool>()
-{
-  return new stack<bool>();
-}
index 320fceb28490163d748b93bb37ad13a12f476b4a..79ab22e2ee56cbd0fdc01ff5f417c85ebcf9fe20 100644 (file)
@@ -109,9 +109,24 @@ template <> stack_t<int>*
 create_stack();
 
 #line 195 "template.cpp"
-template <> stack_t<bool>*
+template <> inline stack_t<bool>*
 create_stack();
 
+//
+// IMPLEMENTATION of inline functions (and needed classes)
+//
+
+
+#line 192 "template.cpp"
+
+
+
+template <> inline stack_t<bool>*
+create_stack<bool>()
+{
+  return new stack<bool>();
+}
+
 //
 // IMPLEMENTATION of function templates
 //