lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [lmi] odd/multiarch 78d7f30 1/2: Merge remote-tracking bra


From: Greg Chicares
Subject: [lmi-commits] [lmi] odd/multiarch 78d7f30 1/2: Merge remote-tracking branch 'origin/master' into odd/multiarch
Date: Sun, 19 May 2019 10:38:05 -0400 (EDT)

branch: odd/multiarch
commit 78d7f307dee33a258c4a2f273a1db0d18a50e762
Merge: 3c3bbb5 3ff6c00
Author: Gregory W. Chicares <address@hidden>
Commit: Gregory W. Chicares <address@hidden>

    Merge remote-tracking branch 'origin/master' into odd/multiarch
---
 GNUmakefile                                |  22 +-
 Makefile.am                                |   3 +
 README.schroot                             |   2 +-
 bcc_5_5_1.make                             |   4 +-
 check_git_setup.sh                         |   2 +-
 commutation_functions_test.cpp             | 567 ++++++++++++++++++++++++++++-
 como.make                                  |   4 +-
 cover.mst                                  |   2 -
 cso_table.cpp                              |  97 +++--
 cso_table.hpp                              |  10 +
 finra_footer_upper.mst                     |   5 +
 gui_test.sh                                |   7 +-
 gwc/child.make                             |   3 +
 gwc/company_logo.png                       | Bin 129753 -> 44825 bytes
 gwc/develop1.txt                           |   5 +
 gwc/parent.make                            |  43 +++
 gwc/set.sh                                 |  29 ++
 gwc/xc                                     | 198 ----------
 gwc/xc11                                   | 203 -----------
 install_cygwin.bat                         |   2 +-
 install_libxml2_libxslt.make               |  46 +--
 install_mingw.make                         |  29 +-
 install_mingw.make => install_mingw32.make |  21 +-
 install_miscellanea.make                   |   2 +-
 install_msw.sh                             |  68 ++--
 install_wx.sh                              |  20 +-
 install_wxpdfdoc.sh                        |  14 +-
 irc7702_tables.cpp                         |  99 +++++
 irc7702_tables.hpp                         |  64 ++++
 local_options.sh                           |  10 +-
 mst_to_xst.sh                              |  21 +-
 msw_cygwin.make                            |   6 +-
 msw_generic.make                           |  17 -
 nychthemeral_test.sh                       |  55 ++-
 objects.make                               |   2 +
 pdf_command_wx.cpp                         | 119 +++---
 set_toolchain.sh                           |  19 +-
 tabs/3/startup_script                      |   4 +-
 test_coding_rules_test.sh                  |   3 +
 test_schemata.sh                           |  66 ++--
 40 files changed, 1199 insertions(+), 694 deletions(-)

diff --git a/GNUmakefile b/GNUmakefile
index ec62791..115a421 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -122,9 +122,9 @@ srcdir          := $(CURDIR)
 
 # These directories are outside the scope of the GNU Coding Standards.
 # Therefore, their names may contain '_' for distinction and clarity.
-localbindir     := $(exec_prefix)/local/bin
-locallibdir     := $(exec_prefix)/local/lib
-localincludedir := $(exec_prefix)/local/include
+localbindir     := $(prefix)/local/$(LMI_COMPILER)_$(LMI_TRIPLET)/bin
+locallibdir     := $(prefix)/local/$(LMI_COMPILER)_$(LMI_TRIPLET)/lib
+localincludedir := $(prefix)/local/include
 winebindir      := $(prefix)/third_party/bin
 test_dir        := $(prefix)/test
 touchstone_dir  := $(prefix)/touchstone
@@ -133,9 +133,17 @@ touchstone_dir  := $(prefix)/touchstone
 
 # Other makefiles included; makefiles not to be remade.
 
-# Don't remake this file.
+# Remake this file to "source" a script.
 
-GNUmakefile $(srcdir)/GNUmakefile:: ;
+export LMI_ENV_FILE := env_$(shell date -u +'%s_%N').eraseme
+
+GNUmakefile $(srcdir)/GNUmakefile:: source_env_vars
+       $(eval include $(LMI_ENV_FILE))
+       @rm $(LMI_ENV_FILE)
+
+.PHONY: source_env_vars
+source_env_vars:
+       @. ./set_toolchain.sh
 
 # Included files that don't need to be remade are given explicit empty
 # commands, which significantly reduces the number of lines emitted by
@@ -189,9 +197,6 @@ gpl_files := \
 # the 'make' command line to override any definition of the same
 # variable in $(local_options).
 
-# alternative to 'set_toolchain.sh'
-export PATH := $(localbindir):$(locallibdir):$(PATH)
-
 MAKETARGET = \
   $(MAKE) \
     --directory=$@ \
@@ -369,6 +374,7 @@ raze: source_clean
 
 .PHONY: eviscerate
 eviscerate: source_clean
+       -$(RM) --force --recursive $(prefix)/local
        -$(RM) --force --recursive $(prefix)/third_party
        -$(RM) --force --recursive $(prefix)/gcc_i686-w64-mingw32
        -$(RM) --force --recursive $(prefix)/gcc_x86_64-w64-mingw32
diff --git a/Makefile.am b/Makefile.am
index fe5ae91..f1bdebe 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -411,6 +411,7 @@ liblmi_la_SOURCES = \
     ihs_irc7702a.cpp \
     ihs_mortal.cpp \
     ihs_server7702.cpp \
+    irc7702_tables.cpp \
     lmi.cpp \
     md5.cpp \
     mec_input.cpp \
@@ -632,6 +633,7 @@ test_commutation_functions_SOURCES = \
   commutation_functions.cpp \
   commutation_functions_test.cpp \
   cso_table.cpp \
+  irc7702_tables.cpp \
   timer.cpp
 test_commutation_functions_CXXFLAGS = $(AM_CXXFLAGS)
 
@@ -1241,6 +1243,7 @@ noinst_HEADERS = \
     input_sequence_parser.hpp \
     interest_rates.hpp \
     interpolate_string.hpp \
+    irc7702_tables.hpp \
     istream_to_string.hpp \
     ledger.hpp \
     ledger_base.hpp \
diff --git a/README.schroot b/README.schroot
index 3211add..d2f77d5 100644
--- a/README.schroot
+++ b/README.schroot
@@ -111,7 +111,7 @@ apt-get update
 apt-get --assume-yes install wget g++-mingw-w64 automake libtool make \
  pkg-config git cvs zsh bzip2 unzip sudo wine default-jre jing trang \
  g++-multilib libxml2-utils libxslt1-dev vim-gtk vim-doc shellcheck \
- xsltproc \
+ bc bsdtar xsltproc \
  >lmi-buster2-apt-get-log 2>&1
 
 # This command should produce little output:
diff --git a/bcc_5_5_1.make b/bcc_5_5_1.make
index 2d0cf0b..784268d 100644
--- a/bcc_5_5_1.make
+++ b/bcc_5_5_1.make
@@ -53,7 +53,9 @@ compiler_impersonation_cppflags := \
   -D WIN32_LEAN_AND_MEAN \
   -I $(shadow_header_directory) \
 
-gcc3_dir     := /MinGW_
+# This makefile because unusable long ago, so this dependency has been
+# renamed to avoid pointless maintenance updates.
+gcc3_dir     := /opt/lmi/no_longer_usable
 gcc3_bin_dir := $(gcc3_dir)/bin
 
 # Casual workarounds for borland C++ version 5.5.1 . The vendor calls
diff --git a/check_git_setup.sh b/check_git_setup.sh
index 08117fd..a61e949 100755
--- a/check_git_setup.sh
+++ b/check_git_setup.sh
@@ -24,7 +24,7 @@
 # Navigate to the directory where this script resides, and make sure
 # it's a git "toplevel" directory.
 
-cd $(dirname $(readlink -f "$0")) || printf 'Cannot cd\n'
+cd "$(dirname "$(readlink -f "$0")")" || printf 'Cannot cd\n'
 toplevel=$(git rev-parse --show-toplevel)
 printf '"%s" is current directory\n' "$PWD"
 printf '"%s" is git toplevel directory\n' "$toplevel"
diff --git a/commutation_functions_test.cpp b/commutation_functions_test.cpp
index 0a435f9..58e8916 100644
--- a/commutation_functions_test.cpp
+++ b/commutation_functions_test.cpp
@@ -25,13 +25,16 @@
 
 #include "cso_table.hpp"
 #include "et_vector.hpp"
+#include "irc7702_tables.hpp"
+#include "materially_equal.hpp"
 #include "math_functions.hpp"
 #include "ssize_lmi.hpp"
 #include "test_tools.hpp"
 #include "timer.hpp"
 
 #include <algorithm>
-#include <cmath>                        // fabs()
+#include <cfloat>                       // DBL_EPSILON
+#include <cmath>                        // fabs(), log()
 #include <functional>                   // bind()
 #include <iomanip>                      // setw() etc.
 #include <ios>                          // ios_base::fixed()
@@ -709,6 +712,567 @@ void Test_1980_CSO_Male_ANB()
         ;
 }
 
+// These two arrays are pasted from the "corridor mult" and "7Pt"
+// columns of 'validate_2001cso', after loading that spreadsheet
+// in 'gnumeric' and formatting those columns to twenty decimals.
+// They use UL commutation functions. See:
+//   https://lists.nongnu.org/archive/html/lmi/2015-07/msg00004.html
+
+static double const ss_ul_corr[100] =
+{16.05428685334679173025
+,15.58833599045649087600
+,15.08131070200895074152
+,14.56342500447235721595
+,14.04800434985640045227
+,13.54397833171609022429
+,13.05507387234714933300
+,12.58409661481673680328
+,12.13030984655223143420
+,11.69174091577074925397
+,11.26914166185736476677
+,10.86078105527353621085
+,10.47029884268147448267
+,10.09843359081480329564
+, 9.74294658529263379876
+, 9.40759852219825454256
+, 9.09057733647785148889
+, 8.79027993284445763322
+, 8.50397918973384925323
+, 8.22818279387080941945
+, 7.96118932260834633041
+, 7.70160265863622406357
+, 7.44976553796342688685
+, 7.20499258154732391546
+, 6.96714059909527883008
+, 6.73646229302490073820
+, 6.51311660413237181189
+, 6.29752334665072410758
+, 6.08868484174302349032
+, 5.88548788700455993705
+, 5.68759233818214315903
+, 5.49522616091999260846
+, 5.30831030469870679411
+, 5.12719475896684162564
+, 4.95191511278486373726
+, 4.78246091867951061971
+, 4.61878315488500756913
+, 4.46095911393538724354
+, 4.30885324846834905088
+, 4.16231281496283944676
+, 4.02117206738939625410
+, 3.88525584688570946312
+, 3.75459497560775545821
+, 3.62916166404261142375
+, 3.50888104609130779821
+, 3.39355762372614266908
+, 3.28298850929638108553
+, 3.17689558846831987537
+, 3.07468880549077061559
+, 2.97599858560200258850
+, 2.88084470780052326333
+, 2.78925893311157580001
+, 2.70137019361723274002
+, 2.61714709838817194409
+, 2.53660248632115825629
+, 2.45973786190931420492
+, 2.38640466067929235550
+, 2.31641149864538897774
+, 2.24933351623363186889
+, 2.18485859704871998588
+, 2.12298548776600348731
+, 2.06377060631972986116
+, 2.00732734016649461140
+, 1.95364688011445042370
+, 1.90257560558083449465
+, 1.85390645085427285821
+, 1.80741123662186708998
+, 1.76283474569483433747
+, 1.72002394995400198496
+, 1.67882810972211782286
+, 1.63921097550600691761
+, 1.60120703518178442160
+, 1.56497463008854764688
+, 1.53056280828563395779
+, 1.49778239342608299189
+, 1.46651641824560186045
+, 1.43669325356442145747
+, 1.40828569180480034362
+, 1.38135623671030072224
+, 1.35595612880361837682
+, 1.33205157176719568568
+, 1.30966078753973991233
+, 1.28874851143154445232
+, 1.26913015525378947146
+, 1.25071057910177563244
+, 1.23349050718607222699
+, 1.21741784864651991782
+, 1.20250900968492024923
+, 1.18879112389207719502
+, 1.17616396084234375863
+, 1.16443752080775975166
+, 1.15305360309844973088
+, 1.14154811660101529469
+, 1.12990850456893321407
+, 1.11805918549405669538
+, 1.10585007755591901990
+, 1.09272887195287826678
+, 1.07768889207696427768
+, 1.05889467902677236744
+, 1.03392745267212093907
+};
+
+static double const ss_ul_7pp[100] =
+{0.00999062440751989980
+,0.01028589716601673552
+,0.01062994889232243140
+,0.01100709650196978612
+,0.01141070148832002557
+,0.01183541561717901119
+,0.01227894262614234906
+,0.01273890281958302631
+,0.01321604446917592178
+,0.01371289447070540846
+,0.01422886804024923145
+,0.01476663382430560070
+,0.01532082243677517636
+,0.01588896142650659399
+,0.01647329371041960158
+,0.01706468830702987174
+,0.01766329128405109278
+,0.01826920380439612038
+,0.01888577215846250559
+,0.01951980733786566266
+,0.02017525559338708904
+,0.02085633674231307522
+,0.02156255487066226217
+,0.02229655784475696040
+,0.02305946770995651388
+,0.02385084039099466188
+,0.02467017211649025557
+,0.02551531634397709650
+,0.02639053264687007266
+,0.02730200324593424696
+,0.02825306412357134547
+,0.02924406198100011275
+,0.03027703373115286228
+,0.03135091541809587046
+,0.03246623554060621558
+,0.03362359115588391123
+,0.03482374166899589174
+,0.03606599422970604291
+,0.03735138265340059993
+,0.03868112554395738284
+,0.04005664955242391884
+,0.04147956289034327587
+,0.04294811241142196950
+,0.04446025296529201171
+,0.04601393073756083335
+,0.04760879558840754727
+,0.04924490987244876244
+,0.05092435295618532448
+,0.05265819337044034404
+,0.05445592655778288410
+,0.05631857051817811682
+,0.05824605305494993251
+,0.06023316553704032711
+,0.06227739915724234826
+,0.06437337655335158282
+,0.06651452375385756566
+,0.06870008885031553270
+,0.07093229090910557755
+,0.07322803247632281298
+,0.07560364239280463472
+,0.07805934610230855220
+,0.08058864677483222605
+,0.08317610640496489460
+,0.08580967539473746686
+,0.08848738367896104295
+,0.09121467879909027354
+,0.09400583834207149048
+,0.09688672842792392381
+,0.09987797601076543741
+,0.10300586867342216568
+,0.10628627958701071521
+,0.10972561873411729172
+,0.11330637125813265709
+,0.11702343505126171219
+,0.12092139119378841894
+,0.12504454546357654521
+,0.12943750862444663996
+,0.13413592524308720622
+,0.13914635982676987203
+,0.14447036818012279347
+,0.15013201659901123652
+,0.15613245573059561511
+,0.16249080594919776410
+,0.16930561735046611993
+,0.17664266810670117835
+,0.18447808708057295002
+,0.19278062434737353037
+,0.20145103153300336629
+,0.21034011597622215284
+,0.21938905920499771063
+,0.22862636208321829301
+,0.23858323922962185182
+,0.24981209741923118828
+,0.26220186143911550225
+,0.28642313285880155460
+,0.31717670783614265728
+,0.35965728769722676850
+,0.42686340219691948361
+,0.56031960772985123231
+,0.96718584791956385693
+};
+
+static double const ss_ol_corr[100] =
+{16.03069515721970
+,15.56545542916450
+,15.05919070490880
+,14.54207568908480
+,14.02741865395940
+,13.52413778894550
+,13.03595534928800
+,12.56567351181010
+,12.11255664606990
+,11.67463475724690
+,11.25265884919660
+,10.84490022682110
+,10.45499411648920
+,10.08367827587890
+, 9.72871697105366
+, 9.39386625032253
+, 9.07731649360929
+, 8.77746677844702
+, 8.49159356632208
+, 8.21620906614680
+, 7.94961408895666
+, 7.69041434829488
+, 7.43895222208455
+, 7.19454325862477
+, 6.95704451334878
+, 6.72670844298237
+, 6.50369386229784
+, 6.28842014111261
+, 6.07989090207194
+, 5.87699437244831
+, 5.67939087980040
+, 5.48730816704992
+, 5.30066733657544
+, 5.11981801243330
+, 4.94479580197072
+, 4.77559033227269
+, 4.61215270269525
+, 4.45456017660894
+, 4.30267743185537
+, 4.15635196932867
+, 4.01541830136802
+, 3.87970153695790
+, 3.74923252419573
+, 3.62398356964482
+, 3.50387995898405
+, 3.38872648535844
+, 3.27832055910429
+, 3.17238444761715
+, 3.07032882594890
+, 2.97178458990226
+, 2.87677154683430
+, 2.78532147558464
+, 2.69756322259474
+, 2.61346549280934
+, 2.53304117542039
+, 2.45629184138028
+, 2.38306915684781
+, 2.31318201343135
+, 2.24620607000211
+, 2.18182960005580
+, 2.12005141288773
+, 2.06092793502465
+, 2.00457251268315
+, 1.95097642680359
+, 1.89998629486328
+, 1.85139534102519
+, 1.80497569334546
+, 1.76047246308625
+, 1.71773284834008
+, 1.67660633172185
+, 1.63705678130120
+, 1.59911874599313
+, 1.56295053110245
+, 1.52860126016288
+, 1.49588204901423
+, 1.46467616317511
+, 1.43491217369859
+, 1.40656304375306
+, 1.37969137924250
+, 1.35434853909332
+, 1.33050092572148
+, 1.30816690878090
+, 1.28731141765329
+, 1.26775022859716
+, 1.24938847835256
+, 1.23222703314812
+, 1.21621399207302
+, 1.20136578942719
+, 1.18770946309554
+, 1.17514487873005
+, 1.16348237607749
+, 1.15216547131899
+, 1.14073189550427
+, 1.12916922360185
+, 1.11740178851122
+, 1.10527880649853
+, 1.09224812150223
+, 1.07730439700387
+, 1.05861825755067
+, 1.03377932830447
+};
+
+static double const ss_ol_7pp[100] =
+{0.010005327186958
+,0.010301016999909
+,0.010645562907928
+,0.011023256091546
+,0.011427447066149
+,0.011852778725528
+,0.012296950914868
+,0.012757579901923
+,0.013235415035928
+,0.013732987171806
+,0.014249710382439
+,0.014788257479081
+,0.015343250090949
+,0.015912211536579
+,0.016497388214910
+,0.017089634046416
+,0.017689095179996
+,0.018295872789306
+,0.018913318467641
+,0.019548254138137
+,0.020204632276942
+,0.020886679342528
+,0.021593898359639
+,0.022328941267110
+,0.023092931684899
+,0.023885424544973
+,0.024705914983204
+,0.025552252675176
+,0.026428703850223
+,0.027341460483306
+,0.028293863627333
+,0.029286260140180
+,0.030320689819902
+,0.031396086507395
+,0.032512979072804
+,0.033671965026394
+,0.034873804442084
+,0.036117802719780
+,0.037404994687573
+,0.038736600205397
+,0.040114047455165
+,0.041538946413990
+,0.043009540227530
+,0.044523779574169
+,0.046079606410946
+,0.047676669074214
+,0.049315028941757
+,0.050996767549288
+,0.052732969936346
+,0.054533145156035
+,0.056398310810159
+,0.058328392333208
+,0.060318170371727
+,0.062365129728319
+,0.064463881836038
+,0.066607839381289
+,0.068796246114121
+,0.071031321069015
+,0.073329989610741
+,0.075708601646018
+,0.078167377428823
+,0.080699804001149
+,0.083290412982767
+,0.085927129777381
+,0.088607974722984
+,0.091338396338728
+,0.094132685084862
+,0.097016735479080
+,0.100011192647016
+,0.103142368320708
+,0.106426141130087
+,0.109868909420875
+,0.113453108667038
+,0.117173603120152
+,0.121075007777516
+,0.125201654498742
+,0.129598172492744
+,0.134300204399513
+,0.139314266113466
+,0.144641852159782
+,0.150306989508367
+,0.156310753283924
+,0.162672203024568
+,0.169489903915145
+,0.176829591075732
+,0.184667243191684
+,0.192971446212092
+,0.201642732430611
+,0.210531675161746
+,0.219579312738766
+,0.228814049726310
+,0.238767148018836
+,0.249990843980925
+,0.262373528220005
+,0.286591643152315
+,0.317340642829014
+,0.359815590009435
+,0.427015751779345
+,0.560465915779944
+,0.967324430485689
+};
+
+/// Test CVAT corridor and seven-pay premium.
+
+void Test_Corridor_and_7PP()
+{
+    std::vector<double> const naar_discount
+        (100
+        ,i_upper_12_over_12_from_i<double>()(0.04)
+        );
+    irc7702_tables z
+        (oe_2001cso
+        ,oe_orthodox
+        ,oe_age_last_birthday
+        ,mce_unisex
+        ,mce_unismoke
+        ,naar_discount
+        ,1.0 / 12.0
+        ,0
+        ,100
+        );
+    std::vector<double> const& ul_corr = z.ul_corr();
+    std::vector<double> const& ul_7pp  = z.ul_7pp ();
+    std::vector<double> const& ol_corr = z.ol_corr();
+    std::vector<double> const& ol_7pp  = z.ol_7pp ();
+
+    // In the last year, the OL formula reduces to:
+    //   NSP[omega-1] = vq * (i/delta) + vp
+    //   (0.30285 / 1.04) * (0.04 / ln(1.04)) + (1 - 0.30285) / 1.04
+    BOOST_TEST(materially_equal(0.30285, z.q_[99], 0.0));
+    double ol_nsp99 =
+          (       z.q_[99]  / 1.04) * (0.04 / std::log(1.04))
+        +  (1.0 - z.q_[99]) / 1.04
+        ;
+    BOOST_TEST(materially_equal(ol_corr[99], 1.0 / ol_nsp99, DBL_EPSILON));
+
+    for(int j = 0; j < lmi::ssize(ol_corr); ++j)
+        {
+        // Values calculated here must match spreadsheet values to
+        // within a minuscule tolerance.
+        BOOST_TEST(materially_equal(ss_ul_corr[j], ul_corr[j]));
+        BOOST_TEST(materially_equal(ss_ul_7pp [j], ul_7pp [j]));
+        BOOST_TEST(materially_equal(ss_ol_corr[j], ol_corr[j]));
+        BOOST_TEST(materially_equal(ss_ol_7pp [j], ol_7pp [j]));
+        // The 0.0015 tolerance was found experimentally, not by any
+        // sort of mathematical law. It represents the inherent
+        // discrepancy between the UL method on the one hand, and the
+        // OL method (with the i/delta approximation) on the other.
+        BOOST_TEST(materially_equal(   ol_corr[j], ul_corr[j], 0.0015));
+        BOOST_TEST(materially_equal(   ol_7pp [j], ul_7pp [j], 0.0015));
+        }
+
+    // At least for now, display plenty of detail.
+
+    std::cout << std::endl;
+
+    std::cout
+        << ol_corr[99] << " OL corr[omega-1]\n"
+        << 1.0 / ol_nsp99 << " vq * (i/delta) + vp\n"
+        << std::endl
+        ;
+
+    std::cout << "q, UL corr, UL 7pp, OL corr, OL 7pp\n";
+    for(int j = 0; j < lmi::ssize(ol_corr); ++j)
+        {
+        std::cout
+            << j
+            << '\t' << z.q_[j]
+            << '\t' << ul_corr[j]
+            << '\t' << ul_7pp[j]
+            << '\t' << ol_corr[j]
+            << '\t' << ol_7pp[j]
+            << '\n';
+        }
+    std::cout << std::endl;
+
+    std::vector<double> q12(lmi::ssize(ol_corr));
+    assign(q12, apply_binary(coi_rate_from_q<double>(), z.q_, 1.0 / 12.0));
+    std::cout << "q, q upper (12), UL corr, UL 7pp\n";
+    for(int j = 0; j < lmi::ssize(ul_corr); ++j)
+        {
+        std::cout
+            << j
+            << '\t' << z.q_[j]
+            << '\t' << q12[j]
+            << '\t' << ul_corr[j]
+            << '\t' << ul_7pp[j]
+            << '\n';
+        }
+    std::cout << std::endl;
+
+    std::cout << "UL corr, OL corr, relative error\n";
+    for(int j = 0; j < lmi::ssize(ul_corr); ++j)
+        {
+        std::cout
+            << j
+            << '\t' << ul_corr[j]
+            << '\t' << ol_corr[j]
+            << '\t' << (ol_corr[j] - ul_corr[j]) / ul_corr[j]
+            << '\n';
+        }
+    std::cout << std::endl;
+
+    std::cout << "UL 7pp, OL 7pp, relative error\n";
+    for(int j = 0; j < lmi::ssize(ul_corr); ++j)
+        {
+        std::cout
+            << j
+            << '\t' << ul_7pp[j]
+            << '\t' << ol_7pp[j]
+            << '\t' << (ol_7pp[j] - ul_7pp[j]) / ul_7pp[j]
+            << '\n';
+        }
+    std::cout << std::endl;
+
+    std::cout << "UL corr, 7pp: {calculated, spreadsheet, relative error}\n";
+    for(int j = 0; j < lmi::ssize(ss_ul_corr); ++j)
+        {
+        std::cout
+            << j
+            << '\t' << ul_corr[j]
+            << '\t' << ss_ul_corr[j]
+            << '\t' << (ss_ul_corr[j] - ul_corr[j]) / ul_corr[j]
+            << '\t' << ul_7pp[j]
+            << '\t' << ss_ul_7pp[j]
+            << '\t' << (ss_ul_7pp[j] - ul_7pp[j]) / ul_7pp[j]
+            << '\n';
+        }
+    std::cout << std::endl;
+
+    std::cout << "OL corr, 7pp: {calculated, spreadsheet, relative error}\n";
+    for(int j = 0; j < lmi::ssize(ss_ul_corr); ++j)
+        {
+        std::cout
+            << j
+            << '\t' << ol_corr[j]
+            << '\t' << ss_ol_corr[j]
+            << '\t' << (ss_ol_corr[j] - ol_corr[j]) / ol_corr[j]
+            << '\t' << ol_7pp[j]
+            << '\t' << ss_ol_7pp[j]
+            << '\t' << (ss_ol_7pp[j] - ol_7pp[j]) / ol_7pp[j]
+            << '\n';
+        }
+}
+
 /// Test UL commutation functions in extreme cases.
 ///
 /// For example, ic and ig can both be zero, and qc may round to zero
@@ -727,6 +1291,7 @@ int test_main(int, char*[])
     ULCommFnsTest();
     OLCommFnsTest();
     Test_1980_CSO_Male_ANB();
+    Test_Corridor_and_7PP();
     TestLimits();
 
     return EXIT_SUCCESS;
diff --git a/como.make b/como.make
index 8cc9463..70bb162 100644
--- a/como.make
+++ b/como.make
@@ -76,7 +76,9 @@ UNUSED_compiler_impersonation_cppflags := \
   -D LMI_IGNORE_PCH \
   -D __COMO__ \
 
-gcc3_dir     := /MinGW_
+# This makefile because unusable long ago, so this dependency has been
+# renamed to avoid pointless maintenance updates.
+gcc3_dir     := /opt/lmi/no_longer_usable
 gcc3_bin_dir := $(gcc3_dir)/bin
 
 # Comeau C++ for msw requires both its own bin/ directory and the
diff --git a/cover.mst b/cover.mst
index e1b759c..a9f376e 100644
--- a/cover.mst
+++ b/cover.mst
@@ -136,8 +136,6 @@ it roughly where we want it to appear.
 <p align="center"><img inv_factor="0.45" src="company_logo.png"></img></p>
 
 <br></br>
-<br></br>
-<br></br>
 
 <font size="-1">
 
diff --git a/cso_table.cpp b/cso_table.cpp
index 37d22cd..0ac73dd 100644
--- a/cso_table.cpp
+++ b/cso_table.cpp
@@ -916,8 +916,36 @@ static double const 
q2017[cso_n_alb_or_anb][cso_n_gender][cso_n_smoking][cso_ome
   },
 };
 
+namespace
+{
+int get_sns_age(oenum_cso_era cso_era, mcenum_smoking smoking)
+{
+    return
+        ((mce_unismoke == smoking) ? 0
+        :(oe_1980cso == cso_era) ? cso_sns_age_1980
+        :(oe_2001cso == cso_era) ? cso_sns_age_2001
+        :(oe_2017cso == cso_era) ? cso_sns_age_2017
+        :                          throw "invalid cso sns age"
+        );
+}
+
+int get_omega(oenum_cso_era cso_era)
+{
+    return
+        ((oe_1980cso == cso_era) ? cso_omega_1980
+        :(oe_2001cso == cso_era) ? cso_omega_2001
+        :(oe_2017cso == cso_era) ? cso_omega_2017
+        :                          throw "invalid cso omega"
+        );
+}
+} // Unnamed namespace.
+
 /// Return a single CSO ultimate table.
 ///
+/// This overload returns a [min_age, max_age] subset of a full
+/// valuation table that has been padded if necessary to provide
+/// values for all ages from zero to omega.
+///
 /// Only the 1980, 2001, and 2017 eras are supported.
 ///
 /// CSO tables are either ANB or ALB; they disregard other nuances of
@@ -941,6 +969,8 @@ std::vector<double> cso_table
     ,oenum_alb_or_anb alb_or_anb
     ,mcenum_gender    gender
     ,mcenum_smoking   smoking
+    ,int              min_age
+    ,int              max_age
     )
 {
     bool const is_anb = alb_or_anb != oe_age_last_birthday;
@@ -950,26 +980,17 @@ std::vector<double> cso_table
         :(oe_2017cso == cso_era) ? q2017[is_anb][gender][smoking]
         :                          throw "invalid cso era"
         );
-    int const sns_age =
-        ((mce_unismoke == smoking) ? 0
-        :(oe_1980cso == cso_era) ? cso_sns_age_1980
-        :(oe_2001cso == cso_era) ? cso_sns_age_2001
-        :(oe_2017cso == cso_era) ? cso_sns_age_2017
-        :                          throw "invalid cso sns age"
-        );
-    int const omega =
-        ((oe_1980cso == cso_era) ? cso_omega_1980
-        :(oe_2001cso == cso_era) ? cso_omega_2001
-        :(oe_2017cso == cso_era) ? cso_omega_2017
-        :                          throw "invalid cso omega"
-        );
+    int const sns_age = get_sns_age(cso_era, smoking);
+    int const omega   = get_omega  (cso_era         );
 
-    if(mce_unismoke != smoking)
-        {
-        LMI_ASSERT(each_equal(p, p + sns_age, 0.0));
-        }
+    LMI_ASSERT(each_equal(p, p + sns_age, 0.0));
+    LMI_ASSERT(0 == std::count(p + sns_age, p + omega, 0.0));
+    LMI_ASSERT(1.0 == p[omega - 1]);
+
+    LMI_ASSERT(0 <= min_age);
+    LMI_ASSERT(max_age <= omega);
 
-    std::vector<double> v(p + sns_age, p + omega);
+    std::vector<double> v(p + min_age, p + max_age);
 
     if
         (oe_heterodox    == autopisty
@@ -983,19 +1004,43 @@ std::vector<double> cso_table
         // was also ratified by NAIC).
         if(is_anb)
             {
-            LMI_ASSERT(0.03831 == v[56]);
-            v[56] =    0.03891;
+            LMI_ASSERT(0.03831 == v[71 - min_age]);
+            v[71 - min_age] =    0.03891;
             }
         else
             {
-            LMI_ASSERT(0.03644 == v[55]);
-            v[55] =    0.03673;
-            LMI_ASSERT(0.04039 == v[56]);
-            v[56] =    0.04070;
+            LMI_ASSERT(0.03644 == v[71 - min_age - 1]);
+            v[71 - min_age - 1] =    0.03673;
+            LMI_ASSERT(0.04039 == v[71 - min_age]);
+            v[71 - min_age] =    0.04070;
             }
         }
 
-    LMI_ASSERT(0 == std::count(v.begin(), v.end(), 0.0));
-    LMI_ASSERT(1.0 == v.back());
     return v;
 }
+
+/// Return a single CSO ultimate table.
+///
+/// This overload returns a full valuation table including all ages
+/// from zero (padded if necessary) to omega.
+///
+/// See the overload with more arguments for details.
+
+std::vector<double> cso_table
+    (oenum_cso_era    cso_era
+    ,oenum_autopisty  autopisty
+    ,oenum_alb_or_anb alb_or_anb
+    ,mcenum_gender    gender
+    ,mcenum_smoking   smoking
+    )
+{
+    return cso_table
+        (cso_era
+        ,autopisty
+        ,alb_or_anb
+        ,gender
+        ,smoking
+        ,get_sns_age(cso_era, smoking)
+        ,get_omega  (cso_era         )
+        );
+}
diff --git a/cso_table.hpp b/cso_table.hpp
index 99e07a3..5999ecb 100644
--- a/cso_table.hpp
+++ b/cso_table.hpp
@@ -36,6 +36,16 @@ std::vector<double> LMI_SO cso_table
     ,oenum_alb_or_anb
     ,mcenum_gender
     ,mcenum_smoking
+    ,int              min_age
+    ,int              max_age
+    );
+
+std::vector<double> LMI_SO cso_table
+    (oenum_cso_era
+    ,oenum_autopisty
+    ,oenum_alb_or_anb
+    ,mcenum_gender
+    ,mcenum_smoking
     );
 
 #endif // cso_table_hpp
diff --git a/finra_footer_upper.mst b/finra_footer_upper.mst
index f9f3983..364b717 100644
--- a/finra_footer_upper.mst
+++ b/finra_footer_upper.mst
@@ -19,6 +19,11 @@
     snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
 }}
 
+{{!
+    This is only required on the first page after the cover page,
+    but it seems more convenient to print it on all pages.
+}}
+
 <font size="-2">
 
 <p>
diff --git a/gui_test.sh b/gui_test.sh
index fa9f18c..6c2ba03 100755
--- a/gui_test.sh
+++ b/gui_test.sh
@@ -131,7 +131,12 @@ gui_test_clutter='
 '
 
 # Directory for test logs.
-log_dir=/tmp/lmi/"${LMI_COMPILER}_${LMI_TRIPLET}"/logs
+#
+# It seems redundant to construct yet another $prefix and $exec_prefix here;
+# perhaps that should be done OAOO in a script that selects a toolchain.
+prefix=/opt/lmi
+exec_prefix="$prefix/${LMI_COMPILER}_${LMI_TRIPLET}"
+log_dir="$exec_prefix"/logs
 mkdir --parents "$log_dir"
 
 cd /opt/lmi/src/lmi
diff --git a/gwc/child.make b/gwc/child.make
new file mode 100644
index 0000000..4505ae7
--- /dev/null
+++ b/gwc/child.make
@@ -0,0 +1,3 @@
+.PHONY: all
+all:
+       @echo "'$$LMI_IN' --> '$$LMI_OUT1', '$$LMI_OUT2' : targets in 
'child.make'"
diff --git a/gwc/company_logo.png b/gwc/company_logo.png
index 8d26457..63295ca 100644
Binary files a/gwc/company_logo.png and b/gwc/company_logo.png differ
diff --git a/gwc/develop1.txt b/gwc/develop1.txt
index b1d1b25..377c186 100644
--- a/gwc/develop1.txt
+++ b/gwc/develop1.txt
@@ -79,6 +79,11 @@ git checkout odd/foo
 git commit sandbox_test.cpp
 git checkout master
 git push origin odd/foo
+  # (to copy to a subdir before deletion, so it's in permanent history)
+  # (this works only if all modified files are unique to the branch)
+git checkout master
+git format-patch --output-directory=/tmp/patch/ master..odd/foo
+git am --directory=gwc /tmp/patch/*
   # (to expunge branch if later cherry-picked)
 git branch --delete odd/foo
 git push origin --delete odd/foo
diff --git a/gwc/parent.make b/gwc/parent.make
new file mode 100644
index 0000000..81fd3eb
--- /dev/null
+++ b/gwc/parent.make
@@ -0,0 +1,43 @@
+# This demonstration shows a way to source a script in a makefile,
+# and export environment variables set by that script to make's
+# environment:
+#  - form a unique name $LMI_ENV_FILE for a file to hold the value
+#  - give the top-level makefile a target to remake itself, with
+#     - $(eval include $(LMI_ENV_FILE)) in its recipe, and
+#     - $(LMI_ENV_FILE) as a prerequisite
+#  - add a phony $(LMI_ENV_FILE) target that sources the script
+#  - make the script write 'make' assignments like "export foo := bar"
+#    for each desired environment variable to a file named
+#    $LMI_ENV_FILE, iff that filename is of nonzero length
+# To test:
+#   $export LMI_IN=Russia;   make -f parent.make all
+#   $export LMI_IN=Mongolia; make -f parent.make all
+# and check what appears on stdout.
+
+export LMI_ENV_FILE := env_$(shell date -u +'%s_%N').eraseme
+
+parent.make:: $(LMI_ENV_FILE)
+       $(eval include $(LMI_ENV_FILE))
+       @echo "'$$LMI_IN' --> '$$LMI_OUT1', '$$LMI_OUT2' : eval in 
'parent.make'"
+       rm $(LMI_ENV_FILE)
+
+$(LMI_ENV_FILE):
+       @echo "Sourcing 'set.sh'"; \
+       . ./set.sh ; \
+       echo "'$$LMI_IN' --> '$$LMI_OUT1', '$$LMI_OUT2' : sourced in 
'parent.make'"
+
+all:
+       @echo "'$$LMI_IN' --> '$$LMI_OUT1', '$$LMI_OUT2' : targets in 
'parent.make'"
+       $(MAKE) --no-print-directory -f child.make
+
+# Obviously one could simply write a cover script to replace direct
+# invocation of 'make', but that's nasty. See:
+#   https://lists.gnu.org/archive/html/help-make/2006-04/msg00142.html
+# which suggests 'eval'.
+#
+# This is unhelpful:
+#   
https://stackoverflow.com/questions/7507810/how-to-source-a-script-in-a-makefile
+# except that it has a link to:
+#   https://blog.153.io/2016/04/18/source-a-shell-script-in-make/
+# which doesn't actually work in its final, simplified version;
+# but earlier in that article it uses 'eval include', which does work.
diff --git a/gwc/set.sh b/gwc/set.sh
new file mode 100755
index 0000000..0660dc9
--- /dev/null
+++ b/gwc/set.sh
@@ -0,0 +1,29 @@
+#!/bin/sh this-script-must-be-sourced-not-run
+
+foo()
+{
+# $LMI_ENV_FILE is defined by the makefile that sources this script.
+# shellcheck disable=SC2154
+echo "LMI_ENV_FILE in 'set.sh': $LMI_ENV_FILE"
+echo "'$LMI_IN' --> '$LMI_OUT1', '$LMI_OUT2' : entering 'set.sh'"
+export LMI_OUT1="$LMI_IN"
+export LMI_OUT2="$LANG"
+
+case "$LMI_IN" in
+    (Mongolia) LMI_OUT2="mn_MN" ;;
+    (Russia)   LMI_OUT2="ru_RU" ;;
+    (*) ;;
+esac
+
+echo "'$LMI_IN' --> '$LMI_OUT1', '$LMI_OUT2' : leaving 'set.sh'"
+if [ -n "$LMI_ENV_FILE" ]; then
+    {
+    echo "export LMI_OUT1 := $LMI_OUT1"
+    echo "export LMI_OUT2 := $LMI_OUT2"
+    } > "$LMI_ENV_FILE"
+fi
+}
+
+foo
+
+unset -f foo
diff --git a/gwc/xc b/gwc/xc
deleted file mode 100644
index 7aa41ff..0000000
--- a/gwc/xc
+++ /dev/null
@@ -1,198 +0,0 @@
-# prerequisites
-
-apt-get update
-apt-get install g++-mingw-w64-i686 automake libtool make pkg-config
-apt-get install subversion git
-# optional--personal preferences only:
-apt-get install zsh gnome-system-monitor geany
-# only for VM clipboard support
-apt-get install spice-vdagent
-# ...in VM...apparently not needed
-# update-rc.d spice-vdagent defaults
-
-chsh -s /bin/zsh greg
-
-cat >~/.zshrc <<EOF
-# 
PATH="/opt/lmi/local/bin:/opt/lmi/local/lib:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH"
-
-export coefficiency="--jobs=`nproc`"
-
-# export TZ=UCT
-# export LC_COLLATE=C.UTF-8
-
-# bindkey "\e[3~" delete-char      # Del
-# bindkey '\e[H' beginning-of-line # Home
-# bindkey '\e[F' end-of-line       # End
-bindkey "^[[1;5D" backward-word  # Ctrl-left
-bindkey "^[[1;5C" forward-word   # Ctrl-right
-bindkey '\e[1;3D' backward-word  # Alt-left
-bindkey '\e[1;3C' forward-word   # Alt-right
-
-prompt='%d[%?]%(!.#.$)'
-
-HISTSIZE=1000
-SAVEHIST=1000
-HISTFILE=~/.history
-setopt HIST_IGNORE_DUPS
-
-autoload -U compinit
-compinit -u
-
-# The following lines were added by compinstall
-
-# zstyle ':completion:*' completer _complete _ignored
-# zstyle :compinstall filename '/home/greg/.zshrc'
-
-# autoload -Uz compinit
-# compinit
-# End of lines added by compinstall
-EOF
-
-# fix libtool breakage (needs work)
-
-http://lists.gnu.org/archive/html/libtool-patches/2011-06/msg00001.html
-
---- /usr/share/libtool/config/ltmain.sh.original       2016-01-25 
03:43:07.768000000 +0000
-+++ /usr/share/libtool/config/ltmain.sh        2016-01-25 03:44:17.100000000 
+0000
-@@ -4178,7 +4178,8 @@
- /* declarations of non-ANSI functions */
- #if defined(__MINGW32__)
- # ifdef __STRICT_ANSI__
--int _putenv (const char *);
-+     /* int _putenv (const char *); */
-+_CRTIMP int _putenv (const char *);
- # endif
- #elif defined(__CYGWIN__)
- # ifdef __STRICT_ANSI__
-
-# downloads: once only
-
-mkdir --parents ~/src
-cd ~/src
-svn checkout http://svn.sv.nongnu.org/svn/lmi/lmi/trunk lmi 2>&1 |less
-
-mkdir --parents ~/src/3rdparty
-
-cd ~/src/3rdparty
-wget http://downloads.sourceforge.net/boost/boost_1_38_0.tar.bz2
-tar xf boost_1_38_0.tar.bz2
-
-cd ~/src/3rdparty
-wget ftp://ftp.gnome.org/pub/GNOME/sources/libxml2/2.6/libxml2-2.6.26.tar.bz2
-tar xf libxml2-2.6.26.tar.bz2
-
-cd ~/src/3rdparty
-#wget http://svn.sv.nongnu.org/svn/lmi/lmi/trunk/libxslt-1.1.17-lmi.patch
-wget ftp://ftp.gnome.org/pub/GNOME/sources/libxslt/1.1/libxslt-1.1.17.tar.bz2
-tar xf libxslt-1.1.17.tar.bz2
-patch --strip=1 <~/src/lmi/libxslt-1.1.17-lmi.patch
-
-cd ~/src/3rdparty
-git clone https://github.com/vadz/xmlwrapp.git
-cd xmlwrapp
-
-cd ~/src/3rdparty
-git clone https://github.com/wxWidgets/wxWidgets.git
-
-cd ~/src/3rdparty
-git clone https://github.com/vadz/wxpdfdoc.git
-
-# updates: only after initial download
-
-# [svn update; git too; we can flesh this step out later]
-
-# build
-
-mkdir ~/build
-mkdir --parents ~/msw/i686-w64-mingw32/lib
-cd ~/src/3rdparty/boost_1_38_0
-# it would seem nicer not to build in the source directories
-for z in regex system filesystem; \
-  do (cd libs/$z/src && \
-  i686-w64-mingw32-g++ -I../../.. -c *.cpp && \
-  i686-w64-mingw32-ar rc ~/msw/i686-w64-mingw32/lib/libboost_$z.a *.o); done
-mkdir --parents ~/msw/i686-w64-mingw32/include
-cp -a boost ~/msw/i686-w64-mingw32/include/
-
-cd ~/src/3rdparty
-mkdir ~/build/libxml2-msw
-cd $_
-~/src/3rdparty/libxml2-2.6.26/configure \
-  --disable-static --enable-shared \
-  --with-{debug,schemas} --without-{iconv,modules,python,schematron} \
-  --prefix=$HOME/msw/i686-w64-mingw32 \
-  --build=x86_64-unknown-linux-gnu \
-  --host=i686-w64-mingw32 \
-  --without-threads
-make $coefficiency --quiet install
-
-cd ~/src/3rdparty
-mkdir ~/build/libxslt-msw
-cd $_
-~/src/3rdparty/libxslt-1.1.17/configure \
-  --disable-static --enable-shared \
-  --with-debug --without-{crypto,python} \
-  --prefix=$HOME/msw/i686-w64-mingw32 \
-  --build=x86_64-unknown-linux-gnu \
-  --host=i686-w64-mingw32 \
-  --with-libxml-prefix=$HOME/msw/i686-w64-mingw32
-# repair this packaging mistake before invoking 'make':
-rm ~/src/3rdparty/libxslt-1.1.17/libxslt/xsltconfig.h
-make $coefficiency --quiet install
-
-cd ~/src/3rdparty/xmlwrapp
-./bootstrap
-mkdir ~/build/xmlwrapp-msw
-cd $_
-~/src/3rdparty/xmlwrapp/configure \
-  --disable-shared --disable-tests --disable-docs \
-  --with-boost=$HOME/msw/i686-w64-mingw32 \
-  --prefix=$HOME/msw/i686-w64-mingw32 \
-  --host=i686-w64-mingw32 \
-  PKG_CONFIG_LIBDIR=$HOME/msw/i686-w64-mingw32/lib/pkgconfig
-make $coefficiency install
-
-mkdir ~/build/wx-msw
-cd $_
-# same options as lmi production, sans --build and --enable-vendor:
-~/src/3rdparty/wxWidgets/configure \
-  --prefix=$HOME/msw/i686-w64-mingw32 \
-  --host=i686-w64-mingw32 \
-  --disable-apple_ieee \
-  --disable-aui \
-  --disable-compat24 \
-  --disable-fswatcher \
-  --disable-gif \
-  --disable-mediactrl \
-  --disable-propgrid \
-  --disable-ribbon \
-  --disable-richtext \
-  --disable-stc \
-  --disable-threads \
-  --disable-webview \
-  --enable-monolithic \
-  --enable-shared \
-  --enable-std_iostreams \
-  --enable-stl \
-  --without-libjpeg \
-  --without-libtiff \
-  --without-opengl \
-  --without-subdirs
-make $coefficiency install
-mkdir ~/build/wxpdfdoc-msw
-cd $_
-~/src/3rdparty/wxpdfdoc/configure \
-    --prefix=$HOME/msw/i686-w64-mingw32 --host=i686-w64-mingw32 \
-    --with-wx-config=$HOME/msw/i686-w64-mingw32/bin/wx-config
-make $coefficiency install
-
-cd ~/src/lmi
-./autogen.sh
-mkdir ~/build/lmi-msw
-cd $_
-PATH=$HOME/msw/i686-w64-mingw32/bin:$PATH ~/src/lmi/configure \
-  --prefix=$HOME/msw/i686-w64-mingw32 --host=i686-w64-mingw32 \
-  CPPFLAGS=-I$HOME/msw/i686-w64-mingw32/include \
-  LDFLAGS=-L$HOME/msw/i686-w64-mingw32/lib \
-  CXXFLAGS='-Wno-unused-local-typedefs -Wno-unused-variable' 2>&1 |less
-make $coefficiency install 2>&1 |less
diff --git a/gwc/xc11 b/gwc/xc11
deleted file mode 100755
index 7d1adc5..0000000
--- a/gwc/xc11
+++ /dev/null
@@ -1,203 +0,0 @@
-# prerequisites
-
-apt-get update
-apt-get install g++-mingw-w64-i686 automake libtool make pkg-config
-apt-get install subversion git
-# optional--personal preferences only:
-apt-get install zsh gnome-system-monitor geany
-# only for VM clipboard support
-apt-get install spice-vdagent
-# ...in VM...apparently not needed
-# update-rc.d spice-vdagent defaults
-
-chsh -s /bin/zsh greg
-
-cat >~/.zshrc <<EOF
-# 
PATH="/opt/lmi/local/bin:/opt/lmi/local/lib:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH"
-
-export coefficiency="--jobs=`nproc`"
-
-# export TZ=UCT
-# export LC_COLLATE=C.UTF-8
-
-# bindkey "\e[3~" delete-char      # Del
-# bindkey '\e[H' beginning-of-line # Home
-# bindkey '\e[F' end-of-line       # End
-bindkey "^[[1;5D" backward-word  # Ctrl-left
-bindkey "^[[1;5C" forward-word   # Ctrl-right
-bindkey '\e[1;3D' backward-word  # Alt-left
-bindkey '\e[1;3C' forward-word   # Alt-right
-
-prompt='%d[%?]%(!.#.$)'
-
-HISTSIZE=1000
-SAVEHIST=1000
-HISTFILE=~/.history
-setopt HIST_IGNORE_DUPS
-
-autoload -U compinit
-compinit -u
-
-# The following lines were added by compinstall
-
-# zstyle ':completion:*' completer _complete _ignored
-# zstyle :compinstall filename '/home/greg/.zshrc'
-
-# autoload -Uz compinit
-# compinit
-# End of lines added by compinstall
-EOF
-
-# fix libtool breakage (needs work)
-
-Adapted from:
-  http://lists.gnu.org/archive/html/libtool-patches/2011-06/msg00001.html
-
---- /usr/share/libtool/config/ltmain.sh.original 2016-01-25 03:43:07.768000000 
+0000
-+++ /usr/share/libtool/config/ltmain.sh 2016-01-25 03:44:17.100000000 +0000
-@@ -4178,7 +4178,8 @@
- /* declarations of non-ANSI functions */
- #if defined(__MINGW32__)
- # ifdef __STRICT_ANSI__
--int _putenv (const char *);
-+     /* int _putenv (const char *); */
-+_CRTIMP int _putenv (const char *);
- # endif
- #elif defined(__CYGWIN__)
- # ifdef __STRICT_ANSI__
-
-# downloads: once only
-
-mkdir --parents ~/src
-cd ~/src
-svn checkout http://svn.sv.nongnu.org/svn/lmi/lmi/trunk lmi 2>&1 |less
-
-mkdir --parents ~/src/3rdparty
-
-cd ~/src/3rdparty
-wget http://downloads.sourceforge.net/boost/boost_1_33_1.tar.bz2
-tar xf boost_1_33_1.tar.bz2
-patch --strip=1 < ~/src/lmi/boost_1_33_1.patch
-
-cd ~/src/3rdparty
-wget ftp://ftp.gnome.org/pub/GNOME/sources/libxml2/2.6/libxml2-2.6.26.tar.bz2
-tar xf libxml2-2.6.26.tar.bz2
-
-cd ~/src/3rdparty
-wget ftp://ftp.gnome.org/pub/GNOME/sources/libxslt/1.1/libxslt-1.1.17.tar.bz2
-tar xf libxslt-1.1.17.tar.bz2
-patch --strip=1 <~/src/lmi/libxslt-1.1.17-lmi.patch
-
-cd ~/src/3rdparty
-git clone https://github.com/vadz/xmlwrapp.git
-cd xmlwrapp
-
-cd ~/src/3rdparty
-git clone https://github.com/wxWidgets/wxWidgets.git
-
-cd ~/src/3rdparty
-git clone https://github.com/vadz/wxpdfdoc.git
-
-# updates: only after initial download
-
-# [svn update; git too; we can flesh this step out later]
-
-# build
-
-mkdir ~/build
-mkdir --parents ~/msw/i686-w64-mingw32/lib
-cd ~/src/3rdparty/boost_1_33_1
-# it would seem nicer not to build in the source directories
-for z in regex filesystem; \
-  do (cd libs/$z/src && \
-  i686-w64-mingw32-g++ -std=c++11 -I../../.. -c *.cpp && \
-  i686-w64-mingw32-ar rc ~/msw/i686-w64-mingw32/lib/libboost_$z.a *.o); done
-mkdir --parents ~/msw/i686-w64-mingw32/include
-cp -a boost ~/msw/i686-w64-mingw32/include/
-
-cd ~/src/3rdparty
-mkdir ~/build/libxml2-msw
-cd $_
-~/src/3rdparty/libxml2-2.6.26/configure \
-  --disable-static --enable-shared \
-  --with-{debug,schemas} --without-{iconv,modules,python,schematron} \
-  --prefix=$HOME/msw/i686-w64-mingw32 \
-  --build=x86_64-unknown-linux-gnu \
-  --host=i686-w64-mingw32 \
-  --without-threads
-make $coefficiency --quiet install
-
-cd ~/src/3rdparty
-mkdir ~/build/libxslt-msw
-cd $_
-~/src/3rdparty/libxslt-1.1.17/configure \
-  --disable-static --enable-shared \
-  --with-debug --without-{crypto,python} \
-  --prefix=$HOME/msw/i686-w64-mingw32 \
-  --build=x86_64-unknown-linux-gnu \
-  --host=i686-w64-mingw32 \
-  --with-libxml-prefix=$HOME/msw/i686-w64-mingw32
-# repair this packaging mistake before invoking 'make':
-rm ~/src/3rdparty/libxslt-1.1.17/libxslt/xsltconfig.h
-make $coefficiency --quiet install
-
-cd ~/src/3rdparty/xmlwrapp
-./bootstrap
-mkdir ~/build/xmlwrapp-msw
-cd $_
-~/src/3rdparty/xmlwrapp/configure \
-  --disable-shared --disable-tests --disable-docs \
-  --with-boost=$HOME/msw/i686-w64-mingw32 \
-  --prefix=$HOME/msw/i686-w64-mingw32 \
-  --host=i686-w64-mingw32 \
-  PKG_CONFIG_LIBDIR=$HOME/msw/i686-w64-mingw32/lib/pkgconfig \
-  CXXFLAGS='-std=c++11'
-make $coefficiency install
-
-mkdir ~/build/wx-msw
-cd $_
-# same options as lmi production, sans --build and --enable-vendor:
-~/src/3rdparty/wxWidgets/configure \
-  --prefix=$HOME/msw/i686-w64-mingw32 \
-  --host=i686-w64-mingw32 \
-  --disable-apple_ieee \
-  --disable-aui \
-  --disable-compat24 \
-  --disable-fswatcher \
-  --disable-gif \
-  --disable-mediactrl \
-  --disable-propgrid \
-  --disable-ribbon \
-  --disable-richtext \
-  --disable-stc \
-  --disable-threads \
-  --disable-webview \
-  --enable-monolithic \
-  --enable-shared \
-  --enable-std_iostreams \
-  --enable-stl \
-  --without-libjpeg \
-  --without-libtiff \
-  --without-opengl \
-  --without-subdirs \
-  CXXFLAGS='-std=c++11'
-make $coefficiency install
-
-mkdir ~/build/wxpdfdoc-msw
-cd $_
-~/src/3rdparty/wxpdfdoc/configure \
-  --prefix=$HOME/msw/i686-w64-mingw32 --host=i686-w64-mingw32 \
-  --with-wx-config=$HOME/msw/i686-w64-mingw32/bin/wx-config \
-  CXXFLAGS='-std=c++11'
-make $coefficiency install
-
-cd ~/src/lmi
-./autogen.sh
-mkdir ~/build/lmi-msw
-cd $_
-PATH=$HOME/msw/i686-w64-mingw32/bin:$PATH ~/src/lmi/configure \
-  --prefix=$HOME/msw/i686-w64-mingw32 --host=i686-w64-mingw32 \
-  CPPFLAGS=-I$HOME/msw/i686-w64-mingw32/include \
-  LDFLAGS=-L$HOME/msw/i686-w64-mingw32/lib \
-  CXXFLAGS='-Wno-unused-local-typedefs -Wno-unused-variable -std=c++11'
-make $coefficiency install
diff --git a/install_cygwin.bat b/install_cygwin.bat
index 64a2e7f..9ed0b10 100644
--- a/install_cygwin.bat
+++ b/install_cygwin.bat
@@ -32,7 +32,7 @@ START "Installing Cygwin" /WAIT setup-x86_64 ^
   --wait --quiet-mode ^
   --site http://mirrors.kernel.org/sourceware/cygwin/ ^
   --root C:/cygwin64_lmi --packages ^
-   
"autoconf,automake,bsdtar,dos2unix,doxygen,gdb,git,libtool,make,openssh,patch,pkg-config,rsync,unzip,wget,zip,zsh"
+   
"autoconf,automake,bc,bsdtar,dos2unix,doxygen,gdb,git,libtool,make,openssh,patch,pkg-config,rsync,unzip,vim,wget,zip,zsh"
 cd C:\cygwin64_lmi\etc
 echo # >> fstab
 echo C:/opt/lmi             /opt/lmi       lmi_specific binary,user 0 0 >> 
fstab
diff --git a/install_libxml2_libxslt.make b/install_libxml2_libxslt.make
index e5574bd..714d93a 100644
--- a/install_libxml2_libxslt.make
+++ b/install_libxml2_libxslt.make
@@ -23,16 +23,14 @@
 
 # Archives and their md5sums
 
-xz_version      := xz-5.2.3
 libxml2_version := libxml2-2.9.4
 libxslt_version := libxslt-1.1.29
 
-xz-5.2.3.tar.gz-md5       := ef68674fb47a8b8e741b34e429d86e9d
 libxml2-2.9.4.tar.gz-md5  := ae249165c173b1ff386ee8ad676815f5
 libxslt-1.1.29.tar.gz-md5 := a129d3c44c022de3b9dcf6d6f288d72e
 
 # Libraries are ordered by dependency, rather than alphabetically.
-libraries := $(xz_version) $(libxml2_version) $(libxslt_version)
+libraries := $(libxml2_version) $(libxslt_version)
 
 source_archives := $(addsuffix .tar.gz, $(libraries))
 
@@ -43,25 +41,17 @@ source_archives := $(addsuffix .tar.gz, $(libraries))
 host          := ftp://xmlsoft.org
 host_path     := libxml2
 
-$(xz_version).tar.gz: host      := https://sourceforge.net
-$(xz_version).tar.gz: host_path := projects/lzmautils/files
-
-mingw_dir     := /opt/lmi/mingw
+mingw_dir     := /opt/lmi/${LMI_COMPILER}_${LMI_TRIPLET}/gcc_msw
 
 LMI_COMPILER  ?= gcc
 LMI_TRIPLET   ?= i686-w64-mingw32
 
-# It would be cleaner to use the "LMI_*" components in $exec_prefix
-# (arch-dependent libraries) rather than in $prefix (arch-independent
-# headers, e.g.). However, libxml2's '--with-lzma' option assumes that
-# $prefix and $exec_prefix are the same directory--see:
-#   https://lists.nongnu.org/archive/html/lmi/2019-04/msg00018.html
-prefix        := /opt/lmi/$(LMI_COMPILER)_$(LMI_TRIPLET)/local
-exec_prefix   := $(prefix)
+prefix        := /opt/lmi/local
+exec_prefix   := $(prefix)/$(LMI_COMPILER)_$(LMI_TRIPLET)
 
 cache_dir     := /cache_for_lmi/downloads
 
-build_dir     := $(prefix)/../xml-ad_hoc
+build_dir     := $(exec_prefix)/xml-ad_hoc
 
 # Variables that normally should be left alone 
#################################
 
@@ -73,20 +63,6 @@ ifeq (cygwin,$(findstring cygwin,$(lmi_build_type)))
   mingw_bin_dir := $(mingw_dir)/bin/
 endif
 
-xz_cflags := \
-  -Wno-format \
-  -Wno-format-extra-args \
-  -Wno-implicit-fallthrough \
-  -Wno-maybe-uninitialized \
-
-$(xz_version)_options := \
-  --prefix=$(prefix) \
-  --exec-prefix=$(exec_prefix) \
-  --build=`$(build_dir)/$(xz_version)/build-aux/config.guess` \
-  --host=$(LMI_TRIPLET) \
-  --disable-dependency-tracking \
-  CFLAGS="-g -O2 $(xz_cflags)" \
-
 # For 'host' and 'build' configure options, see:
 #   http://cygwin.com/ml/cygwin/2002-01/msg00837.html
 
@@ -135,7 +111,7 @@ $(libxml2_version)_options := \
   --build=`$(build_dir)/$(libxml2_version)/config.guess` \
   --host=$(LMI_TRIPLET) \
   $(xmlsoft_common_options) \
-  --with-lzma=$(prefix) \
+  --without-lzma \
   --with-schemas \
   --without-iconv \
   --without-modules \
@@ -175,7 +151,6 @@ all: clobber_exec_prefix_only $(source_archives) 
$(libraries)
 
 # Order-only prerequisites.
 
-$(libxml2_version):| $(xz_version)
 $(libxslt_version):| $(libxml2_version)
 $(libraries)      :| $(source_archives)
 $(source_archives):| initial_setup
@@ -220,7 +195,7 @@ $(libraries):
        -[ -e address@hidden ] && $(PATCH) --directory=$(build_dir) --strip=1 
<address@hidden
        cd $(build_dir)/$@ \
          && export PATH="$(mingw_bin_dir):${PATH}" \
-         && PKG_CONFIG_PATH="$(prefix)/lib/pkgconfig" \
+         && PKG_CONFIG_PATH="$(exec_prefix)/lib/pkgconfig" \
            $(address@hidden) ./configure $(address@hidden) \
          && $(MAKE) \
          && $(MAKE) install \
@@ -234,20 +209,13 @@ $(libraries):
 
 .PHONY: clobber_exec_prefix_only
 clobber_exec_prefix_only:
-       -$(RM) --force --recursive $(exec_prefix)/bin/liblzma*
-       -$(RM) --force --recursive $(exec_prefix)/bin/lz*
-       -$(RM) --force --recursive $(exec_prefix)/bin/xz*
-       -$(RM) --force --recursive $(exec_prefix)/bin/unlz*
-       -$(RM) --force --recursive $(exec_prefix)/bin/unxz*
        -$(RM) --force --recursive $(exec_prefix)/bin/*xml2*
        -$(RM) --force --recursive $(exec_prefix)/bin/*xslt*
        -$(RM) --force --recursive $(exec_prefix)/bin/xmllint*
        -$(RM) --force --recursive $(exec_prefix)/bin/xmlcatalog*
-       -$(RM) --force --recursive $(exec_prefix)/include/lzma*
        -$(RM) --force --recursive $(exec_prefix)/include/libxml2
        -$(RM) --force --recursive $(exec_prefix)/include/libxslt
        -$(RM) --force --recursive $(exec_prefix)/include/libexslt
-       -$(RM) --force --recursive $(exec_prefix)/lib/liblzma*
        -$(RM) --force --recursive $(exec_prefix)/lib/*xml2*
        -$(RM) --force --recursive $(exec_prefix)/lib/*xslt*
        -$(RM) --force --recursive $(exec_prefix)/lib/cmake
diff --git a/install_mingw.make b/install_mingw.make
index 21de260..0881dea 100644
--- a/install_mingw.make
+++ b/install_mingw.make
@@ -1,4 +1,4 @@
-# Installer for MinGW-w64 native toolchain.
+# Installer for MinGW-w64 64-bit msw-native toolchain.
 #
 # Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 
2016, 2017, 2018, 2019 Gregory W. Chicares.
 #
@@ -28,7 +28,7 @@ this_makefile := $(abspath $(lastword $(MAKEFILE_LIST)))
 # rather than release its own; lmi uses i686 builds with native
 # threads and SJLJ exceptions.
 
-version   := MinGW-7_3_0
+version   := MinGW-8_1_0
 
 file_list   = $($(version))
 
@@ -37,12 +37,13 @@ file_list   = $($(version))
 #   http://gcc.gnu.org/ml/gcc-patches/2004-06/msg00703.html
 # when multiple versions of MinGW gcc are installed, as discussed on
 # the mingw-users mailing list in these messages:
-#   http://article.gmane.org/gmane.comp.gnu.mingw.user/14747
+#   https://sourceforge.net/p/mingw/mailman/message/15864073/
 #     [2005-01-17T16:30:44Z from Greg Chicares]
-#   http://article.gmane.org/gmane.comp.gnu.mingw.user/14748
+#   https://sourceforge.net/p/mingw/mailman/message/15864075/
 #     [2005-01-17T18:15:26Z from Aaron W. LaFramboise]
 
-prefix     := /opt/lmi/mingw
+mingw_dir  := /opt/lmi/${LMI_COMPILER}_${LMI_TRIPLET}/gcc_msw
+prefix     := $(mingw_dir)
 
 cache_dir  := /cache_for_lmi/downloads
 
@@ -56,17 +57,11 @@ mirror     := http://downloads.sourceforge.net/mingw-w64
 
 # File lists 
###################################################################
 
-#MinGW-6_3_0 := i686-6.3.0-release-win32-sjlj-rt_v5-rev1.7z
-MinGW-6_3_0 := i686-6.3.0-release-win32-sjlj-rt_v5-rev2.7z
-MinGW-7_2_0 := i686-7.2.0-release-win32-sjlj-rt_v5-rev0.7z
-MinGW-7_3_0 := i686-7.3.0-release-win32-sjlj-rt_v5-rev0.7z
+MinGW-8_1_0 := x86_64-8.1.0-release-win32-seh-rt_v6-rev0.7z
 
 # Archive md5sums 
##############################################################
 
-#$(MinGW-6_3_0)-md5 := b92e8480cf8d5904da78ab6d94f1a047
-$(MinGW-6_3_0)-md5 := 6e15de993400279c24b40b1f978e9380
-$(MinGW-7_2_0)-md5 := f34ff6eca4aa7a645f60c977b107c5d2
-$(MinGW-7_3_0)-md5 := 37d964d08ce48dc170cc95a84679cc4f
+$(MinGW-8_1_0)-md5 := ebe9cf22aa13c9e34f5e684a79efaf8e
 
 # Utilities 
####################################################################
 
@@ -105,7 +100,7 @@ ad_hoc_dir_exists = \
 
 .PHONY: all
 all: $(file_list)
-       $(CP) --archive $(ad_hoc_dir)/mingw32 $(prefix)
+       $(CP) --archive $(ad_hoc_dir)/mingw64/* $(prefix)
        $(RM) --force --recursive $(ad_hoc_dir)
 
 $(file_list): initial_setup
@@ -122,12 +117,8 @@ BSDTARFLAGS := --keep-old-files
 
 WGETFLAGS := --no-verbose
 
-# Fall back on a native binary if libarchive issue 629 occurs.
-
 .PHONY: %.7z
 %.7z:
        cd $(cache_dir) && [ -e $@ ] || $(WGET) $(WGETFLAGS) $(mirror)/$@
        cd $(cache_dir) && $(ECHO) "$(address@hidden) *$@" | $(MD5SUM) --check
-       $(BSDTAR) --extract $(BSDTARFLAGS) --directory=$(ad_hoc_dir) 
--file=$(cache_dir)/$@ \
-         || c:/Program\ Files/7-Zip/7z x `cygpath -w 
$(cache_dir)/address@hidden -o$(ad_hoc_dir) \
-         || c:/Program\ Files\ \(x86\)/7-Zip/7z x `cygpath -w 
$(cache_dir)/address@hidden -o`cygpath -w $(ad_hoc_dir)`
+       $(BSDTAR) --extract $(BSDTARFLAGS) --directory=$(ad_hoc_dir) 
--file=$(cache_dir)/$@
diff --git a/install_mingw.make b/install_mingw32.make
similarity index 89%
copy from install_mingw.make
copy to install_mingw32.make
index 21de260..22f103e 100644
--- a/install_mingw.make
+++ b/install_mingw32.make
@@ -1,4 +1,4 @@
-# Installer for MinGW-w64 native toolchain.
+# Legacy installer for MinGW-w64 32-bit msw-native toolchain.
 #
 # Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 
2016, 2017, 2018, 2019 Gregory W. Chicares.
 #
@@ -28,7 +28,7 @@ this_makefile := $(abspath $(lastword $(MAKEFILE_LIST)))
 # rather than release its own; lmi uses i686 builds with native
 # threads and SJLJ exceptions.
 
-version   := MinGW-7_3_0
+version   := MinGW-8_1_0
 
 file_list   = $($(version))
 
@@ -37,12 +37,13 @@ file_list   = $($(version))
 #   http://gcc.gnu.org/ml/gcc-patches/2004-06/msg00703.html
 # when multiple versions of MinGW gcc are installed, as discussed on
 # the mingw-users mailing list in these messages:
-#   http://article.gmane.org/gmane.comp.gnu.mingw.user/14747
+#   https://sourceforge.net/p/mingw/mailman/message/15864073/
 #     [2005-01-17T16:30:44Z from Greg Chicares]
-#   http://article.gmane.org/gmane.comp.gnu.mingw.user/14748
+#   https://sourceforge.net/p/mingw/mailman/message/15864075/
 #     [2005-01-17T18:15:26Z from Aaron W. LaFramboise]
 
-prefix     := /opt/lmi/mingw
+mingw_dir  := /opt/lmi/${LMI_COMPILER}_${LMI_TRIPLET}/gcc_msw
+prefix     := $(mingw_dir)
 
 cache_dir  := /cache_for_lmi/downloads
 
@@ -60,6 +61,7 @@ mirror     := http://downloads.sourceforge.net/mingw-w64
 MinGW-6_3_0 := i686-6.3.0-release-win32-sjlj-rt_v5-rev2.7z
 MinGW-7_2_0 := i686-7.2.0-release-win32-sjlj-rt_v5-rev0.7z
 MinGW-7_3_0 := i686-7.3.0-release-win32-sjlj-rt_v5-rev0.7z
+MinGW-8_1_0 := i686-8.1.0-release-win32-sjlj-rt_v6-rev0.7z
 
 # Archive md5sums 
##############################################################
 
@@ -67,6 +69,7 @@ MinGW-7_3_0 := i686-7.3.0-release-win32-sjlj-rt_v5-rev0.7z
 $(MinGW-6_3_0)-md5 := 6e15de993400279c24b40b1f978e9380
 $(MinGW-7_2_0)-md5 := f34ff6eca4aa7a645f60c977b107c5d2
 $(MinGW-7_3_0)-md5 := 37d964d08ce48dc170cc95a84679cc4f
+$(MinGW-8_1_0)-md5 := 28ec1e65ab85a9e1043998516045ab62
 
 # Utilities 
####################################################################
 
@@ -105,7 +108,7 @@ ad_hoc_dir_exists = \
 
 .PHONY: all
 all: $(file_list)
-       $(CP) --archive $(ad_hoc_dir)/mingw32 $(prefix)
+       $(CP) --archive $(ad_hoc_dir)/mingw32/* $(prefix)
        $(RM) --force --recursive $(ad_hoc_dir)
 
 $(file_list): initial_setup
@@ -122,12 +125,8 @@ BSDTARFLAGS := --keep-old-files
 
 WGETFLAGS := --no-verbose
 
-# Fall back on a native binary if libarchive issue 629 occurs.
-
 .PHONY: %.7z
 %.7z:
        cd $(cache_dir) && [ -e $@ ] || $(WGET) $(WGETFLAGS) $(mirror)/$@
        cd $(cache_dir) && $(ECHO) "$(address@hidden) *$@" | $(MD5SUM) --check
-       $(BSDTAR) --extract $(BSDTARFLAGS) --directory=$(ad_hoc_dir) 
--file=$(cache_dir)/$@ \
-         || c:/Program\ Files/7-Zip/7z x `cygpath -w 
$(cache_dir)/address@hidden -o$(ad_hoc_dir) \
-         || c:/Program\ Files\ \(x86\)/7-Zip/7z x `cygpath -w 
$(cache_dir)/address@hidden -o`cygpath -w $(ad_hoc_dir)`
+       $(BSDTAR) --extract $(BSDTARFLAGS) --directory=$(ad_hoc_dir) 
--file=$(cache_dir)/$@
diff --git a/install_miscellanea.make b/install_miscellanea.make
index b6f6ee9..c7f8d51 100644
--- a/install_miscellanea.make
+++ b/install_miscellanea.make
@@ -71,7 +71,7 @@ sample:               stem = data
 $(boost_archive)-url    := $(sf_mirror)/boost/$(boost_archive)
 $(cgicc_archive)-url    := ftp://ftp.gnu.org/pub/gnu/cgicc/$(cgicc_archive)
 $(jing_archive)-url     := 
https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/jing-trang/$(jing_archive)
-$(md5sum_msw_exe)-url   := 
http://etree.org/cgi-bin/counter.cgi/software/md5sum.exe#!md5!eb574b236133e60c989c6f472f07827b
+$(md5sum_msw_exe)-url   := 
https://github.com/vadz/lmi/releases/download/new-cygwin-makefiles/md5sum.exe
 $(sample_archive)-url   := 
https://download.savannah.gnu.org/releases/lmi/$(sample_archive)
 $(trang_archive)-url    := 
https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/jing-trang/$(trang_archive)
 $(xmlwrapp_archive)-url := 
https://github.com/vslavik/xmlwrapp/releases/download/v0.9.0/$(xmlwrapp_archive)
diff --git a/install_msw.sh b/install_msw.sh
index 1575870..275da78 100755
--- a/install_msw.sh
+++ b/install_msw.sh
@@ -34,9 +34,19 @@ set -vx
 stamp0=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
 echo "Started: $stamp0"
 
+lmi_build_type=$(/usr/share/libtool/build-aux/config.guess)
+
 # This should work with a rather minimal path.
 
 minimal_path=${MINIMAL_PATH:-"/usr/bin:/bin:/usr/sbin:/sbin"}
+
+case "$lmi_build_type" in
+    (*-*-cygwin*)
+        java_path='/cygdrive/c/Program\ Files\ \(x86\)/Common\ 
Files/Oracle/Java/javapath'
+        minimal_path="$minimal_path:$(cygpath --sysdir):$java_path"
+        ;;
+esac
+
 export PATH="$minimal_path"
 
 # '--jobs=4': big benefit for multicore, no penalty for single core
@@ -48,8 +58,6 @@ then
     export coefficiency='--jobs=4'
 fi
 
-lmi_build_type=$(/usr/share/libtool/build-aux/config.guess)
-
 case "$lmi_build_type" in
     (*-*-cygwin*)
         platform=Cygwin
@@ -161,12 +169,6 @@ then
     # It seems quite unlikely that anyone who's building lmi would have
     # any other need for mounts with the names used here.
 
-    restore_MinGW_mount=$(mount --mount-entries | grep '/MinGW_ ')
-    [ -z "$restore_MinGW_mount" ] \
-      || printf '%s\n' "$restore_MinGW_mount" | grep --silent 
'C:/opt/lmi/MinGW-7_3_0' \
-      || printf 'Replacing former MinGW_ mount:\n %s\n' "$restore_MinGW_mount" 
>/dev/tty
-    mount --force "C:/opt/lmi/MinGW-7_3_0" "/MinGW_"
-
     restore_cache_mount=$(mount --mount-entries | grep '/cache_for_lmi ')
     [ -z "$restore_cache_mount" ] \
       || printf '%s\n' "$restore_cache_mount" | grep --silent 
'C:/cache_for_lmi' \
@@ -185,13 +187,6 @@ mount
 md5sum "$0"
 find /cache_for_lmi/downloads -type f | xargs md5sum
 
-if [ "Cygwin" = "$platform" ]
-then
-    # For Cygwin, install and use this msw-native compiler.
-    rm --force --recursive /MinGW_
-    make $coefficiency --output-sync=recurse -f install_mingw.make
-fi
-
 make $coefficiency --output-sync=recurse -f install_miscellanea.make clobber
 make $coefficiency --output-sync=recurse -f install_miscellanea.make
 
@@ -200,9 +195,27 @@ make $coefficiency --output-sync=recurse -f 
install_miscellanea.make
 # it's the one installed to /opt/lmi/bin/ when this script ends.
 export LMI_COMPILER=gcc
 export LMI_TRIPLET
-for LMI_TRIPLET in x86_64-w64-mingw32 i686-w64-mingw32 ;
+# shellcheck disable=SC2043
 #for LMI_TRIPLET in i686-w64-mingw32 ;
+for LMI_TRIPLET in x86_64-w64-mingw32 i686-w64-mingw32 ;
 do
+    # Set a minimal path for makefiles and scripts that are
+    # designed to be independent of lmi's runtime path.
+    export PATH="$minimal_path"
+
+    # For Cygwin, install and use this msw-native compiler.
+    # Install it for other build types, too, even if only for
+    # validating the installation procedure.
+    mingw_dir=/opt/lmi/${LMI_COMPILER}_${LMI_TRIPLET}/gcc_msw
+    [ -d "$mingw_dir" ] && rm --force --recursive "$mingw_dir"
+    if   [ "i686-w64-mingw32"   = "$LMI_TRIPLET" ]; then
+      make $coefficiency --output-sync=recurse -f install_mingw32.make
+    elif [ "x86_64-w64-mingw32" = "$LMI_TRIPLET" ]; then
+      make $coefficiency --output-sync=recurse -f install_mingw.make
+    else
+      printf 'No MinGW compiler for this triplet.\n'
+    fi
+
     make $coefficiency --output-sync=recurse -f install_libxml2_libxslt.make
 
     ./install_wx.sh
@@ -210,9 +223,8 @@ do
 
     find /cache_for_lmi/downloads -type f | xargs md5sum
 
+    # Source this script only for commands that depend upon it.
     . ./set_toolchain.sh
-# Alternative:
-#   export 
PATH=/opt/lmi/"${LMI_COMPILER}_${LMI_TRIPLET}"/local/bin:/opt/lmi/"${LMI_COMPILER}_${LMI_TRIPLET}"/local/lib:$minimal_path
 
     make $coefficiency --output-sync=recurse wx_config_check
     make $coefficiency --output-sync=recurse show_flags
@@ -229,7 +241,9 @@ do
     fi
 done
 
-# To regenerate authentication files:
+mkdir --parents /opt/lmi/data
+
+# To regenerate authentication files for production distributions:
 # cd /opt/lmi/data
 # printf '2450449 2472011'             >expiry
 # printf '%s\n' "$(md5sum expiry)"     >validated.md5
@@ -238,9 +252,17 @@ printf '2450449 2472011'                            
>/opt/lmi/data/expiry
 printf '5fc68a795c9c60da1b32be989efc299a  expiry\n' 
>/opt/lmi/data/validated.md5
 printf '391daa5cbc54e118c4737446bcb84eea'           >/opt/lmi/data/passkey
 
-# Surrogates for proprietary graphics:
-for z in company_logo.png group_quote_banner.png ;
-  do cp --archive /opt/lmi/src/lmi/gwc/$z /opt/lmi/data/ ;
+# Copy proprietary graphics if available; else use generic surrogates.
+graphics_dir_0=/opt/lmi/proprietary/graphics
+graphics_dir_1=/opt/lmi/src/lmi/gwc
+for z in company_logo.png group_quote_banner.png ; do
+  if   [ -f "$graphics_dir_0"/$z ]
+    then cp --archive "$graphics_dir_0"/$z /opt/lmi/data/
+  elif [ -f "$graphics_dir_1"/$z ]
+    then cp --archive "$graphics_dir_1"/$z /opt/lmi/data/
+  else
+    printf 'Graphics files not found.\n'
+  fi
 done
 
 # Configurable settings.
@@ -300,7 +322,7 @@ fi
 stamp1=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
 echo "Finished: $stamp1"
 
-seconds=$(expr $(date '+%s' -d "$stamp1") - $(date '+%s' -d "$stamp0"))
+seconds=$(($(date '+%s' -d "$stamp1") - $(date '+%s' -d "$stamp0")))
 elapsed=$(date -u -d @"$seconds" +'%H:%M:%S')
 echo "Elapsed: $elapsed"
 
diff --git a/install_wx.sh b/install_wx.sh
index 294da80..825abea 100755
--- a/install_wx.sh
+++ b/install_wx.sh
@@ -46,10 +46,10 @@ LMI_TRIPLET=${LMI_TRIPLET:-"i686-w64-mingw32"}
 
 # Variables that normally should be left alone 
#################################
 
-mingw_dir=/opt/lmi/mingw
+mingw_dir=/opt/lmi/${LMI_COMPILER}_${LMI_TRIPLET}/gcc_msw
 
-prefix=/opt/lmi/"${LMI_COMPILER}_${LMI_TRIPLET}"/local
-exec_prefix="$prefix"
+prefix=/opt/lmi/local
+exec_prefix="$prefix/${LMI_COMPILER}_${LMI_TRIPLET}"
 
 repo_name="wxWidgets"
 
@@ -89,7 +89,7 @@ case "$build_type" in
 esac
 
 # Distinguish wx dll by host type, compiler version, and wx SHA1.
-gcc_version=$(${mingw_bin_dir}${LMI_TRIPLET}-gcc -dumpversion|tr -d '\r')
+gcc_version=$("${mingw_bin_dir}${LMI_TRIPLET}-$LMI_COMPILER" -dumpversion|tr 
-d '\r')
 vendor=${LMI_TRIPLET}-$gcc_version-$wx_commit_sha
 
 # Configuration reference:
@@ -135,22 +135,24 @@ config_options="
 
 [ -n "$mingw_bin_dir" ] && export PATH="$mingw_bin_dir:${PATH}"
 
-build_dir="$prefix"/../wx-ad_hoc/lmi-gcc-$gcc_version
+build_dir="$exec_prefix/wx-ad_hoc/lmi-$LMI_COMPILER-$gcc_version"
 
 if [ "$wx_skip_clean" != 1 ]
 then
     rm --force --recursive "$build_dir"
     # This incidentally removes wxPdfDoc, but it's a good idea to rebuild that
     # whenever wx is upgraded anyway.
-    rm --force --recursive $exec_prefix/bin/wx*
-    rm --force --recursive $exec_prefix/include/wx*
-    rm --force --recursive $exec_prefix/lib/wx*
-    rm --force --recursive $exec_prefix/lib/libwx*
+    rm --force --recursive "$exec_prefix/bin/wx*"
+    rm --force --recursive "$exec_prefix/include/wx*"
+    rm --force --recursive "$exec_prefix/lib/wx*"
+    rm --force --recursive "$exec_prefix/lib/libwx*"
 fi
 
 mkdir --parents "$build_dir"
 
 cd "$build_dir"
+# 'configure' options must not be double-quoted
+# shellcheck disable=SC2086
 "$proxy_wx_dir"/configure $config_options
 $MAKE
 $MAKE install
diff --git a/install_wxpdfdoc.sh b/install_wxpdfdoc.sh
index b58ec1c..ee879fa 100755
--- a/install_wxpdfdoc.sh
+++ b/install_wxpdfdoc.sh
@@ -46,10 +46,10 @@ LMI_TRIPLET=${LMI_TRIPLET:-"i686-w64-mingw32"}
 
 # Variables that normally should be left alone 
#################################
 
-mingw_dir=/opt/lmi/mingw
+mingw_dir=/opt/lmi/${LMI_COMPILER}_${LMI_TRIPLET}/gcc_msw
 
-prefix=/opt/lmi/"${LMI_COMPILER}_${LMI_TRIPLET}"/local
-exec_prefix="$prefix"
+prefix=/opt/lmi/local
+exec_prefix="$prefix/${LMI_COMPILER}_${LMI_TRIPLET}"
 
 repo_name="wxpdfdoc"
 
@@ -105,18 +105,20 @@ config_options="
 cd "$proxy_wxpdfdoc_dir"
 autoreconf --verbose
 
-build_dir="$prefix"/../wxpdfdoc-ad_hoc/wxpdfdoc-$wxpdfdoc_commit_sha
+build_dir="$exec_prefix/wxpdfdoc-ad_hoc/wxpdfdoc-$wxpdfdoc_commit_sha"
 
 if [ "$wxpdfdoc_skip_clean" != 1 ]
 then
     rm --force --recursive "$build_dir"
-    rm --force --recursive $exec_prefix/lib/*wxcode*pdfdoc*
-    rm --force --recursive $exec_prefix/src/pdf*.inc
+    rm --force --recursive "$exec_prefix/lib/*wxcode*pdfdoc*"
+    rm --force --recursive "$exec_prefix/src/pdf*.inc"
 fi
 
 mkdir --parents "$build_dir"
 
 cd "$build_dir"
+# 'configure' options must not be double-quoted
+# shellcheck disable=SC2086
 "$proxy_wxpdfdoc_dir"/configure $config_options
 $MAKE
 $MAKE install
diff --git a/irc7702_tables.cpp b/irc7702_tables.cpp
new file mode 100644
index 0000000..40ddf3e
--- /dev/null
+++ b/irc7702_tables.cpp
@@ -0,0 +1,99 @@
+// 7PP and CVAT corridor from first principles.
+//
+// Copyright (C) 2019 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+#include "pchfile.hpp"
+
+#include "irc7702_tables.hpp"
+
+#include "commutation_functions.hpp"
+#include "cso_table.hpp"
+#include "et_vector.hpp"
+#include "math_functions.hpp"
+#include "ssize_lmi.hpp"
+
+#include <cmath>                        // log()
+
+irc7702_tables::irc7702_tables
+    (oenum_cso_era              cso_era
+    ,oenum_autopisty            autopisty
+    ,oenum_alb_or_anb           alb_or_anb
+    ,mcenum_gender              gender
+    ,mcenum_smoking             smoking
+    ,std::vector<double> const& naar_discount
+    ,double                     max_coi_rate
+    ,int                        min_age
+    ,int                        max_age
+    )
+    :q_       {cso_table(cso_era, autopisty, alb_or_anb, gender, smoking, 
min_age, max_age)}
+    ,length_  {lmi::ssize(q_)}
+    // Initialize to proper length to support PETE usage below:
+    ,ul_corr_ (length_)
+    ,ul_7pp_  (length_)
+    ,ol_corr_ (length_)
+    ,ol_7pp_  (length_)
+{
+    std::vector<double> q12(length_);
+    assign(q12, apply_binary(coi_rate_from_q<double>(), q_, max_coi_rate));
+
+    // ic: 0.04 is the statutory rate.
+    // ig: Argument 'naar_discount' corresponds to DB_NaarDiscount,
+    //   which is assumed to be rounded appropriately if at all.
+    std::vector<double> const ic
+        (length_
+        ,i_upper_12_over_12_from_i<double>()(0.04)
+        );
+    std::vector<double> const& ig(naar_discount);
+
+    ULCommFns const ulcf(q12, ic, ig, mce_option1_for_7702, mce_monthly);
+
+    ul_corr_ += ulcf.aD() / (ulcf.aDomega() + ulcf.kM());
+
+    // 'E' is the shift operator, so E(7) f(x) = f(x+7).
+    std::vector<double> E7aN(ulcf.aN());
+    E7aN.insert(E7aN.end(), 7, 0.0);
+    E7aN.erase(E7aN.begin(), 7 + E7aN.begin());
+    ul_7pp_ += (ulcf.aDomega() + ulcf.kM()) / (ulcf.aN() - E7aN);
+
+    double const i_over_delta = 0.04 / std::log(1.04);
+    std::vector<double> const i(length_, 0.04);
+    OLCommFns const olcf(q_, i);
+
+    // Alternative calculations that may be useful someday are given
+    // in comments.
+
+    // reciprocal of (Mx - Momega-1) / Dx
+    ol_corr_ +=
+          olcf.D()
+//      / ((olcf.M() - olcf.M().back()) * i_over_delta + olcf.Domega())
+        / ((olcf.M()                  ) * i_over_delta + olcf.Domega())
+        ;
+
+    // (Mx - Momega-1 + Domega-1) / (Nx - Nx+7)
+    std::vector<double> E7N(olcf.N());
+    E7N.insert(E7N.end(), 7, 0.0);
+    E7N.erase(E7N.begin(), 7 + E7N.begin());
+    ol_7pp_ +=
+//        ((olcf.M() - olcf.M().back()) * i_over_delta + olcf.Domega())
+//        ((olcf.M() - olcf.M().back())                + olcf.Domega())
+          ((olcf.M()                  ) * i_over_delta + olcf.Domega())
+        / (olcf.N() - E7N)
+        ;
+}
diff --git a/irc7702_tables.hpp b/irc7702_tables.hpp
new file mode 100644
index 0000000..661593a
--- /dev/null
+++ b/irc7702_tables.hpp
@@ -0,0 +1,64 @@
+// 7PP and CVAT corridor from first principles.
+//
+// Copyright (C) 2019 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+#ifndef irc7702_tables_hpp
+#define irc7702_tables_hpp
+
+#include "config.hpp"
+
+#include "mc_enum_types.hpp"
+#include "oecumenic_enumerations.hpp"
+#include "so_attributes.hpp"
+
+#include <vector>
+
+class LMI_SO irc7702_tables final
+{
+    friend void Test_Corridor_and_7PP();
+
+  public:
+    irc7702_tables
+        (oenum_cso_era
+        ,oenum_autopisty
+        ,oenum_alb_or_anb
+        ,mcenum_gender
+        ,mcenum_smoking
+        ,std::vector<double> const& naar_discount
+        ,double                     max_coi_rate
+        // Potentially defaultable.
+        ,int                        min_age
+        ,int                        max_age
+        );
+    std::vector<double> const& ul_corr() {return ul_corr_;}
+    std::vector<double> const& ul_7pp () {return ul_7pp_ ;}
+    std::vector<double> const& ol_corr() {return ol_corr_;}
+    std::vector<double> const& ol_7pp () {return ol_7pp_ ;}
+
+  private:
+    std::vector<double> const q_       {};
+    int                 const length_  {};
+    std::vector<double>       ul_corr_ {};
+    std::vector<double>       ul_7pp_  {};
+    std::vector<double>       ol_corr_ {};
+    std::vector<double>       ol_7pp_  {};
+};
+
+#endif // irc7702_tables_hpp
diff --git a/local_options.sh b/local_options.sh
index a0d7ec1..a5a2395 100755
--- a/local_options.sh
+++ b/local_options.sh
@@ -52,10 +52,12 @@
 #     [2005-01-17T18:15:26Z from Aaron W. LaFramboise]
 # when multiple versions of MinGW gcc are installed.
 
-echo "# Copyright (C) $(date -u +'%Y') [you]."    > local_options.make
-echo "# http://savannah.nongnu.org/projects/lmi"; >> local_options.make
-echo ""                                          >> local_options.make
-echo "# Local options"                           >> local_options.make
+{
+  echo "# Copyright (C) $(date -u +'%Y') [you]."
+  echo "# http://savannah.nongnu.org/projects/lmi";
+  echo ""
+  echo "# Local options"
+} > local_options.make
 for z in "$@"
   do
     echo "$z" \
diff --git a/mst_to_xst.sh b/mst_to_xst.sh
index aa1344c..03e1b6a 100755
--- a/mst_to_xst.sh
+++ b/mst_to_xst.sh
@@ -1,4 +1,4 @@
-#!/bin/zsh
+#!/bin/sh
 
 # Copy MST files, obfuscating them for distribution.
 
@@ -30,15 +30,26 @@
 # Stripping the copyright header before obfuscation is a possible
 # future enhancement that might improve runtime performance.
 
-# This script requires zsh because brace expansion is more convenient
-# than 'seq'. It is intended to be called from a makefile that sets
+# This script is intended to be called from a makefile that sets
 # both $datadir and $srcdir.
 
+seqq()
+{
+    first=$1 incr=$2 last=$3
+    echo "for (i = $first; i != $last+$incr; i+=$incr) i" | bc -l
+}
+
+# These variables are indeed not assigned here.
+# shellcheck disable=SC2154
 [ -d "$datadir" ] || { printf 'fail: invalid datadir\n'; exit 2; }
+# shellcheck disable=SC2154
 [ -d "$srcdir"  ] || { printf 'fail: invalid srcdir\n';  exit 3; }
 
-X=$(printf '\%03o' {255..0})
-Y=$(printf '\%03o' {0..255})
+# Word splitting is not a concern here.
+# shellcheck disable=SC2046
+X=$(printf '\\%03o' $(seqq '255' '-1'   '0'))
+# shellcheck disable=SC2046
+Y=$(printf '\\%03o' $(seqq   '0'  '1' '255'))
 
 cd "$srcdir" || { printf 'fail: cd\n'; exit 4; }
 for z in *.mst; do tr "$X" "$Y" <"$z" >"$datadir/${z%%.mst}.xst"; done
diff --git a/msw_cygwin.make b/msw_cygwin.make
index c9bf07e..9c73930 100644
--- a/msw_cygwin.make
+++ b/msw_cygwin.make
@@ -54,7 +54,8 @@ system_root := /cygdrive/c
 # Full path to gcc binaries, slash-terminated if nonempty. Setting it
 # to an empty string finds gcc on $PATH instead.
 
-gcc_bin_dir := /opt/lmi/mingw/bin/
+mingw_dir   := /opt/lmi/${LMI_COMPILER}_${LMI_TRIPLET}/gcc_msw
+gcc_bin_dir := $(mingw_dir)/bin/
 
 # Oddly, MinGW-w64 provides prefixed versions of compilers, e.g.:
 #   i686-w64-mingw32-gcc.exe
@@ -79,12 +80,11 @@ RC      := $(gcc_bin_dir)$(host_hyphen)windres
 #   https://cygwin.com/ml/cygwin/2010-09/msg00553.html
 # Of course manipulating an lmi user's $PATH is out of the question.
 
-compiler_sysroot := /opt/lmi/mingw/$(LMI_TRIPLET)/lib
+compiler_sysroot := $(mingw_dir)/$(LMI_TRIPLET)/lib
 
 compiler_runtime_files := \
   $(wildcard $(compiler_sysroot)/libgcc*.dll) \
   $(wildcard $(compiler_sysroot)/libstdc++*.dll) \
-  $(wildcard $(compiler_sysroot)/libwinpthread-1.dll) \
 
 
################################################################################
 
diff --git a/msw_generic.make b/msw_generic.make
index 5a67b79..f6c3d25 100644
--- a/msw_generic.make
+++ b/msw_generic.make
@@ -31,16 +31,6 @@ endif
 
 system_root := /
 
-PERFORM := wine
-
-# $(winebindir) is where 'install_miscellanea.make' places 'md5sum.exe'.
-
-# alternative to 'set_toolchain.sh'
-w0 := $(shell winepath -w $(localbindir) | sed -e's/\\/\\\\/g')
-w1 := $(shell winepath -w $(locallibdir) | sed -e's/\\/\\\\/g')
-w2 := $(shell winepath -w $(winebindir)  | sed -e's/\\/\\\\/g')
-export WINEPATH=$(w0);$(w1);$(w2)
-
 
################################################################################
 
 # Compiler, linker, and so on.
@@ -72,16 +62,9 @@ RC      := $(gcc_bin_dir)$(host_hyphen)windres
 
 compiler_sysroot := $(dir $(shell $(CXX) -print-libgcc-file-name))
 
-# 'libwinpthread*' is no longer needed for debian cross builds--see:
-#   https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=748353
-# | Provide compilers using Windows and POSIX threads. The default setup
-# | uses Windows threads, thus avoiding the dependency on the pthreads DLL
-# but including it in this list with $(wildcard) does no harm.
-
 compiler_runtime_files := \
   $(wildcard $(compiler_sysroot)/libgcc*.dll) \
   $(wildcard $(compiler_sysroot)/libstdc++*.dll) \
-  $(wildcard $(compiler_sysroot)/libwinpthread-1.dll) \
 
 
################################################################################
 
diff --git a/nychthemeral_test.sh b/nychthemeral_test.sh
index 8b3e205..2d94dcb 100755
--- a/nychthemeral_test.sh
+++ b/nychthemeral_test.sh
@@ -121,13 +121,19 @@ nychthemeral_clutter='
 /^  *[1-9][0-9]* source lines/d
 /^  *[1-9][0-9]* marked defects/d
 /^# xrc tests/d
-/^# schema tests/d
 /^# test all valid emission types/d
+/^# schema tests/d
+/^# test mst --> xst conversion/d
 /^$/d
 '
 
 # Directory for test logs.
-log_dir=/tmp/lmi/"${LMI_COMPILER}_${LMI_TRIPLET}"/logs
+#
+# It seems redundant to construct yet another $prefix and $exec_prefix here;
+# perhaps that should be done OAOO in a script that selects a toolchain.
+prefix=/opt/lmi
+exec_prefix="$prefix/${LMI_COMPILER}_${LMI_TRIPLET}"
+log_dir="$exec_prefix"/logs
 mkdir --parents "$log_dir"
 
 {
@@ -157,7 +163,7 @@ else
 fi
 
 printf '\n# unit tests\n\n'
-make "$coefficiency" unit_tests 2>&1 \
+make "$coefficiency" --output-sync=recurse unit_tests 2>&1 \
   | tee >(grep '\*\*\*') >(grep \?\?\?\?) >(grep '!!!!' --count | xargs printf 
'%d tests succeeded\n') >"$log_dir"/unit_tests
 
 printf '\n# build with shared-object attributes\n\n'
@@ -169,7 +175,7 @@ make "$coefficiency" --output-sync=recurse cgi_tests 
cli_tests build_type=safest
   | tee "$log_dir"/cgi_cli_safestdlib | sed -e "$build_clutter" -e 
"$cli_cgi_clutter"
 
 printf '\n# unit tests in libstdc++ debug mode\n\n'
-make "$coefficiency" unit_tests build_type=safestdlib 2>&1 \
+make "$coefficiency" --output-sync=recurse unit_tests build_type=safestdlib 
2>&1 \
   | tee >(grep '\*\*\*') >(grep \?\?\?\?) >(grep '!!!!' --count | xargs printf 
'%d tests succeeded\n') >"$log_dir"/unit_tests_safestdlib
 
 printf '\n# xrc tests\n\n'
@@ -178,9 +184,9 @@ java -jar /opt/lmi/third_party/rng/jing.jar -c xrc.rnc 
./*.xrc 2>&1 \
 
 # Run the following tests in a throwaway directory so that the files
 # they create can be cleaned up easily.
-cd /tmp
-mkdir --parents /tmp/lmi/tmp
-cd /tmp/lmi/tmp
+throwaway_dir="$log_dir"/tmp
+mkdir --parents "$throwaway_dir"
+cd "$throwaway_dir"
 
 # Copy these files hither because the emission tests write some
 # output files to the input file's directory.
@@ -189,17 +195,46 @@ cp /opt/lmi/src/lmi/sample.cns .
 
 printf '\n# test all valid emission types\n\n'
 
-$PERFORM /opt/lmi/bin/lmi_cli_shared --file=/tmp/lmi/tmp/sample.ill --accept 
--ash_nazg --data_path=/opt/lmi/data 
--emit=emit_test_data,emit_spreadsheet,emit_text_stream,emit_custom_0,emit_custom_1
 >/dev/null
+$PERFORM /opt/lmi/bin/lmi_cli_shared --file="$throwaway_dir"/sample.ill 
--accept --ash_nazg --data_path=/opt/lmi/data 
--emit=emit_test_data,emit_spreadsheet,emit_text_stream,emit_custom_0,emit_custom_1
 >/dev/null
 
-$PERFORM /opt/lmi/bin/lmi_cli_shared --file=/tmp/lmi/tmp/sample.cns --accept 
--ash_nazg --data_path=/opt/lmi/data 
--emit=emit_test_data,emit_spreadsheet,emit_group_roster,emit_text_stream,emit_custom_0,emit_custom_1
 >/dev/null
+$PERFORM /opt/lmi/bin/lmi_cli_shared --file="$throwaway_dir"/sample.cns 
--accept --ash_nazg --data_path=/opt/lmi/data 
--emit=emit_test_data,emit_spreadsheet,emit_group_roster,emit_text_stream,emit_custom_0,emit_custom_1
 >/dev/null
 
 printf '\n# schema tests\n\n'
 /opt/lmi/src/lmi/test_schemata.sh 2>&1 \
   | tee "$log_dir"/schemata | sed -e "$schemata_clutter"
 
+printf '\n# test mst --> xst conversion\n\n'
+
+# All unique characters found in '*.mst' as of 2019-05-13.
+cat >eraseme.mst <<'EOF'
+ !"#$%&'()*+,-./
+0123456789
+:;<=>?@
+ABCDEFGHIJKLMNOPRSTUVWXYZ
+[]^_
+abcdefghijklmnopqrstuvwxyz
+{}
+EOF
+
+printf '%b' "\
+\\0337\\0336\\0335\\0334\\0333\\0332\\0331\\0330\\0327\\0326\
+\\0325\\0324\\0323\\0322\\0321\\0320\\0365\\0317\\0316\\0315\
+\\0314\\0313\\0312\\0311\\0310\\0307\\0306\\0365\\0305\\0304\
+\\0303\\0302\\0301\\0300\\0277\\0365\\0276\\0275\\0274\\0273\
+\\0272\\0271\\0270\\0267\\0266\\0265\\0264\\0263\\0262\\0261\
+\\0260\\0257\\0255\\0254\\0253\\0252\\0251\\0250\\0247\\0246\
+\\0245\\0365\\0244\\0242\\0241\\0240\\0365\\0236\\0235\\0234\
+\\0233\\0232\\0231\\0230\\0227\\0226\\0225\\0224\\0223\\0222\
+\\0221\\0220\\0217\\0216\\0215\\0214\\0213\\0212\\0211\\0210\
+\\0207\\0206\\0205\\0365\\0204\\0202\\0365\
+" >eraseme.touchstone
+
+srcdir=. datadir=. /opt/lmi/src/lmi/mst_to_xst.sh
+cmp eraseme.xst eraseme.touchstone
+
 # Clean up stray output. (The zsh '(N)' glob qualifier turns on
 # null_glob for a single expansion.)
-for z in /tmp/lmi/tmp/*(N); do rm "$z"; done
+for z in "$throwaway_dir"/*(N); do rm "$z"; done
 
 # The automated GUI test simulates keyboard and mouse actions, so
 # no such actions must be performed manually while it is running.
diff --git a/objects.make b/objects.make
index 05c045c..19574bd 100644
--- a/objects.make
+++ b/objects.make
@@ -295,6 +295,7 @@ lmi_common_objects := \
   ihs_irc7702a.o \
   ihs_mortal.o \
   ihs_server7702.o \
+  irc7702_tables.o \
   lmi.o \
   md5.o \
   mec_input.o \
@@ -564,6 +565,7 @@ commutation_functions_test$(EXEEXT): \
   commutation_functions.o \
   commutation_functions_test.o \
   cso_table.o \
+  irc7702_tables.o \
   timer.o \
 
 configurable_settings_test$(EXEEXT): \
diff --git a/pdf_command_wx.cpp b/pdf_command_wx.cpp
index 96bb26b..8c5105e 100644
--- a/pdf_command_wx.cpp
+++ b/pdf_command_wx.cpp
@@ -1330,56 +1330,6 @@ class numbered_page : public page_with_marginals
     int               extra_pages_      {0};
 };
 
-/// Generic cover page for most ledger types.
-///
-/// See discussion here:
-///   https://lists.nongnu.org/archive/html/lmi/2019-04/msg00024.html
-
-class cover_page : public numbered_page
-{
-  public:
-    using numbered_page::numbered_page;
-
-    void render() override
-    {
-        // Call base-class implementation to render the footer.
-        numbered_page::render();
-        int const height_contents = writer_.output_html
-            (writer_.get_horz_margin()
-            ,writer_.get_vert_margin()
-            ,writer_.get_page_width()
-            ,interpolator_.expand_template("cover")
-            );
-
-        // There is no way to draw a border around the page contents in wxHTML
-        // currently, so do it manually.
-        auto& pdf_dc = writer_.dc();
-
-        pdf_dc.SetPen(wxPen(illustration_rule_color, 2));
-        pdf_dc.SetBrush(*wxTRANSPARENT_BRUSH);
-
-        pdf_dc.DrawRectangle
-            (writer_.get_horz_margin()
-            ,writer_.get_vert_margin()
-            ,writer_.get_page_width()
-            ,height_contents
-            );
-    }
-
-  private:
-    int get_extra_pages_needed() override
-    {
-        return 0;
-    }
-
-    // Only the lower part of the footer is wanted here.
-    std::string get_upper_footer_template_name() const override
-    {
-        return std::string {};
-    }
-
-};
-
 // Simplest possible page which is entirely defined by its external template
 // whose name must be specified when constructing it.
 class standard_page : public numbered_page
@@ -1434,6 +1384,21 @@ class standard_page : public numbered_page
             }
     }
 
+  protected:
+    int get_extra_pages_needed() override
+    {
+        page_break_positions_ = writer_.paginate_html
+            (writer_.get_page_width()
+            ,get_page_body_height()
+            ,*page_body_cell_
+            );
+
+        // The cast is safe, we're never going to have more than INT_MAX
+        // pages and if we, somehow, do, the caller checks that this function
+        // returns a positive value.
+        return static_cast<int>(page_break_positions_.size()) - 1;
+    }
+
   private:
     // Parse HTML page contents once and store the result in page_body_cell_
     // and header_cell_ member variables.
@@ -1484,26 +1449,52 @@ class standard_page : public numbered_page
         return header_cell_.get();
     }
 
-    int get_extra_pages_needed() override
-    {
-        page_break_positions_ = writer_.paginate_html
-            (writer_.get_page_width()
-            ,get_page_body_height()
-            ,*page_body_cell_
-            );
-
-        // The cast is safe, we're never going to have more than INT_MAX
-        // pages and if we, somehow, do, the caller checks that this function
-        // returns a positive value.
-        return static_cast<int>(page_break_positions_.size()) - 1;
-    }
-
     char const* const                    page_template_name_;
     std::unique_ptr<wxHtmlContainerCell> page_body_cell_;
     std::unique_ptr<wxHtmlContainerCell> header_cell_;
     std::vector<int>                     page_break_positions_;
 };
 
+/// Generic cover page for most ledger types.
+///
+/// See discussion here:
+///   https://lists.nongnu.org/archive/html/lmi/2019-04/msg00024.html
+
+class cover_page : public standard_page
+{
+  public:
+    cover_page
+        (pdf_illustration  const& illustration
+        ,Ledger            const& ledger
+        ,pdf_writer_wx          & writer
+        ,html_interpolator const& interpolator
+        )
+        :standard_page
+            (illustration
+            ,ledger
+            ,writer
+            ,interpolator
+            ,"cover"
+            )
+    {
+    }
+
+  private:
+    int get_extra_pages_needed() override
+    {
+        int const extra = standard_page::get_extra_pages_needed();
+        if(0 != extra)
+            warning() << "Cover page will overflow." << LMI_FLUSH;
+        return extra;
+    }
+
+    // Only the lower part of the footer is wanted here.
+    std::string get_upper_footer_template_name() const override
+    {
+        return std::string {};
+    }
+};
+
 // Helper classes used to show the numeric summary table. The approach used
 // here is to define a custom HTML tag (<numeric_summary_table>) and use the
 // existing wx_table_generator to replace it with the actual table when
diff --git a/set_toolchain.sh b/set_toolchain.sh
index 54b7caa..319fd17 100755
--- a/set_toolchain.sh
+++ b/set_toolchain.sh
@@ -92,8 +92,9 @@ local   lmi_build_type
 
 local      prefix="/opt/lmi"
 local exec_prefix="$prefix/${LMI_COMPILER}_${LMI_TRIPLET}"
-local localbindir="$exec_prefix"/local/bin
-local locallibdir="$exec_prefix"/local/lib
+local localbindir="$prefix/local/${LMI_COMPILER}_${LMI_TRIPLET}/bin"
+local locallibdir="$prefix/local/${LMI_COMPILER}_${LMI_TRIPLET}/lib"
+# $winebindir is where 'install_miscellanea.make' places 'md5sum.exe'.
 local  winebindir="$prefix"/third_party/bin
 
 # Running a command like this many times:
@@ -107,12 +108,9 @@ local  winebindir="$prefix"/third_party/bin
 minimal_path=${MINIMAL_PATH:-"/usr/bin:/bin:/usr/sbin:/sbin"}
 export PATH="$localbindir":"$locallibdir":"$minimal_path"
 
-# It is appropriate to unset $WINEPATH because no lmi script ever uses
-# it directly--it's used, implicitly, only by 'wine'. But $PERFORM is
-# used directly, so it's always exported, even if empty--though that's
-# probably just a matter of taste.
+# It is okay to export these two variables unconditionally.
 
-unset -v WINEPATH
+export WINEPATH
 export PERFORM
 
 # Are double quotes inside double quotes inside $() dubious? I.e.,
@@ -139,6 +137,13 @@ case "$lmi_build_type" in
         ;;
     (*) ;;
 esac
+if [ -n "$LMI_ENV_FILE" ]; then
+    {
+    echo "export PATH     := $PATH"
+    echo "export WINEPATH := $WINEPATH"
+    echo "export PERFORM  := $PERFORM"
+    } > "$LMI_ENV_FILE"
+fi
 }
 
 # This script is to be sourced, so it can't use a builtin command like
diff --git a/tabs/3/startup_script b/tabs/3/startup_script
index 03f381e..28c12f6 100755
--- a/tabs/3/startup_script
+++ b/tabs/3/startup_script
@@ -6,10 +6,10 @@ b='cd /opt/lmi/src/lmi'
 c='make $coefficiency install check_physical_closure 2>&1 | tee ../log | sed 
-f diagnostics.sed | less -S'
 d='make $coefficiency cgi_tests cli_tests 2>&1 | less -S'
 e='make $coefficiency system_test 2>&1 | less -S'
-f="make \$coefficiency unit_tests 2>&1 | tee >(grep '\*\*\*') >(grep '????') 
>(grep '!!!!' --count | xargs printf '%d tests succeeded\n') >../log"
+f="make \$coefficiency --output-sync=recurse unit_tests 2>&1 | tee >(grep 
'\*\*\*') >(grep '????') >(grep '!!!!' --count | xargs printf '%d tests 
succeeded\n') >../log"
 g='make $coefficiency all build_type=so_test USE_SO_ATTRIBUTES=1 2>&1 | tee 
../log | sed -f diagnostics.sed | less -S'
 h='make $coefficiency cgi_tests cli_tests build_type=safestdlib 2>&1 | tee 
../log | sed -f diagnostics.sed | less -S'
-i="make \$coefficiency unit_tests build_type=safestdlib 2>&1 | tee >(grep 
'\*\*\*') >(grep '????') >(grep '!!!!' --count | xargs printf '%d tests 
succeeded\n') >../log"
+i="make \$coefficiency --output-sync=recurse unit_tests build_type=safestdlib 
2>&1 | tee >(grep '\*\*\*') >(grep '????') >(grep '!!!!' --count | xargs printf 
'%d tests succeeded\n') >../log"
 j='./nychthemeral_test.sh'
 k='make $coefficiency install check_physical_closure 2>&1 | less -S'
 l='make $coefficiency unit_tests unit_test_targets=regex_test.exe 2>&1 | less 
-S'
diff --git a/test_coding_rules_test.sh b/test_coding_rules_test.sh
index 4bd226e..b7e0b51 100755
--- a/test_coding_rules_test.sh
+++ b/test_coding_rules_test.sh
@@ -24,6 +24,9 @@
 # This script is intended to be invoked by lmi makefiles; it would
 # rarely make sense to run it independently.
 
+# '\' really is an intentional escape in many here-documents.
+# shellcheck disable=SC1117
+
 echo "Testing 'test_coding_rules'."
 
 rm --force eraseme*
diff --git a/test_schemata.sh b/test_schemata.sh
index 5c681c1..af2a59b 100755
--- a/test_schemata.sh
+++ b/test_schemata.sh
@@ -25,7 +25,7 @@ echo "  Test schemata..."
 
 # Directory where this script resides.
 
-srcdir=$(dirname $(readlink --canonicalize "$0"))
+srcdir=$(dirname "$(readlink --canonicalize "$0")")
 
 # Directory where 'jing.jar' and 'trang.jar' reside, along with their
 # support files--extracted from:
@@ -36,16 +36,18 @@ jar_dir=/opt/lmi/third_party/rng
 
 # Data for testing.
 
-cp --preserve $srcdir/sample.cns $srcdir/sample.ill .
+cp --preserve "$srcdir"/sample.cns "$srcdir"/sample.ill .
 
 # XSL template to sort cell subelements.
 
-cp --preserve $srcdir/sort_cell_subelements.xsl .
+cp --preserve "$srcdir"/sort_cell_subelements.xsl .
 
 echo "  Test cell-subelement sorting."
 
-xsltproc sort_cell_subelements.xsl sample.cns > sorted.cns
-xsltproc sort_cell_subelements.xsl sample.ill > sorted.ill
+mingw_dir=/opt/lmi/${LMI_COMPILER}_${LMI_TRIPLET}/gcc_msw
+mingw_bin_dir="$mingw_dir"/bin
+PATH="$mingw_bin_dir:$PATH" xsltproc sort_cell_subelements.xsl sample.cns | tr 
--delete '\r' > sorted.cns
+PATH="$mingw_bin_dir:$PATH" xsltproc sort_cell_subelements.xsl sample.ill | tr 
--delete '\r' > sorted.ill
 diff --unified=0 sample.cns sorted.cns
 diff --unified=0 sample.ill sorted.ill
 
@@ -57,7 +59,7 @@ diff --unified=0 sample.ill sorted.ill
 #
 # Only RNC is to be edited; XSD and RNG are generated from it.
 
-cp --preserve $srcdir/types.rnc $srcdir/cell.rnc 
$srcdir/multiple_cell_document.rnc $srcdir/single_cell_document.rnc .
+cp --preserve "$srcdir"/types.rnc "$srcdir"/cell.rnc 
"$srcdir"/multiple_cell_document.rnc "$srcdir"/single_cell_document.rnc .
 
 echo "  Test RNC files with 'jing'."
 
@@ -73,7 +75,7 @@ java -jar $jar_dir/jing.jar -c single_cell_document.rnc   
sample.ill
 # XSD, generated from RNG, is stored in the repository because it's
 # widely used.
 
-cp --preserve $srcdir/types.xsd $srcdir/cell.xsd 
$srcdir/multiple_cell_document.xsd $srcdir/single_cell_document.xsd .
+cp --preserve "$srcdir"/types.xsd "$srcdir"/cell.xsd 
"$srcdir"/multiple_cell_document.xsd "$srcdir"/single_cell_document.xsd .
 
 echo "  Test XSD files with 'jing'."
 
@@ -147,6 +149,8 @@ Did not expect element StateOfJurisdictionMangledTag there
 sample_bad fails to validate
 EOF
 
+# '\/' really is an intentional escape (for sed, not sh).
+# shellcheck disable=SC1117
 cat >eraseme.sed <<EOF
 1,/<\/cell>/ {
   # Negative InforceDcv not allowed.
@@ -161,17 +165,18 @@ EOF
 echo "  Test invalid input: '.cns'."
 
 <sample.cns >sample_bad.cns sed --file=eraseme.sed
-rm --force cns.eraseme
-echo "  invalid input, jing, .rnc:"                                      >> 
cns.eraseme 2>&1
-java -jar $jar_dir/jing.jar -c multiple_cell_document.rnc sample_bad.cns >> 
cns.eraseme 2>&1
-echo "  invalid input, jing, .xsd:"                                      >> 
cns.eraseme 2>&1
-java -jar $jar_dir/jing.jar multiple_cell_document.xsd    sample_bad.cns >> 
cns.eraseme 2>&1
-echo "  invalid input, xmllint, .xsd:"                                   >> 
cns.eraseme 2>&1
-xmllint --noout --schema multiple_cell_document.xsd       sample_bad.cns >> 
cns.eraseme 2>&1
-echo "  invalid input, jing, .rng:"                                      >> 
cns.eraseme 2>&1
-java -jar $jar_dir/jing.jar multiple_cell_document.rng    sample_bad.cns >> 
cns.eraseme 2>&1
-echo "  invalid input, xmllint, .rng:"                                   >> 
cns.eraseme 2>&1
-xmllint --noout --relaxng multiple_cell_document.rng      sample_bad.cns >> 
cns.eraseme 2>&1
+{
+  echo "  invalid input, jing, .rnc:"
+  java -jar $jar_dir/jing.jar -c multiple_cell_document.rnc sample_bad.cns
+  echo "  invalid input, jing, .xsd:"
+  java -jar $jar_dir/jing.jar multiple_cell_document.xsd    sample_bad.cns
+  echo "  invalid input, xmllint, .xsd:"
+  xmllint --noout --schema multiple_cell_document.xsd       sample_bad.cns
+  echo "  invalid input, jing, .rng:"
+  java -jar $jar_dir/jing.jar multiple_cell_document.rng    sample_bad.cns
+  echo "  invalid input, xmllint, .rng:"
+  xmllint --noout --relaxng multiple_cell_document.rng      sample_bad.cns
+} > cns.eraseme 2>&1
 sed -e 's/^.*error: //;s/\.cns fails/ fails/;s/  *$//' -i cns.eraseme
 sed -e 's/^.*Schemas validity error : //' -i cns.eraseme
 sed -e 's/^.*Relax-NG validity error : //' -i cns.eraseme
@@ -180,17 +185,18 @@ diff --unified=0 touchstone.eraseme cns.eraseme
 echo "  Test invalid input: '.ill'."
 
 <sample.ill >sample_bad.ill sed --file=eraseme.sed
-rm --force ill.eraseme
-echo "  invalid input, jing, .rnc:"                                      >> 
ill.eraseme 2>&1
-java -jar $jar_dir/jing.jar -c single_cell_document.rnc   sample_bad.ill >> 
ill.eraseme 2>&1
-echo "  invalid input, jing, .xsd:"                                      >> 
ill.eraseme 2>&1
-java -jar $jar_dir/jing.jar single_cell_document.xsd      sample_bad.ill >> 
ill.eraseme 2>&1
-echo "  invalid input, xmllint, .xsd:"                                   >> 
ill.eraseme 2>&1
-xmllint --noout --schema single_cell_document.xsd         sample_bad.ill >> 
ill.eraseme 2>&1
-echo "  invalid input, jing, .rng:"                                      >> 
ill.eraseme 2>&1
-java -jar $jar_dir/jing.jar single_cell_document.rng      sample_bad.ill >> 
ill.eraseme 2>&1
-echo "  invalid input, xmllint, .rng:"                                   >> 
ill.eraseme 2>&1
-xmllint --noout --relaxng single_cell_document.rng        sample_bad.ill >> 
ill.eraseme 2>&1
+{
+  echo "  invalid input, jing, .rnc:"
+  java -jar $jar_dir/jing.jar -c single_cell_document.rnc   sample_bad.ill
+  echo "  invalid input, jing, .xsd:"
+  java -jar $jar_dir/jing.jar single_cell_document.xsd      sample_bad.ill
+  echo "  invalid input, xmllint, .xsd:"
+  xmllint --noout --schema single_cell_document.xsd         sample_bad.ill
+  echo "  invalid input, jing, .rng:"
+  java -jar $jar_dir/jing.jar single_cell_document.rng      sample_bad.ill
+  echo "  invalid input, xmllint, .rng:"
+  xmllint --noout --relaxng single_cell_document.rng        sample_bad.ill
+} > ill.eraseme 2>&1
 sed -e 's/^.*error: //;s/\.ill fails/ fails/;s/  *$//' -i ill.eraseme
 sed -e 's/^.*Schemas validity error : //' -i ill.eraseme
 sed -e 's/^.*Relax-NG validity error : //' -i ill.eraseme
@@ -202,7 +208,7 @@ echo "  Regenerate XSD files as they should appear in the 
repository."
 # 'cell.xsd', which lacks <xs:complexType name="cell_element">, so
 # process 'multiple' before 'single'.
 
-cp --preserve $srcdir/types_*.rnc $srcdir/cell_*.rnc 
$srcdir/multiple_cell_document_*.rnc $srcdir/single_cell_document_*.rnc .
+cp --preserve "$srcdir"/types_*.rnc "$srcdir"/cell_*.rnc 
"$srcdir"/multiple_cell_document_*.rnc "$srcdir"/single_cell_document_*.rnc .
 
 java -jar $jar_dir/trang.jar multiple_cell_document.rnc    
multiple_cell_document.xsd
 java -jar $jar_dir/trang.jar single_cell_document.rnc      
single_cell_document.xsd



reply via email to

[Prev in Thread] Current Thread [Next in Thread]