diff --git a/jfp-paper/amsfonts.sty b/jfp-paper/amsfonts.sty
new file mode 100644
index 0000000000000000000000000000000000000000..5d563d6254209c12bab4fda5444903fde2161129
--- /dev/null
+++ b/jfp-paper/amsfonts.sty
@@ -0,0 +1,190 @@
+%%
+%% This is file `amsfonts.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% amsfonts.dtx 
+%% 
+%%% ====================================================================
+%%% @LaTeX-file{
+%%%   filename        = "amsfonts.dtx",
+%%%   version         = "2.2f",
+%%%   date            = "2001/10/25",
+%%%   time            = "11:51:34 EDT",
+%%%   checksum        = "12894 459 2125 19071",
+%%%   author          = "American Mathematical Society",
+%%%   copyright       = "Copyright 2001 American Mathematical Society,
+%%%                      all rights reserved.  Copying of this file is
+%%%                      authorized only if either:
+%%%                      (1) you make absolutely no changes to your copy,
+%%%                      including name; OR
+%%%                      (2) if you do make changes, you first rename it
+%%%                      to some other name.",
+%%%   address         = "American Mathematical Society,
+%%%                      Technical Support,
+%%%                      Publications Technical Group,
+%%%                      P. O. Box 6248,
+%%%                      Providence, RI 02940,
+%%%                      USA",
+%%%   telephone       = "401-455-4080 or (in the USA and Canada)
+%%%                      800-321-4AMS (321-4267)",
+%%%   FAX             = "401-331-3842",
+%%%   email           = "tech-support@ams.org (Internet)",
+%%%   codetable       = "ISO/ASCII",
+%%%   keywords        = "latex, amslatex, ams-latex, amsfonts, msam,
+%%%                      msbm, eufm, blackboard bold",
+%%%   supported       = "yes",
+%%%   abstract        = "This file is part of the AMSFonts distribution.
+%%%                      It provides easy access in \LaTeXe{} to certain
+%%%                      math fonts for extra math symbols, fraktur
+%%%                      letters, and blackboard bold letters. See the
+%%%                      AMSFonts user's guide for more information.",
+%%%   docstring       = "The checksum field above contains a CRC-16
+%%%                      checksum as the first value, followed by the
+%%%                      equivalent of the standard UNIX wc (word
+%%%                      count) utility output of lines, words, and
+%%%                      characters.  This is produced by Robert
+%%%                      Solovay's checksum utility.",
+%%% }
+%%% ====================================================================
+\NeedsTeXFormat{LaTeX2e}% LaTeX 2.09 can't be used (nor non-LaTeX)
+[1994/12/01]% LaTeX date must be December 1994 or later
+\ProvidesPackage{amsfonts}[2001/10/25 v2.2f]
+\DeclareOption{psamsfonts}{%
+  \ifnum\cmex@opt=7 \def\cmex@opt{10}%
+  \else \def\cmex@opt{0}\fi
+  \DeclareFontFamily{U}{msa}{}%
+  \DeclareFontShape{U}{msa}{m}{n}{<-6>msam5<6-8>msam7<8->msam10}{}%
+  \DeclareFontFamily{U}{msb}{}%
+  \DeclareFontShape{U}{msb}{m}{n}{<-6>msbm5<6-8>msbm7<8->msbm10}{}%
+  \DeclareFontFamily{U}{euf}{}%
+  \DeclareFontShape{U}{euf}{m}{n}{<-6>eufm5<6-8>eufm7<8->eufm10}{}%
+  \DeclareFontShape{U}{euf}{b}{n}{<-6>eufb5<6-8>eufb7<8->eufb10}{}%
+}
+\@ifundefined{cmex@opt}{\def\cmex@opt{1}}{}
+\ProcessOptions\relax
+\ifnum\cmex@opt=1 \relax
+  \DeclareFontShape{OMX}{cmex}{m}{n}{<-8>cmex7<8>cmex8<9>cmex9%
+    <10><10.95><12><14.4><17.28><20.74><24.88>cmex10}{}%
+  \expandafter\let\csname OMX/cmex/m/n/10\endcsname\relax
+\else
+  \ifnum\cmex@opt=10 % need to override cmex7 fontdef from amsmath
+    \begingroup
+    \expandafter\let\csname OMX+cmex\endcsname\relax
+    \fontencoding{OMX}\fontfamily{cmex}%
+    \try@load@fontshape
+    \endgroup
+    \expandafter\let\csname OMX/cmex/m/n/10\endcsname\relax
+    \def\cmex@opt{0}%
+  \fi
+\fi
+\providecommand*{\@mathmeasure}[3]{%
+  \setbox#1\hbox{\frozen@everymath\@emptytoks\m@th$#2#3$}}
+\@ifundefined{@emptytoks}{\csname newtoks\endcsname\@emptytoks}{}
+\DeclareSymbolFont{AMSa}{U}{msa}{m}{n}
+\DeclareSymbolFont{AMSb}{U}{msb}{m}{n}
+\@ifundefined{yen}{%
+  \edef\yen{\noexpand\mathhexbox{\hexnumber@\symAMSa}55}
+}{}
+\@ifundefined{checkmark}{%
+  \edef\checkmark{\noexpand\mathhexbox{\hexnumber@\symAMSa}58}
+}{}
+\@ifundefined{circledR}{%
+  \edef\circledR{\noexpand\mathhexbox{\hexnumber@\symAMSa}72}
+}{}
+\@ifundefined{maltese}{%
+  \edef\maltese{\noexpand\mathhexbox{\hexnumber@\symAMSa}7A}
+}{}
+\begingroup \catcode`\"=12
+\DeclareMathDelimiter{\ulcorner}{\mathopen} {AMSa}{"70}{AMSa}{"70}
+\DeclareMathDelimiter{\urcorner}{\mathclose}{AMSa}{"71}{AMSa}{"71}
+\DeclareMathDelimiter{\llcorner}{\mathopen} {AMSa}{"78}{AMSa}{"78}
+\DeclareMathDelimiter{\lrcorner}{\mathclose}{AMSa}{"79}{AMSa}{"79}
+\xdef\widehat#1{\noexpand\@mathmeasure\z@\textstyle{#1}%
+  \noexpand\ifdim\noexpand\wd\z@>\tw@ em%
+  \mathaccent"0\hexnumber@\symAMSb 5B{#1}%
+  \noexpand\else\mathaccent"0362{#1}\noexpand\fi}
+\xdef\widetilde#1{\noexpand\@mathmeasure\z@\textstyle{#1}%
+  \noexpand\ifdim\noexpand\wd\z@>\tw@ em%
+  \mathaccent"0\hexnumber@\symAMSb 5D{#1}%
+  \noexpand\else\mathaccent"0365{#1}\noexpand\fi}
+\DeclareMathSymbol{\dabar@}{\mathord}{AMSa}{"39}
+\xdef\dashrightarrow{\mathrel{\dabar@\dabar@
+                              \mathchar"0\hexnumber@\symAMSa 4B}}%
+\xdef\dashleftarrow{\mathrel{\mathchar"0\hexnumber@\symAMSa 4C\dabar@
+                              \dabar@}}%
+\global\let\dasharrow\dashrightarrow
+\global\let\rightleftharpoons\undefined
+\DeclareMathSymbol{\rightleftharpoons}{\mathrel}{AMSa}{"0A}
+\global\let\angle\undefined
+\DeclareMathSymbol{\angle}            {\mathord}{AMSa}{"5C}
+\global\let\hbar\undefined
+\DeclareMathSymbol{\hbar}             {\mathord}{AMSb}{"7E}
+\global\let\sqsubset\undefined
+\DeclareMathSymbol{\sqsubset}         {\mathrel}{AMSa}{"40}
+\global\let\sqsupset\undefined
+\DeclareMathSymbol{\sqsupset}         {\mathrel}{AMSa}{"41}
+\global\let\mho\undefined
+\DeclareMathSymbol{\mho}              {\mathord}{AMSb}{"66}
+\endgroup
+\DeclareMathAlphabet{\mathfrak}{U}{euf}{m}{n}
+\SetMathAlphabet{\mathfrak}{bold}{U}{euf}{b}{n}
+\DeclareSymbolFontAlphabet{\mathbb}{AMSb}
+\DeclareFontEncodingDefaults{\relax}{\def\accentclass@{7}}
+\DeclareRobustCommand{\frak}[1]{%
+  {\@subst@obsolete{amsfonts}\frak\mathfrak{#1}}}
+\DeclareRobustCommand{\Bbb}[1]{%
+  {\@subst@obsolete{amsfonts}\Bbb\mathbb{#1}}}
+\DeclareRobustCommand{\bold}[1]{%
+  {\@subst@obsolete{amsfonts}\bold\mathbf{#1}}}
+\begingroup \catcode`\"=12 \relax
+\gdef\newsymbol#1#2#3#4#5{%
+  \@obsolete{amsfonts}\newsymbol\DeclareMathSymbol
+  \@ifdefinable#1{%
+     \edef\next@
+       {\ifcase #2 \or
+          \hexnumber@\symAMSa\or
+          \hexnumber@\symAMSb\fi}%
+     \ifx\next@\@empty
+       \PackageError{amsfonts}{\Invalid@@\newsymbol}\@ehd%
+     \else
+      \global\mathchardef#1"#3\next@#4#5
+     \fi}}
+\endgroup
+\long\def\@gobblethree#1#2#3{}
+\if@compatibility
+  \let\@obsolete\@gobblethree
+\else
+  \def\@obsolete#1#2#3{\PackageWarning{#1}{%
+    Obsolete command \protect#2; \protect#3 should be used instead}}%
+\fi
+\def\@subst@obsolete#1#2#3{\@obsolete{#1}#2#3\gdef#2{#3}#2}
+\begingroup \catcode`\"=12
+\DeclareMathSymbol{\square}           {\mathord}{AMSa}{"03}
+\DeclareMathSymbol{\lozenge}          {\mathord}{AMSa}{"06}
+\DeclareMathSymbol{\vartriangleright} {\mathrel}{AMSa}{"42}
+\DeclareMathSymbol{\vartriangleleft}  {\mathrel}{AMSa}{"43}
+\DeclareMathSymbol{\trianglerighteq}  {\mathrel}{AMSa}{"44}
+\DeclareMathSymbol{\trianglelefteq}   {\mathrel}{AMSa}{"45}
+\DeclareMathSymbol{\rightsquigarrow}  {\mathrel}{AMSa}{"20}
+\@ifpackageloaded{latexsym}{\@tempswafalse}{\@tempswatrue}
+\if@tempswa
+  \global\let\Box\square
+  \global\let\Diamond\lozenge
+  \global\let\leadsto\rightsquigarrow
+  \global\let\lhd\@@undefined
+  \global\let\unlhd\@@undefined
+  \global\let\rhd\@@undefined
+  \global\let\unrhd\@@undefined
+  \DeclareMathSymbol{\lhd}     {\mathbin}{AMSa}{"43}
+  \DeclareMathSymbol{\unlhd}   {\mathbin}{AMSa}{"45}
+  \DeclareMathSymbol{\rhd}     {\mathbin}{AMSa}{"42}
+  \DeclareMathSymbol{\unrhd}   {\mathbin}{AMSa}{"44}
+\xdef\Join{\mathrel{\mathchar"0\hexnumber@\symAMSb 6F\mkern-13.8mu%
+  \mathchar"0\hexnumber@\symAMSb 6E}}
+\fi
+\endgroup
+\endinput
+%%
+%% End of file `amsfonts.sty'.
\ No newline at end of file
diff --git a/jfp-paper/bm.sty b/jfp-paper/bm.sty
new file mode 100644
index 0000000000000000000000000000000000000000..57a736d697a948e97e143541a7a0b69ed2a9b467
--- /dev/null
+++ b/jfp-paper/bm.sty
@@ -0,0 +1,423 @@
+%%
+%% This is file `bm.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% bm.dtx  (with options: `package')
+%% 
+%% This is a generated file.
+%% 
+%% Copyright 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003
+%% The LaTeX3 Project and any individual authors listed elsewhere
+%% in this file.
+%% 
+%% This file was generated from file(s) of the Standard LaTeX `Tools Bundle'.
+%% --------------------------------------------------------------------------
+%% 
+%% It may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either version 1.3
+%% of this license or (at your option) any later version.
+%% The latest version of this license is in
+%%    http://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of LaTeX
+%% version 2003/12/01 or later.
+%% 
+%% This file may only be distributed together with a copy of the LaTeX
+%% `Tools Bundle'. You may however distribute the LaTeX `Tools Bundle'
+%% without such generated files.
+%% 
+%% The list of all files belonging to the LaTeX `Tools Bundle' is
+%% given in the file `manifest.txt'.
+%% 
+%% Copyright 1996 1997 1998 1999 2002 2003 2004 David Carlisle Frank Mittelbach
+%%
+%% Development of this package was commissioned by Y&Y Inc.
+%% http://www.yandy.com
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{bm}
+          [2004/02/26 v1.1c Bold Symbol Support (DPC/FMi)]
+\def\bm#1#2{%
+  \let\bm@pmb\install@mathalphabet
+  \let\bm@pmb@\getanddefine@fonts
+  \let\bm@pmb@@\or
+  \edef\bm@general{\f@encoding/\f@family/\f@series/\f@shape/\f@size}%
+  \@tempcnta#2%
+  \count@-\count18%
+  \advance\count@-\@tempcnta
+  \advance\count@15\relax
+  \ifnum\count@<\z@
+    \advance\@tempcnta\count@
+  \fi
+  \let\or\relax
+  \expandafter\let\csname bm@#1table\endcsname\@gobble
+  \def\bm@define##1{%
+    \expandafter\xdef\csname bm@#1table\endcsname{%
+      \csname bm@#1table\endcsname\or##1}}%
+  \def\getanddefine@fonts##1##2{%
+    \def\@tempa{##2}%
+    \def\@tempb####1##1####2####3\@nil{\def\@tempb{####2}}%
+    \expandafter\expandafter\expandafter
+      \@tempb\csname mv@#1\endcsname\@nil
+    \ifx\@tempa\@tempb
+      \bm@define\m@ne
+    \else
+      \edef\@tempa{sym#1\expandafter\@gobblefour\string##1}%
+      \ifnum\@tempcnta<%
+           \expandafter\ifx\csname\@tempa\endcsname\relax
+             \@ne
+           \else
+             \m@ne
+           \fi
+        \bm@define\z@
+      \else
+        \expandafter\ifx\csname\@tempa\endcsname\relax
+          \begingroup
+          \escapechar\m@ne
+          \edef\@tempb{\endgroup
+            \noexpand\split@name
+            \expandafter\string\@tempb}%
+          \@tempb/\@nil
+         \expandafter\ifx
+           \csname symbold\expandafter\@gobblefour\string##1\endcsname
+           \relax
+            \expandafter\new@mathgroup\csname\@tempa\endcsname
+            \expandafter\new@symbolfont\csname\@tempa\endcsname
+                       \f@encoding\f@family\f@series\f@shape
+            \advance\@tempcnta\m@ne
+         \else
+           \def\bm@expand####1##1####2####3\@nil{\def\bm@expand{####2}}%
+    \expandafter\expandafter\expandafter
+           \bm@expand\csname mv@bold\endcsname\@nil
+           \ifx\bm@expand\@tempb
+             \expandafter\let\csname\@tempa\expandafter\endcsname
+                \csname symbold\expandafter
+                        \@gobblefour\string##1\endcsname
+           \else
+             \expandafter\new@mathgroup\csname\@tempa\endcsname
+             \expandafter\new@symbolfont\csname\@tempa\endcsname
+                       \f@encoding\f@family\f@series\f@shape
+             \advance\@tempcnta\m@ne
+           \fi
+         \fi
+        \else
+          \PackageInfo{bm}%
+            {Symbol font \@tempa\space already defined.\MessageBreak
+             Not overwriting it}%
+        \fi
+        \count@\csname\@tempa\endcsname
+        \advance\count@-##1%
+        \bm@define{\the\count@\relax}%
+      \fi
+    \fi}%
+  \let\install@mathalphabet\@gobbletwo
+  \mv@normal
+  \expandafter\xdef\csname bm@#1table\endcsname{%
+    \noexpand\ifcase\@tempcnta
+      \csname bm@#1table\endcsname
+    \noexpand\else
+      \z@
+    \noexpand\fi}%
+  \expandafter\split@name\bm@general\@nil
+  \let\install@mathalphabet\bm@pmb
+  \let\getanddefine@fonts\bm@pmb@
+  \let\or\bm@pmb@@}
+\ifx\bmmax\@undefined
+  \chardef\bmmax=4
+\fi
+\ifx\mv@bold\@undefined
+  \def\bm@boldtable{\m@ne}
+  \AtEndOfPackage{%
+    \def\bm@gr@up#1#2{%
+      \bm@pmb{#2}}}
+\else
+  \bm{bold}\bmmax
+  \@ifundefined{symboldoperators}
+    {}
+    {\DeclareSymbolFontAlphabet\mathbf{boldoperators}}
+\fi
+\ifx\hmmax\@undefined
+  \chardef\hmmax=3
+\fi
+\ifx\mv@heavy\@undefined
+\else
+  \bm{heavy}\hmmax
+\fi
+\begingroup
+\catcode`\'=\active
+\@firstofone{\endgroup
+\def\bm@general#1#2#3#4#5{%
+  \begingroup
+    \let\bm\@firstofone
+    \let\hm\@firstofone
+    \global\let\bm@command\@empty
+    \let\@let@token\@empty
+    \let\protect\@empty
+    \let\@typeset@protect\@empty
+    \def\bm@mathchoice{\bm@m@thchoice#1}%
+    \def\bm@group{\bm@gr@up#1}%
+    \let\bm@table#2%
+    \let\left\holdinginserts
+    \let\right\left
+    \let\mskip\mkern
+    \let\hskip\kern
+    \let\bm@prime\copy
+    \def'{\bm@prime\prime\relax}%
+    \def\@ifnextchar##1##2##3##4{%
+      \if##1##4%
+        \expandafter\@firstoftwo
+      \else
+        \expandafter\@secondoftwo
+      \fi
+      {##2##4}{##3{##4}}}%
+    \def\GenericWarning##1##2{%
+      \unvcopy{\GenericWarning{##1}{##2}}}%
+    \def\GenericError##1##2##3##4{%
+      \unvcopy{\GenericError{##1}{##2}{##3}{##4}}}%
+    \let\DN@\copy
+    \let\FN@\copy
+    \let\next@\copy
+    \global\let\bm@first\@empty
+    \ifx\uproot@\undefined\else
+       \def\root##1\of##2{{\root##1\of{##2}}}%
+    \fi
+    \def\mathaccentV##1{\mathaccent"\accentclass@}%
+    \let\@ifnext\@ifnextchar
+    \let\measure@lhs\copy
+    \let \rel@break\copy
+    \let \bin@break\copy
+    \let \after@open\copy
+    \let \after@close\copy
+    \let\ifmmode\iftrue
+     \let\install@mathalphabet\def
+     \let\getanddefine@fonts\@gobbletwo
+     #3%
+    \def\select@group##1##2##3##4{{%
+      \protect##1{##4}}}%
+    \def\use@mathgroup##1##2##3{{%
+      \protect\use@mathgroup##1{##2}{##3}}}%
+    \bm@expand#5\bm@end
+  \endgroup
+  #4}
+}
+\DeclareRobustCommand\bm{%
+  \bm@general\boldmath\bm@boldtable\mv@bold\bm@command}
+\protected@edef\bm#1{\bm{#1}}
+\def\DeclareBoldMathCommand{\@testopt\bm@declare{bold}}
+\def\bm@declare[#1]#2{%
+  \expandafter\bm@general
+        \csname #1math\expandafter\endcsname
+        \csname bm@#1table\expandafter\endcsname
+        \csname mv@#1\endcsname
+        {\bm@define#2}}
+\def\bmdefine{\DeclareBoldMathCommand[bold]}
+\ifx\mv@heavy\@undefined
+  \let\hm\bm
+  \let\heavymath\boldmath
+  \let\bm@heavytable\bm@boldtable
+\else
+  \DeclareRobustCommand\hm{%
+    \bm@general\heavymath\bm@heavytable\mv@heavy\bm@command}
+  \protected@edef\hm#1{\hm{#1}}
+  \def\hmdefine{\DeclareBoldMathCommand[heavy]}
+\fi
+\outer\def\bm@end{\@@end}
+\def\bm@expand{\afterassignment\bm@exp@nd\count@`\a}
+\def\bm@exp@nd{\afterassignment\bm@test\count@`\a}
+\def\bm@test{%
+  \let\bm@previous\@let@token
+  \futurelet\@let@token\bm@test@}
+\def\bm@test@{%
+  \ifx\@let@token\bgroup
+    \expandafter\bm@group
+  \else
+    \expandafter\bm@test@token
+  \fi}
+\def\bm@gr@up#1#2{%
+  \bm@add{{\bm@gr@@p#1{{#2}}}}}
+\def\bm@gr@@p#1#2{%
+  \ifmmode
+    \bm@mchoice#1{#2}{#2}{#2}{#2}%
+  \else
+    \bfseries#1#2%
+  \fi}
+\def\bm@test@token#1{%
+  \let\bm@next\@empty
+  \ifx#1\@@end
+  \else\ifx#1\mathchoice
+    \let\bm@next\bm@mathchoice
+  \else\ifx#1\mathchar
+    \afterassignment\bm@mathchar\count@
+  \else\ifx#1\mathaccent
+    \afterassignment\bm@mathaccent\count@
+  \else\ifx#1\delimiter
+    \afterassignment\bm@delimiter\count@
+  \else\ifx#1\radical
+    \afterassignment\bm@radical\count@
+  \else\ifx#1\mkern
+    \bm@register#1{\muskip\z@}%
+  \else\ifx#1\kern
+    \bm@register#1\skip@
+  \else\ifx#1\penalty
+    \bm@register#1\count@
+  \else\ifx#1\unvcopy
+    \let\bm@next\bm@add
+  \else\ifcat\noexpand#1\relax
+    \xdef\meaning@{\meaning#1}%
+    \expandafter\bm@mchar@test\meaning@""\@nil#1%
+  \else\ifcat.\ifcat a#1.\else#1\fi
+    \count@\mathcode`#1\relax
+    \ifnum\count@=\mathcode`\'%
+      \begingroup\uccode`\~`#1\uppercase{\endgroup
+        \def\bm@next{\bm@expand~}}%
+    \else
+      \ifx\bm@previous\left
+        \count@\delcode`#1\relax
+        \bm@delimiter
+      \else
+        \bm@mathchar
+      \fi
+    \fi
+  \else
+    \bm@add{#1}%
+  \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
+  \bm@next}
+\def\bm@define#1{%
+  \begingroup
+    \ifx\bm@command\@gtempa
+      \def\mathchar{\global\mathchardef#1}%
+      \bm@command
+    \else
+      \toks@\expandafter{\bm@command}%
+      \xdef#1{\bm@first\noexpand\bm@protect\noexpand#1{\the\toks@}}%
+    \fi
+  \endgroup}
+\def\bm@protect#1{%
+  \ifx\protect\@typeset@protect
+    \expandafter\@firstofone
+  \else
+    \protect#1\expandafter\@gobble
+  \fi}
+\def\bm@mchoice#1#2#3#4#5{%
+  \mathchoice{\hbox{#1$\displaystyle\m@th#2$}}%
+             {\hbox{#1$\textstyle\m@th#3$}}%
+             {\hbox{#1$\scriptstyle\m@th#4$}}%
+             {\hbox{#1$\scriptscriptstyle\m@th#5$}}}
+\def\bm@m@thchoice#1#2#3#4#5{%
+  \bm@add{\bm@mchoice#1{#2}{#3}{#4}{#5}}}
+\def\bm@register#1#2{%
+  \def\@tempa{#1\the#2}%
+  \afterassignment\bm@r@gister#2}
+\def\bm@r@gister{%
+  \bm@xadd{\@tempa\space}}
+\def\bm@mathchar{%
+  \@tempcntb\count@
+  \let\@tempa\bm@group
+  \bm@changefam{}%
+  \ifnum\count@>\@tempcntb
+    \ifx\bm@command\@empty
+      \xdef\@gtempa{\mathchar\the\count@\space}%
+    \fi
+    \bm@xadd{\mathchar\the\count@\space}%
+  \else
+    \begingroup
+      \divide\count@"1000
+      \let\bm@expand\relax
+      \bm@xadd\bm@class
+    \endgroup
+    \edef\@tempb{%
+      \noexpand\@tempa{\mathchar\the\count@\space}}%
+    \@tempb
+  \fi}
+\def\bm@pmb#1{%
+  \bm@add{\bm@pmb@{#1}}}
+\def\bm@pmb@#1{{%
+  \setbox\tw@\hbox{$\m@th\mkern.4mu$}%
+  \mathchoice
+    \bm@pmb@@\displaystyle\@empty{#1}%
+    \bm@pmb@@\textstyle\@empty{#1}%
+    \bm@pmb@@\scriptstyle\defaultscriptratio{#1}%
+    \bm@pmb@@\scriptscriptstyle\defaultscriptscriptratio{#1}}}
+\def\bm@pmb@@#1#2#3{{%
+  \setbox\z@\hbox{$\m@th#1#3$}%
+  \dimen@#2\wd\tw@
+  \rlap{\copy\z@}%
+  \kern\dimen@
+  \raise1.5\dimen@\rlap{\copy\z@}%
+  \kern\dimen@
+  \box\z@}}%
+\def\bm@class{%
+  \ifcase\count@
+    \or
+    \mathop\or
+    \mathbin\or
+    \mathrel\or
+    \mathopen\or
+    \mathclose\or
+    \mathpunct\or
+  \fi}
+\def\bm@add#1{%
+  \begingroup
+    \toks@\expandafter{\bm@command#1}%
+    \xdef\bm@command{\the\toks@}%
+  \endgroup
+  \bm@expand}
+\def\bm@xadd#1{%
+  \begingroup
+    \toks@\expandafter{\bm@command}%
+    \xdef\bm@command{\the\toks@#1}%
+  \endgroup
+  \bm@expand}
+\def\bm@mathaccent{%
+ \bm@changefam{}%
+ \begingroup
+ \def\bm@group##1{\endgroup\bm@xadd{\bgroup}##1\egroup}%
+ \def\bm@test@token{\endgroup\bm@test@token}%
+ \let\relax\@empty
+ \bm@xadd{\mathaccent\the\count@\space}}
+\def\bm@delimiter{%
+  \ifnum\count@>\z@
+    \bm@changefam{}%
+    \bm@changefam{000}%
+  \fi
+  \bm@xadd{\delimiter\the\count@\space}}%
+\def\bm@radical{%
+ \bm@changefam{}%
+ \bm@changefam{000}%
+ \bm@xadd{\radical\the\count@\space}}%
+\edef\bm@mchar@{\meaning\mathchar}
+\def\bm@mchar@test#1"#2"#3\@nil#4{%
+  \xdef\meaning@{#1}%
+  \ifx\meaning@\bm@mchar@
+    \count@"#2\relax
+    \bm@mathchar
+  \else
+    \ifx\bm@previous\@empty
+      \ifx\relax#4%
+        \gdef\bm@first{#4}%
+      \fi
+    \fi
+    \bm@add{#4}%
+  \fi}
+\def\bm@changefam#1{%
+  \@tempcnta\count@
+  \divide\@tempcnta"1000#1 %
+  \multiply\@tempcnta"1000#1 %
+  \advance\@tempcnta-\count@
+  \divide\@tempcnta-"100#1 %
+  \@tempcnta\bm@table
+  \ifnum\@tempcnta=\m@ne
+    \let\@tempa\bm@pmb
+  \else
+    \multiply\@tempcnta"100#1 %
+    \advance\count@\@tempcnta
+  \fi}
+\def\bm@prime{^\bgroup
+  \let\bm@prime'%
+  \def\prim@s##1\relax{##1\futurelet\@let@token\pr@m@s}%
+  \prim@s}
+\let\boldsymbol\bm
+\let\heavysymbol\hm
+\endinput
+%%
+%% End of file `bm.sty'.
\ No newline at end of file
diff --git a/jfp-paper/jfp-gtt.tex b/jfp-paper/jfp-gtt.tex
new file mode 100644
index 0000000000000000000000000000000000000000..8665fc9bc8dbdeb3982f33c1a66522b3b1c2a873
--- /dev/null
+++ b/jfp-paper/jfp-gtt.tex
@@ -0,0 +1,44 @@
+\documentclass{jfp1}
+
+\title{Gradual Type Theory}
+
+\author[M.S. New]
+       {Max S. New\\
+        Northeastern University\\
+        %% \email{maxnew@ccs.neu.edu}
+       }
+
+\author[D.R. Licata]
+       {Daniel R. Licata \\
+        Wesleyan University\\
+        %% \email{drlicata@wesleyan.edu}
+       }
+
+\author[A. Ahmed]
+       {Amal Ahmed \\
+        Northeastern University\\
+        %% \email{amal@ccs.neu.edu}
+       }
+
+\jdate{September 2001, update April 2007}
+\pubyear{2001}
+\pagerange{\pageref{firstpage}--\pageref{lastpage}}
+\doi{S0956796801004857}
+
+\newtheorem{lemma}{Lemma}[section]
+
+\begin{document}
+\label{firstpage}
+\maketitle
+
+\begin{abstract}
+  foo bar
+\end{abstract}
+
+\section{Introduction}
+
+hi
+
+\label{lastpage}
+
+\end{document}
diff --git a/jfp-paper/jfp.bst b/jfp-paper/jfp.bst
new file mode 100644
index 0000000000000000000000000000000000000000..d0fdaa0cab574114598e7d1d82924c216d4dfb56
--- /dev/null
+++ b/jfp-paper/jfp.bst
@@ -0,0 +1,1316 @@
+%  CUP Journal of Functional Programming bibliography style 
+%  v1.0, released 22nd May 1995 
+%  Copyright 1994,1995 Cambridge University Press
+
+%  This BibTeX 0.99 style file is intended for documents that use the
+%  author-date citation system.  It should be used in conjunction with the
+%  authordate1-4.sty (or equivalent) LaTeX style-option.
+%
+%  In deciding on the bibliography layout to be implemented, the following
+%  works have been consulted:
+%  1. British Standard 5605:  "Citing publications by bibliographic
+%         references", 1978.
+%  2. British Standard 1629:  "Bibliographic references", 1976.
+%     (Note:  There is now a 1989 edition.)
+%  3. "Copy-editing" by Judith Butcher, Cambridge University Press, 1981.
+%  4. "The Oxford Dictionary for Writers and Editors", Oxford University
+%         Press, 1981 (for abbreviations).
+%  5. "The Chicago Manual of Style", Chicago University Press, 1982.
+%
+%  Discretion has been used in certain matters.  In particular:
+%  - Titles are italic except when there is a "contribution title" and
+%    a "main publication title", in which case the "contribution title"
+%    is roman while the "main publication title" is italic.
+%  - When there is a PUBLISHER, it is assumed that ADDRESS contains "place of
+%    publication";  output is of the form "place-of-publication: publisher".
+%    When there is an ORGANIZATION as well as a PUBLISHER, output is of the
+%    form "place-of-publication: publisher, for organization".  Otherwise,
+%    it is assumed that ADDRESS is a postal address, and output is of the
+%    form "institution, address", "organization, address", "school, address"
+%    or "howpublished, address".
+%  - If there is a MONTH but no VOLUME or NUMBER for a journal-article, the
+%    MONTH is used on the assumption that it contains information that is
+%    equivalent to VOLUME or NUMBER.  MONTH is ignored for other documents
+%    that have a PUBLISHER, but output after YEAR for anything else.
+%  - When CHAPTER and/or PAGES are specified with INBOOK, it is assumed that
+%    these fields are being used to pick out particular pages of interest
+%    (as an alternative to using the optional [...] argument of \cite);
+%    the information is put at the very end of the entry, in line with BS 1629.
+%    When CHAPTER and/or PAGES are specified for INCOLLECTION or INPROCEEDINGS,
+%    it is assumed that the fields are being used to specify the location of
+%    the part/article of interest; the information is put before the
+%    BOOKTITLE, in line with Chicago's treatment of "parts" and "chapters".
+%  - Since "volume" can be used in various ways (see page 219 of Butcher),
+%    this file assumes that, when there is a SERIES, any VOLUME and NUMBER
+%    refer to position in the SERIES (i.e. Butcher's meaning 4).
+%    If there is a VOLUME but no SERIES, it is assumed that VOLUME refers
+%    to a volume within a particular work (i.e. Butcher's meaning 1, 2 or 3).
+%    For INPROCEEDINGS and INCOLLECTION, this information goes after the
+%    BOOKTITLE.  (If you prefer to have volume information before EDITOR,
+%    as on page 449 of Chicago, you can set TYPE = "Vol." with INCOLLECTION.)
+%
+%  This file differs from authordate1.bst, authordate3.bst and
+%  authordate4.bst in that:
+%  - Titles of journals, articles and boooks are "downstyle".  Apart from the
+%    first character, and the first character following : and white space,
+%    uppercase letters are converted to lowercase unless protected by {}.
+%  - Author's and editor's names are in roman.
+%
+%  The combination of authordate2.bst and authordate1-4.sty allows citations
+%  of the form \shortcite{bloggs-60} as well as the usual \cite{bloggs-60}.
+%  When
+%       ... \cite{bloggs-60} ... \shortcite{bloggs-60} ...
+%  appears in the input file,
+%       ... (Bloggs, 1960) ... (1960) ...
+%  appears in the final document.
+%
+%  This file was developed from apalike.bst.  It also uses code taken from
+%  acm.bst, aaai-named.bst, btxbst.doc, ieeetr.bst and siam.bst.
+%
+%                                                     David Rhead
+%                                                     Cripps Computing Centre
+%                                                     Nottingham University
+%                                                     March 1990
+%
+
+ENTRY
+  { address
+    author
+    booktitle
+    chapter
+    edition
+    editor
+    howpublished
+    institution
+    journal
+    key
+    month
+    note
+    number
+    organization
+    pages
+    publisher
+    school
+    series
+    title
+    type
+    volume
+    year
+  }
+  {}
+  { label extra.label sort.label }
+
+INTEGERS { output.state before.all mid.sentence after.sentence after.block }
+
+FUNCTION {init.state.consts}
+{ #0 'before.all :=
+  #1 'mid.sentence :=
+  #2 'after.sentence :=
+  #3 'after.block :=
+}
+
+STRINGS { s t }
+
+FUNCTION {output.nonnull}
+{ 's :=
+  output.state mid.sentence =
+    { ", " * write$ }
+    { output.state after.block =
+     { add.period$ write$
+       newline$
+       "\newblock " write$
+     }
+     { output.state before.all =
+         'write$
+         { add.period$ " " * write$ }
+       if$
+     }
+      if$
+      mid.sentence 'output.state :=
+    }
+  if$
+  s
+}
+
+FUNCTION {output}
+{ duplicate$ empty$
+    'pop$
+    'output.nonnull
+  if$
+}
+
+FUNCTION {output.check}
+{ 't :=
+  duplicate$ empty$
+    { pop$ "empty " t * " in " * cite$ * warning$ }
+    'output.nonnull
+  if$
+}
+
+FUNCTION {output.year.month.check}
+{ year empty$
+    { "empty year in " cite$ * warning$ }
+    { add.period$ write$
+      month empty$
+        { " (" year * extra.label * ")" *                   % ajw
+          after.sentence 'output.state :=
+        }
+        { " " year * extra.label * " (" * month * ")." *
+          after.sentence 'output.state :=
+        }
+      if$
+    }
+  if$
+}
+
+FUNCTION {output.year.check}
+{ year empty$
+    { "empty year in " cite$ * warning$ }
+    { add.period$ write$
+      " (" year * extra.label * ")" *                       % ajw
+      after.sentence 'output.state :=
+    }
+  if$
+}
+
+FUNCTION {output.bibitem}
+{ newline$
+  "\bibitem[" write$
+  label write$
+  "]{" write$
+  cite$ write$
+  "}" write$
+  newline$
+  ""
+  before.all 'output.state :=
+}
+
+FUNCTION {fin.entry}
+{ add.period$
+  write$
+  newline$
+}
+
+FUNCTION {new.block}
+{ output.state before.all =
+    'skip$
+    { after.block 'output.state := }
+  if$
+}
+
+FUNCTION {new.sentence}
+{ output.state after.block =
+    'skip$
+    { output.state before.all =
+        'skip$
+        { after.sentence 'output.state := }
+      if$
+    }
+  if$
+}
+
+FUNCTION {not}
+{   { #0 }
+    { #1 }
+  if$
+}
+
+FUNCTION {and}
+{   'skip$
+    { pop$ #0 }
+  if$
+}
+
+FUNCTION {or}
+{   { pop$ #1 }
+    'skip$
+  if$
+}
+
+FUNCTION {new.block.checkb}
+{ empty$
+  swap$ empty$
+  and
+    'skip$
+    'new.block
+  if$
+}
+
+FUNCTION {field.or.null}
+{ duplicate$ empty$
+    { pop$ "" }
+    'skip$
+  if$
+}
+
+FUNCTION {boldface}
+{ duplicate$ empty$
+    { pop$ "" }
+    { "{\bf " swap$ * "}" * }
+  if$
+}
+
+FUNCTION {emphasize}
+{ duplicate$ empty$
+    { pop$ "" }
+    { "{\em " swap$ * "}" * }
+  if$
+}
+
+INTEGERS { nameptr namesleft numnames }
+
+
+FUNCTION {format.names}
+{ 's :=
+  #1 'nameptr :=
+  s num.names$ 'numnames :=
+  numnames 'namesleft :=
+    { namesleft #0 > }
+    { s nameptr "{vv~}{ll}{, jj}{, ff}" format.name$ 't :=  
+      nameptr #1 >
+        { namesleft #1 >
+            { ", " * t * }
+            { t "others" =
+                { ", {\em et~al.\ }\relax" * }
+                { ", \& " * t * }                           %  Butcher, pages
+              if$                                           %  186-189.
+            }
+          if$
+        }
+        't
+      if$
+      nameptr #1 + 'nameptr :=
+      namesleft #1 - 'namesleft :=
+    }
+  while$
+}
+
+FUNCTION {format.authors}
+{ author empty$
+    { "" }
+    { author format.names }
+  if$
+}
+
+FUNCTION {format.key}
+{ empty$
+    { key field.or.null }
+    { "" }
+  if$
+}
+
+FUNCTION {format.editors}
+{ editor empty$
+    { "" }
+    { editor format.names
+      editor num.names$ #1 >                                %  Use ODWE abbrevs.
+        { " (eds)" * }                                      %  to avoid
+        { " (ed)" * }                                       %  ambiguity between
+      if$                                                   %  "editor" and
+    }                                                       %  "edition".
+  if$
+}
+
+FUNCTION {format.title}                                     %  Howells example
+{ title empty$                                              %  in BS 5605 comes
+    { "" }                                                  %  out wrong because
+    { title "t" change.case$ }                              %  Patashnik
+  if$                                                       %  capitalizes
+}                                                           %  after a colon.
+
+FUNCTION {n.dashify}
+{ 't :=
+  ""
+    { t empty$ not }
+    { t #1 #1 substring$ "-" =
+        { t #1 #2 substring$ "--" = not
+            { "--" *
+              t #2 global.max$ substring$ 't :=
+            }
+            {   { t #1 #1 substring$ "-" = }
+               { "-" *
+                 t #2 global.max$ substring$ 't :=
+               }
+              while$
+            }
+          if$
+        }
+        { t #1 #1 substring$ *
+          t #2 global.max$ substring$ 't :=
+        }
+        if$
+    }
+  while$
+}
+
+FUNCTION {format.btitle}
+{ title empty$
+   { "" }
+   { title "t" change.case$ emphasize }
+   if$
+}
+
+FUNCTION {tie.or.space.connect}
+{ duplicate$ text.length$ #3 <
+    { "~" }
+    { " " }
+  if$
+  swap$ * *
+}
+
+FUNCTION {either.or.check}
+{ empty$
+    'pop$
+    { "can't use both " swap$ * " fields in " * cite$ * warning$ }
+  if$
+}
+
+INTEGERS { multiresult }
+
+FUNCTION {multi.page.check}
+{ 't :=
+  #0 'multiresult :=
+    { multiresult not
+      t empty$ not
+      and
+    }
+    { t #1 #1 substring$
+      duplicate$ "-" =
+      swap$ duplicate$ "," =
+      swap$ "+" =
+      or or
+        { #1 'multiresult := }
+        { t #2 global.max$ substring$ 't := }
+      if$
+    }
+  while$
+  multiresult
+}
+
+FUNCTION {format.numberinseries}
+{ number empty$
+    { "" }
+    { number multi.page.check
+        { ", nos. " number n.dashify tie.or.space.connect }
+        { ", no. "  number tie.or.space.connect }
+      if$
+    }
+  if$
+}
+
+FUNCTION {booklike.series.volume.number}                    %  Chicago, pages
+{ series empty$                                             %  450-451.
+    { volume empty$
+      { " " }
+      { " Vol. " volume * }
+      if$
+    }
+    {
+      volume empty$
+        { number empty$
+            { series }
+            { series format.numberinseries * }
+          if$
+        }
+        { number empty$
+            { series ", vol. " volume * * }
+            { series ", vol. " * volume * format.numberinseries * }
+          if$
+        }
+      if$
+    }
+  if$
+}
+
+FUNCTION {incollectionlike.series.volume.number}
+{ series empty$
+    { volume empty$
+      { " " }
+      { " vol. " volume * }
+      if$
+    }
+    { new.block
+      volume empty$
+        { number empty$
+            { series }
+            { series format.numberinseries * }
+          if$
+        }
+        { number empty$
+            { series ", vol. " volume * * }
+            { series ", vol. " * volume * format.numberinseries * }
+          if$
+        }
+      if$
+    }
+  if$
+}
+
+FUNCTION {format.edition}
+{ edition empty$
+    { "" }
+    { output.state mid.sentence =
+        { edition "l" change.case$ " edn." * }
+        { edition "t" change.case$ " edn." * }
+      if$
+    }
+  if$
+}
+
+FUNCTION {format.pages}
+{ pages empty$
+    { "" }
+    { pages multi.page.check
+        { "" pages n.dashify tie.or.space.connect }
+        { "" pages tie.or.space.connect }
+      if$
+    }
+  if$
+}
+
+FUNCTION {format.pagesinbook}                               %  By the time the
+{ pages empty$                                              %  reader has read
+    { "" }                                                  %  address, pub'r,
+    { pages multi.page.check                                %  note (where the
+        { "Pages " pages n.dashify tie.or.space.connect }   %  note may end with
+        { "Page " pages tie.or.space.connect }              %  numbers), s/he
+      if$                                                   %  may not recognise
+    }                                                       %  a number-range as
+  if$                                                       %  meaning pages.
+}                                                           %  Avoid ambiguity
+                                                            %  (Butcher, p.181).
+
+FUNCTION {format.vol.num.date.pages}
+{ volume empty$
+   { month empty$
+       { "" }
+       { month }
+     if$
+   }
+    { volume boldface field.or.null
+        number empty$
+        { month empty$
+            'skip$
+            { "(" month * ")" *  * }
+          if$
+        }
+        { "(" number * ")" *  *
+            volume empty$
+            { "there's a number but no volume in " cite$ * warning$ }
+            'skip$
+          if$
+        }
+      if$
+    }
+  if$
+  pages empty$
+    'skip$
+    { duplicate$ empty$
+        { pop$ format.pages }
+        { ", " * pages n.dashify * }
+      if$
+    }
+  if$
+}
+
+FUNCTION {format.chapter.pages.inbook}
+{ chapter empty$
+    'format.pagesinbook
+    { type empty$
+        { "Chap." }
+        { type }
+      if$
+      chapter tie.or.space.connect
+      pages empty$
+        'skip$
+        { ", " * format.pagesinbook "l" change.case$ * }
+      if$
+    }
+  if$
+}
+
+FUNCTION {format.chapter.pages.incoll}
+{ chapter empty$
+    { pages empty$
+        { " " }                                             % ajw
+        { "{\em " format.pagesinbook " of:} " * * }
+      if$
+    }
+    { type empty$
+        { "{\em Chap. " chapter * }
+        { "{\em " type * " " * chapter * }
+      if$
+      pages empty$
+        { " of:} " * }
+        { ", " * format.pagesinbook "l" change.case$ " of:} " * * }
+      if$
+    }
+  if$
+}
+
+FUNCTION {format.in.ed.booktitle}                           %  Achieves effect
+{ booktitle empty$                                          %  shown in 16.51
+    { "" }                                                  %  of Chicago, at
+    { editor empty$                                         %  expense of not
+        { format.chapter.pages.incoll                       %  achieving effects
+          booktitle emphasize * }          %  shown in 16.50
+        { format.chapter.pages.incoll                       %  of Chicago, on
+          format.editors * ", " *                           %  page 189 of
+          booktitle emphasize * }          %  Butcher and in
+      if$                                                   %  4.4 of BS 1629.
+    }
+  if$
+}
+
+FUNCTION {format.thesis.type}
+{ type empty$
+    'skip$
+    { pop$
+      type "t" change.case$
+    }
+  if$
+}
+
+FUNCTION {format.tr.number}
+{ type empty$
+    { "Tech. rept."  }                                      %  ODWE abbrevs.
+    'type
+  if$
+  number empty$
+    { "t" change.case$ }
+    { number tie.or.space.connect }
+  if$
+}
+
+FUNCTION {format.addr.pub}
+{ publisher empty$
+    { "" }
+    { address empty$
+        { "" }
+        { address ": " * }
+      if$
+      publisher *
+    }
+  if$
+}
+
+FUNCTION {format.addr.pub.org}                              %  If there's an
+{ address empty$                                            %  an organization
+  { publisher * ", for " * organization * }                 %  and a publisher
+  { address ": " * publisher * ", for " * organization * }  %  too.
+  if$
+}
+
+FUNCTION {format.addr.inst}
+{ address empty$
+  { institution empty$
+    { "" }
+    { institution }
+    if$
+  }
+  { institution empty$
+    { "" }
+    { institution ", " * }
+    if$
+    address *
+  }
+  if$
+}
+
+FUNCTION {format.addr.org}
+{ address empty$
+  { organization empty$
+    { "" }
+    { organization }
+    if$
+  }
+  { organization empty$
+    { "" }
+    { organization ", " * }
+    if$
+    address *
+  }
+  if$
+}
+
+FUNCTION {format.article.crossref}
+{ "{\em In:}"
+  " \cite{" * crossref * "}" *
+}
+
+FUNCTION {format.book.crossref}
+{ volume empty$
+    { "empty volume in " cite$ * "'s crossref of " * crossref * warning$
+      "{\em In:}"
+    }
+    { " Vol." volume tie.or.space.connect
+      " of " *
+    }
+  if$
+  "\cite{" * crossref * "}" *
+}
+
+FUNCTION {format.incoll.inproc.crossref}
+{ "{\em In:}"
+  " \cite{" * crossref * "}" *
+}
+
+FUNCTION {article}
+{ output.bibitem
+  format.authors "author" output.check
+  author format.key output
+  output.year.check
+  new.block
+  format.title "title" output.check
+  new.block
+  crossref missing$
+    { journal "t" change.case$ emphasize
+      "journal" output.check
+      format.vol.num.date.pages output
+    }
+    { format.article.crossref output.nonnull
+      format.pages output
+    }
+  if$
+  new.block
+  note output
+  fin.entry
+}
+
+FUNCTION {book}
+{ output.bibitem
+  author empty$
+    { format.editors "author and editor" output.check
+      editor format.key output
+    }
+    { format.authors output.nonnull
+      crossref missing$
+        { "author and editor" editor either.or.check }
+        'skip$
+      if$
+    }
+  if$
+  output.year.check
+  new.block
+  format.btitle "title" output.check
+  crossref missing$
+    { new.sentence
+      format.edition output
+      new.block
+      booklike.series.volume.number output
+      new.block
+      format.addr.pub "publisher" output.check
+    }
+    { new.block
+      format.book.crossref output.nonnull
+    }
+  if$
+  new.block
+  note output
+  fin.entry
+}
+
+FUNCTION {booklet}
+{ output.bibitem
+  format.authors output
+  author format.key output
+  output.year.month.check
+  new.block
+  format.btitle "title" output.check
+  new.block
+  howpublished output
+  address output
+  new.block
+  note output
+  fin.entry
+}
+
+FUNCTION {inbook}
+{ output.bibitem
+  author empty$
+    { format.editors "author and editor" output.check
+      editor format.key output
+    }
+    { format.authors output.nonnull
+      crossref missing$
+        { "author and editor" editor either.or.check }
+        'skip$
+      if$
+    }
+  if$
+  output.year.check
+  new.block
+  format.btitle "title" output.check
+  crossref missing$
+    { new.sentence
+      format.edition output
+      new.block
+      booklike.series.volume.number output
+      new.block
+      format.addr.pub "publisher" output.check
+    }
+    { new.block
+      format.book.crossref output.nonnull
+    }
+  if$
+  new.block
+  note output
+  new.block                                                 %  BS 1629 (rather
+  format.chapter.pages.inbook "chapter and pages" output.check
+  fin.entry                                                 %  than Chicago,
+}                                                           %  p. 451)
+
+FUNCTION {incollection}
+{ output.bibitem
+  author empty$
+    { format.editors "editor" output.check
+      editor format.key output             }
+    { format.authors "author" output.check
+      author format.key output             }
+  if$
+  output.year.check
+  new.block
+  format.title "title" output.check
+  new.block
+  crossref missing$                                         %  Chapter and/or
+    { format.in.ed.booktitle output                         %  page numbers can
+      format.edition output                                 %  come out via this
+      incollectionlike.series.volume.number output          %  route, too.
+      new.block
+      format.addr.pub "publisher" output.check
+    }
+    { format.incoll.inproc.crossref output.nonnull
+      new.block
+    }
+  if$
+  new.block
+  note output
+  fin.entry
+}
+
+FUNCTION {inproceedings}
+{ output.bibitem
+  format.authors "author" output.check
+  author format.key output
+  publisher empty$
+    { output.year.month.check }
+    { output.year.check }
+  if$
+  new.block
+  format.title "title" output.check
+  new.block
+  crossref missing$
+    { format.in.ed.booktitle "booktitle" output.check
+      incollectionlike.series.volume.number output
+      new.block
+      publisher empty$
+      {
+        organization empty$
+        'skip$
+        { format.addr.org output }
+        if$
+      }
+      {
+        organization empty$
+        { format.addr.pub output }
+        { format.addr.pub.org output }
+        if$
+      }
+      if$
+    }
+    { format.incoll.inproc.crossref output.nonnull
+    }
+  if$
+  new.block
+  note output
+  fin.entry
+}
+
+FUNCTION {conference} { inproceedings }
+
+FUNCTION {manual}
+{ output.bibitem
+  format.authors output
+  author format.key output
+  output.year.month.check
+  new.block
+  format.btitle "title" output.check
+  new.sentence
+  format.edition output
+  new.block
+  organization address new.block.checkb
+  format.addr.org output
+  new.block
+  note output
+  fin.entry
+}
+
+FUNCTION {mastersthesis}
+{ output.bibitem
+  format.authors "author" output.check
+  author format.key output
+  output.year.month.check
+  new.block
+  format.btitle "title" output.check
+  new.block
+  "M.Phil. thesis" format.thesis.type output.nonnull        %  ODWE abbrev.
+  school "school" output.check
+  address output
+  new.block
+  note output
+  fin.entry
+}
+
+FUNCTION {misc}
+{ output.bibitem
+  format.authors output
+  author format.key output
+  output.year.month.check
+  new.block
+  format.btitle output
+  new.block
+  howpublished output
+  new.block
+  note output
+  fin.entry
+}
+
+FUNCTION {phdthesis}
+{ output.bibitem
+  format.authors "author" output.check
+  author format.key output
+  output.year.month.check
+  new.block
+  format.btitle "title" output.check
+  new.block
+  "Ph.D. thesis" format.thesis.type output.nonnull          %  Butcher,
+  school "school" output.check                              %  page 174.
+  address output
+  new.block
+  note output
+  fin.entry
+}
+
+FUNCTION {proceedings}
+{ output.bibitem
+  format.editors "author and editor" output.check
+  editor format.key output
+  publisher empty$
+    { output.year.month.check }
+    { output.year.check }
+  if$
+  new.block
+  format.btitle "title" output.check
+  new.block
+  booklike.series.volume.number output
+      new.block
+      publisher empty$
+      {
+        organization empty$
+        'skip$
+        { format.addr.org output }
+        if$
+      }
+      {
+        organization empty$
+        { format.addr.pub output }
+        { format.addr.pub.org output }
+        if$
+      }
+      if$
+  new.block
+  note output
+  fin.entry
+}
+
+FUNCTION {techreport}
+{ output.bibitem
+  format.authors "author" output.check
+  author format.key output
+  output.year.month.check
+  new.block
+  format.btitle "title" output.check
+  new.block
+  format.tr.number output.nonnull
+  new.sentence
+  format.addr.inst "institution" output.check
+  new.block
+  note output
+  fin.entry
+}
+
+FUNCTION {unpublished}
+{ output.bibitem
+  format.authors "author" output.check
+  author format.key output
+  output.year.month.check
+  new.block
+  format.btitle "title" output.check
+  new.block
+  note "note" output.check
+  fin.entry
+}
+
+FUNCTION {default.type} { misc }
+
+MACRO {jan} {"Jan."}                                        %  ODWE, "months", &
+                                                            %  Chicago, p. 383.
+MACRO {feb} {"Feb."}
+
+MACRO {mar} {"Mar."}
+
+MACRO {apr} {"Apr."}
+
+MACRO {may} {"May"}
+
+MACRO {jun} {"June"}
+
+MACRO {jul} {"July"}
+
+MACRO {aug} {"Aug."}
+
+MACRO {sep} {"Sept."}
+
+MACRO {oct} {"Oct."}
+
+MACRO {nov} {"Nov."}
+
+MACRO {dec} {"Dec."}
+
+MACRO {acmcs} {"ACM Computing Surveys"}
+
+MACRO {acta} {"Acta Informatica"}
+
+MACRO {cacm} {"Communications of the ACM"}
+
+MACRO {ibmjrd} {"IBM Journal of Research and Development"}
+
+MACRO {ibmsj} {"IBM Systems Journal"}
+
+MACRO {ieeese} {"IEEE Transactions on Software Engineering"}
+
+MACRO {ieeetc} {"IEEE Transactions on Computers"}
+
+MACRO {ieeetcad}
+ {"IEEE Transactions on Computer-Aided Design of Integrated Circuits"}
+
+MACRO {ipl} {"Information Processing Letters"}
+
+MACRO {jacm} {"Journal of the ACM"}
+
+MACRO {jcss} {"Journal of Computer and System Sciences"}
+
+MACRO {scp} {"Science of Computer Programming"}
+
+MACRO {sicomp} {"SIAM Journal on Computing"}
+
+MACRO {tocs} {"ACM Transactions on Computer Systems"}
+
+MACRO {tods} {"ACM Transactions on Database Systems"}
+
+MACRO {tog} {"ACM Transactions on Graphics"}
+
+MACRO {toms} {"ACM Transactions on Mathematical Software"}
+
+MACRO {toois} {"ACM Transactions on Office Information Systems"}
+
+MACRO {toplas} {"ACM Transactions on Programming Languages and Systems"}
+
+MACRO {tcs} {"Theoretical Computer Science"}
+
+READ
+
+FUNCTION {sortify}
+{ purify$
+  "l" change.case$
+}
+
+INTEGERS { len }
+
+FUNCTION {chop.word}
+{ 's :=
+  'len :=
+  s #1 len substring$ =
+    { s len #1 + global.max$ substring$ }
+    's
+  if$
+}
+
+FUNCTION {format.lab.names}
+{ 's :=
+  s #1 "{vv~}{ll}" format.name$
+  s num.names$ duplicate$
+  #2 >
+%%%%%    { pop$ " {\em et~al.\ }\relax" * }
+    { pop$ " {\em et~al.}\relax" * }
+    { #2 <
+        'skip$
+        { s #2 "{ff }{vv }{ll}{ jj}" format.name$ "others" =
+            { " {\em et~al.\ }\relax" * }
+            { " \& " * s #2 "{vv~}{ll}" format.name$ * }
+          if$
+        }
+      if$
+    }
+  if$
+}
+
+FUNCTION {author.key.label}
+{ author empty$
+    { key empty$
+        { cite$ #1 #3 substring$ }
+        'key
+      if$
+    }
+    { author format.lab.names }
+  if$
+}
+
+FUNCTION {author.editor.key.label}
+{ author empty$
+    { editor empty$
+        { key empty$
+            { cite$ #1 #3 substring$ }
+            'key
+          if$
+        }
+        { editor format.lab.names }
+      if$
+    }
+    { author format.lab.names }
+  if$
+}
+
+FUNCTION {editor.key.label}
+{ editor empty$
+    { key empty$
+        { cite$ #1 #3 substring$ }
+        'key
+      if$
+    }
+    { editor format.lab.names }
+  if$
+}
+
+FUNCTION {calc.label}
+  { type$ "book" =
+    type$ "inbook" =
+    type$ "incollection" =                                  %  For sensible
+  or or                                                     %  treatment of
+    'author.editor.key.label                                %  Singer in
+    { type$ "proceedings" =                                 %  BS 1629.
+        'editor.key.label
+        'author.key.label
+      if$
+    }
+  if$
+  duplicate$
+  year empty$
+  {
+    "\protect\citename{" swap$ * ", }" *
+    "n.d." * 'label :=                                      %  Chicago,
+  }                                                         %  page 457.
+  {
+    "\protect\citename{" swap$ * ", }" *
+    year
+    *
+    'label :=
+  }
+  if$
+  year field.or.null purify$ *
+  sortify 'sort.label :=
+}
+
+
+FUNCTION {sort.format.names}                                %  To produce the
+{ 's :=                                                     %  order of entries
+  #1 'nameptr :=                                            %  specified in item
+  ""                                                        %  (3) on page 187
+  s num.names$ 'numnames :=                                 %  of Butcher.
+  numnames 'namesleft :=
+    { namesleft #0 > nameptr #3 < and }                     %  Only 1st 2 names
+    { nameptr #1 >                                          %  matter for
+        { "   " * }                                         %  sorting.
+        'skip$
+      if$                                                   %  Anything that's
+      nameptr #2 = numnames #2 > and                        %  "et al" goes
+      { "zzzzz" * }                                         %  after works by 2
+      {                                                     %  authors.
+        s nameptr "{vv{ } }{ll{ }}{  ff{ }}{  jj{ }}" format.name$ 't :=
+        nameptr numnames = t "others" = and
+          { "zzzzz" * }
+          { t sortify * }
+        if$
+      }
+      if$
+      nameptr #1 + 'nameptr :=
+      namesleft #1 - 'namesleft :=
+    }
+  while$
+}
+
+FUNCTION {sort.format.title}
+{ 't :=
+  "A " #2
+    "An " #3
+      "The " #4 t chop.word
+    chop.word
+  chop.word
+  sortify
+  #1 global.max$ substring$
+}
+
+FUNCTION {author.sort}
+{ author empty$
+    { key empty$
+        { "to sort, need author or key in " cite$ * warning$
+          ""
+        }
+        { key sortify }
+      if$
+    }
+    { author sort.format.names }
+  if$
+}
+
+FUNCTION {author.editor.sort}
+{ author empty$
+    { editor empty$
+        { key empty$
+            { "to sort, need author, editor, or key in " cite$ * warning$
+              ""
+            }
+            { key sortify }
+          if$
+        }
+        { editor sort.format.names }
+      if$
+    }
+    { author sort.format.names }
+  if$
+}
+
+FUNCTION {editor.sort}
+{ editor empty$
+    { key empty$
+        { "to sort, need editor or key in " cite$ * warning$
+          ""
+        }
+        { key sortify }
+      if$
+    }
+    { editor sort.format.names }
+  if$
+}
+
+FUNCTION {presort}                                          %  Two sorting
+{ calc.label                                                %  passes, from
+  label sortify                                             %  apalike.bst.
+  "    "
+  *
+  type$ "book" =
+  type$ "inbook" =
+  type$ "incollection" =                                    %  For Singer
+  or or                                                     %  in BS 1629.
+    'author.editor.sort
+    { type$ "proceedings" =
+        'editor.sort
+        'author.sort
+      if$
+    }
+  if$
+  #1 entry.max$ substring$
+  'sort.label :=
+  sort.label
+  *
+  "    "
+  *
+  title field.or.null
+  sort.format.title
+  *
+  #1 entry.max$ substring$
+  'sort.key$ :=
+}
+
+ITERATE {presort}
+
+SORT
+
+STRINGS { last.label next.extra }
+
+INTEGERS { last.extra.num }
+
+FUNCTION {initialize.extra.label.stuff}
+{ #0 int.to.chr$ 'last.label :=
+  "" 'next.extra :=
+  #0 'last.extra.num :=
+}
+
+FUNCTION {forward.pass}
+{ last.label label =
+    { last.extra.num #1 + 'last.extra.num :=
+      last.extra.num int.to.chr$ 'extra.label :=
+    }
+    { "a" chr.to.int$ 'last.extra.num :=
+      "" 'extra.label :=
+      label 'last.label :=
+    }
+  if$
+}
+
+FUNCTION {reverse.pass}
+{ next.extra "b" =
+    { "a" 'extra.label := }
+    'skip$
+  if$                                                       %  Code needed here
+                                                            %  if \citeauthor
+                                                            %  and \citeyear
+  label extra.label * 'label :=                             %  were supported.
+  extra.label 'next.extra :=
+}
+
+EXECUTE {initialize.extra.label.stuff}
+
+ITERATE {forward.pass}
+
+REVERSE {reverse.pass}
+
+FUNCTION {bib.sort.order}
+{ sort.label
+  "    "
+  *
+  year field.or.null sortify
+  *
+  "    "
+  *
+  title field.or.null
+  sort.format.title
+  *
+  #1 entry.max$ substring$
+  'sort.key$ :=
+}
+
+ITERATE {bib.sort.order}
+
+SORT
+
+FUNCTION {begin.bib}
+{ preamble$ empty$
+    'skip$
+    { preamble$ write$ newline$ }
+  if$
+  "\begin{thebibliography}{}" write$ newline$
+}
+
+EXECUTE {begin.bib}
+
+EXECUTE {init.state.consts}
+
+ITERATE {call.type$}
+
+FUNCTION {end.bib}
+{ newline$
+  "\end{thebibliography}" write$ newline$
+}
+
+EXECUTE {end.bib}
\ No newline at end of file
diff --git a/jfp-paper/jfp1.cls b/jfp-paper/jfp1.cls
new file mode 100644
index 0000000000000000000000000000000000000000..ca9c813ad6328e666112182c2e9a2288e2edd27a
--- /dev/null
+++ b/jfp-paper/jfp1.cls
@@ -0,0 +1,1894 @@
+%%
+%% This is file `jfp.cls'
+%%
+%% CUP Journal of Functional Programming document class
+%% Copyright 2001 Cambridge University Press
+%%
+%% by Mark A. Reed
+%%   based on JFP.STY v1.24.
+%%
+%% Incorporating parts of authordate.sty
+%%    by David Rhead, Cripps Computing Centre (Feb 1990).
+%%
+%% Bugs (in the case of unchanged files) should be reported to
+%% texline@cambridge.org
+%%
+%% This software may only be used in the preparation of journal articles
+%% or books or parts of books to be published by Cambridge University Press.
+%% Any other use constitutes an infringement of copyright.
+%%
+%% \CharacterTable
+%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+
+\NeedsTeXFormat{LaTeX2e}[1997/12/01]
+\ProvidesClass{jfp}[2001/09/27 v1.02 Journal of Functional Programming
+  ^^Jdocument class]
+
+\newif\ifprodtf
+\newif\ifonepage\global\onepagefalse%
+\newif\ifonline
+\onlinefalse
+%
+\newif\ifcompmod\global\compmodfalse
+%
+\newif\ifincremental\incrementalfalse
+%%
+\newif\ifindex
+\newif\ifdraft
+\newif\ifnoquery
+\newif\ifbookreview
+\newif\ifsptitle
+%
+\newif\ifsplissue
+\global\splissuefalse
+%
+\newif\ifprinter
+\newdimen\draftrule
+\newdimen\trimrule
+\global\draftrule0pt
+\trimrule.1pt
+%
+\newdimen\trimwidth
+\newdimen\trimheight
+\newdimen\typewidth
+\newdimen\typeheight
+
+\newdimen\tempdimen
+\newdimen\normaltextheight
+\newskip\normalbaselineskip
+\newdimen\blindfoliodrop
+\newif\ifprinter
+\global\printerfalse
+%%
+\DeclareOption{compmod}{\compmodtrue}
+%
+\DeclareOption{splissue}{\splissuetrue}
+%
+%
+\DeclareOption{incremental}{\incrementaltrue}
+\DeclareOption{index}{\indextrue}
+\DeclareOption{bookreview}{\bookreviewtrue}
+\DeclareOption{noquery}{\noquerytrue}
+\DeclareOption{oneside}{\relax}
+\DeclareOption{twoside}{\@twosidetrue \@mparswitchtrue}
+\DeclareOption{draft}{\draftrule.5pt\setlength\overfullrule{5\p@}}
+\DeclareOption{final}{\setlength\overfullrule{\z@}}
+\DeclareOption{onecolumn}{\@twocolumnfalse}
+\DeclareOption{onepage}{\global\onepagetrue}
+\DeclareOption{twocolumn}{\relax}
+\DeclareOption{titlepage}{\relax}
+\DeclareOption{notitlepage}{\relax}
+\DeclareOption{leqno}{\relax}
+\DeclareOption{fleqn}{\relax}
+\DeclareOption{prodtf}{\prodtftrue}
+\DeclareOption{sptitle}{\sptitletrue}
+\DeclareOption{printer}{\printertrue}
+\DeclareOption{online}{\onlinetrue}
+%
+\ExecuteOptions{twoside,final,onecolumn}
+\ProcessOptions\relax
+
+\newif\ifCUPmtlplainloaded
+%% \ifprodtf
+%%   \CUPmtlplainloadedtrue
+%%   \RequirePackage{CUPTimes,jfp2esym}
+%% %  \RequirePackage{Times,jfp2esym} %%% TB
+%% \fi
+%%%%%%%%%%%%%%%%
+%
+\def\trkdefault{trk}% All trk
+\DeclareRobustCommand\trkshape
+        {\not@math@alphabet\trkshape\mathrm
+         \fontshape\trkdefault\selectfont}
+%
+\def\spchapterfont{\fontsize{18}{21}\selectfont}%\trkshape}
+\def\subtitlefont{\normalfont\fontsize{12}{14}\selectfont\itshape}%
+%
+\def\splissuefont{\fontsize{12}{14}\itshape\selectfont}%\trkshape}
+%
+\DeclareFontFamily{OT1}{mtr}{}
+\DeclareFontShape{OT1}{mtr}{m}{n}{<->mtr10}{}
+\DeclareFontShape{OT1}{mtr}{m}{trk}{<->mtr10[track+140]}{}
+\DeclareFontShape{OT1}{mtr}{m}{sl}{<->mtsl10}{}
+\DeclareFontShape{OT1}{mtr}{m}{it}{<->mtti10}{}
+\DeclareFontShape{OT1}{mtr}{m}{sc}{<->mtcsc10}{}
+%
+% Warning: please note that the upright shape below is
+%          used for the \pounds symbol of LaTeX. So this
+%          font definition shouldn't be removed.
+%
+\DeclareFontShape{OT1}{mtr}{m}{ui}{<->mtu10}{}
+%
+%%%%%%% bold series
+\DeclareFontShape{OT1}{mtr}{b}{n}{<->sub * cmr/b/n}{}
+%
+%%%%%%%% bold extended series
+\DeclareFontShape{OT1}{mtr}{bx}{n}{<->mtbx10}{}
+\DeclareFontShape{OT1}{mtr}{bx}{sl}{<->mtbxsl10}{}
+\DeclareFontShape{OT1}{mtr}{bx}{it}{<->mtbxti10}{}
+%
+% Again this is necessary for a correct \pounds symbol in
+% the cmr fonts Hopefully the dc/ec font layout will take
+% over soon.
+%
+\DeclareFontShape{OT1}{mtr}{bx}{ui}{<->ssub * mtr/m/ui}{}
+%
+%%%%% For mathfrak ... updated on 26th of April 2006
+%
+\DeclareFontFamily{U}{eufa}{}%
+\DeclareFontShape{U}{eufa}{m}{n}{<-6>eufm5<6-8>eufm7<8->eufm10}{}%
+\DeclareFontShape{U}{eufa}{b}{n}{<-6>eufb5<6-8>eufb7<8->eufb10}{}%
+%
+%%\newcommand{\mathfrak}[1]{{\protect\pmathfrak#1}}
+%%\newcommand{\pmathfrak}{\@fontswitch{\relax}{\mfraknew}}
+\DeclareMathAlphabet\mfraknew{U}{eufa}{m}{n}
+\SetMathAlphabet\mfraknew{normal}{U}{eufa}{m}{n}
+\SetMathAlphabet\mfraknew{bold}{U}{eufa}{b}{n}
+%%%%
+
+%%%%%%%%%%%%%%%%
+\setlength\lineskip{1\p@}
+\setlength\normallineskip{1\p@}
+\renewcommand\baselinestretch{}
+
+\renewcommand\normalsize{%
+\ifbookreview
+\@setfontsize\small\@ixpt{11}%
+\else
+\@setfontsize\normalsize\@xpt{13}%
+\fi
+  \abovedisplayskip 6.5\p@ \@plus 1\p@ \@minus 1\p@
+  \belowdisplayskip \abovedisplayskip
+  \abovedisplayshortskip 3\p@ \@plus 1\p@
+  \belowdisplayshortskip \abovedisplayshortskip
+  \let\@listi\@listI}
+
+\normalsize
+
+\newcommand\small{%
+ \@setfontsize\small\@ixpt{11}%
+  \abovedisplayskip 6\p@ \@plus 1\p@ \@minus 1\p@
+  \belowdisplayskip \abovedisplayskip
+  \abovedisplayshortskip 3\p@ \@plus 1\p@
+  \belowdisplayshortskip \abovedisplayshortskip
+  \def\@listi{\leftmargin\leftmargini
+    \topsep 6\p@ \@plus 1\p@ \@minus 1\p@
+    \parsep \z@ \itemsep \parsep}%
+}
+
+\newcommand\footnotesize{%
+  \@setfontsize\footnotesize\@ixpt\@xpt
+  \abovedisplayskip 5\p@ \@plus 1\p@ \@minus 1\p@
+  \belowdisplayskip \abovedisplayskip
+  \abovedisplayshortskip \z@ \@plus 1\p@
+  \belowdisplayshortskip \abovedisplayshortskip
+  \def\@listi{\leftmargin\leftmargini
+    \topsep 4.5\p@ \@plus 1\p@ \@minus 1\p@
+    \parsep \z@ \itemsep \parsep}%
+}
+
+\newcommand\scriptsize{\@setfontsize\scriptsize\@viiipt\@ixpt}
+\newcommand\tiny{\@setfontsize\tiny\@vpt\@vipt}
+\newcommand\large{\@setfontsize\large\@xiipt{14}}
+\newcommand\Large{\@setfontsize\Large\@xvpt{18}}
+\ifprodtf
+  \newcommand\LARGE{\@setfontsize\LARGE{19}{21}}%
+\else
+  \newcommand\LARGE{\@setfontsize\LARGE{18}{21}}%
+\fi
+\newcommand\huge{\@setfontsize\huge\@xxpt{25}}
+\newcommand\Huge{\@setfontsize\Huge\@xxvpt{30}}
+%
+\def\sluglinefont{\fontsize{7.5}{10}\selectfont}
+%
+\newcommand\affilsize{\@setfontsize\affilsize\@viiipt\@xpt}
+\newcommand\onlineaffilsize{\@setfontsize\affilsize\@viipt\@ixpt}
+\let\authorsize\normalsize
+
+\DeclareOldFontCommand{\rm}{\normalfont\rmfamily}{\mathrm}
+\DeclareOldFontCommand{\sf}{\normalfont\sffamily}{\mathsf}
+\DeclareOldFontCommand{\tt}{\normalfont\ttfamily}{\mathtt}
+\DeclareOldFontCommand{\bf}{\normalfont\bfseries}{\mathbf}
+\DeclareOldFontCommand{\it}{\normalfont\itshape}{\mathit}
+\DeclareOldFontCommand{\sl}{\normalfont\slshape}{\@nomath\sl}
+\DeclareOldFontCommand{\sc}{\normalfont\scshape}{\@nomath\sc}
+\DeclareRobustCommand*\cal{\@fontswitch\relax\mathcal}
+\DeclareRobustCommand*\mit{\@fontswitch\relax\mathnormal}
+
+  \setlength\topmargin{11mm}
+\setlength\trimheight{247mm}
+\setlength\trimwidth{174mm}
+%
+\setlength\typeheight{50.5pc}
+\setlength\typewidth{30pc}
+
+\setlength\marginparwidth{2.0cm}
+\setlength\marginparsep{10\p@}
+
+\setlength\headheight{6\p@}
+\setlength\headsep{18\p@}
+\setlength\topskip{6\p@}
+\setlength\footskip{26\p@}
+
+\setlength\textheight{48.5pc}
+\addtolength\textheight{-8.8pt}
+\addtolength\textheight{\topskip}
+\setlength\normaltextheight{\textheight}
+
+\setlength\textwidth{30pc}
+\setlength\columnsep{10\p@}
+\setlength\columnseprule{\z@}
+
+\setlength\oddsidemargin{21mm}%5pc}
+\setlength\evensidemargin\trimwidth
+\addtolength\evensidemargin{-\textwidth}
+\addtolength\evensidemargin{-\oddsidemargin}
+
+\setlength\footnotesep{\z@}
+\setlength{\skip\footins}{19.5\p@ \@plus 12\p@ \@minus 1\p@}
+
+\setlength\floatsep{13\p@ \@plus 6.5\p@ \@minus 1\p@}
+\setlength\textfloatsep{15\p@ \@plus 4.5\p@ \@minus 3\p@}
+\setlength\intextsep{13\p@ \@plus 6.5\p@ \@minus 2\p@}
+\setlength\dblfloatsep{13\p@ \@plus 6.5\p@ \@minus 2\p@}
+\setlength\dbltextfloatsep{15\p@ \@plus 4.5\p@ \@minus 3\p@}
+\setlength\@fptop{\z@ \@plus 0fil}
+\setlength\@fpsep{13\p@ \@plus 0fil}
+\setlength\@fpbot{\z@ \@plus 3fil}
+\setlength\@dblfptop{\z@ \@plus 0fil}
+\setlength\@dblfpsep{13\p@ \@plus 0fil}
+\setlength\@dblfpbot{\z@ \@plus 3fil}
+\setlength\marginparpush{5\p@}
+
+\setlength\parskip{\z@}% \@plus .3\p@}
+\setlength\parindent{10pt}
+\setlength\partopsep{\z@ \@plus 1\p@}
+\@lowpenalty   51
+\@medpenalty  151
+\@highpenalty 301
+\@beginparpenalty -\@lowpenalty
+\@endparpenalty -\@lowpenalty
+\@itempenalty -\@lowpenalty
+\clubpenalty\@M%z@
+\widowpenalty\@M
+\hyphenpenalty8000
+
+%
+\def\cleardoublepage{\clearpage\if@twoside \ifodd\c@page\else
+    \hbox{}\thispagestyle{empty}\newpage\if@twocolumn\hbox{}\newpage\fi\fi\fi}
+%
+\newcommand\partname{Part}
+\newcommand\part{\par\addvspace{4ex}\@afterindentfalse \secdef\@part\@spart}
+
+\def\@part[#1]#2{%
+  \ifnum \c@secnumdepth >\m@ne
+    \refstepcounter{part}%
+    \addcontentsline{toc}{part}{\partname\ \thepart: #1}%
+  \else
+    \addcontentsline{toc}{part}{#1}%
+  \fi
+  {\parindent \z@ \centering
+   \ifnum \c@secnumdepth >\m@ne
+     \normalfont\large\rmfamily \MakeUppercase{\partname}\ %
+     \ifcase\thepart \or ONE \or TWO \or THREE \or FOUR \or FIVE
+     \or SIX \or SEVEN \or EIGHT \or NINE \or TEN \else \fi
+     \par \nobreak
+   \fi
+   \normalfont\LARGE\rmfamily #2 \markboth{}{}\par}%
+   \nobreak \vskip 3ex \@afterheading
+}
+
+\def\@spart#1{%
+  {\parindent \z@ \centering\normalfont\LARGE\rmfamily #1\par}%
+  \nobreak \vskip 3ex \@afterheading
+}
+
+\newcommand\section{%
+  \@startsection {section}{1}{\z@}%
+    {-19.5\p@ \@plus -6.5\p@ \@minus -3.25\p@}%
+    {6.5\p@ \@plus \z@ \@minus 1\p@}
+    {\normalfont\normalsize\bfseries\centering}%
+}
+
+\newcommand\subsection{%
+  \@startsection{subsection}{2}{\z@}
+    {-19.5\p@ \@plus -3.25\p@ \@minus -3.25\p@}
+    {6.5\p@ \@plus \z@ \@minus 1\p@}
+    {\normalfont\normalsize\bfseries\itshape\centering}%
+}
+
+\newcommand\subsubsection{%
+  \@startsection{subsubsection}{3}{\z@}
+    {-19.5\p@ \@plus -3.25\p@ \@minus -3.25\p@}
+    {6.5\p@ \@plus \z@ \@minus 1\p@}
+    {\normalfont\normalsize\itshape\centering}%
+}
+
+\newcommand\paragraph{%
+  \@startsection{paragraph}{4}{\z@}
+    {-13\p@ \@plus -1.5\p@ \@minus -1.5\p@}
+    {-0.5em}
+    {\normalfont\normalsize\bfseries\raggedright}%
+}
+
+\newcommand\subparagraph{%
+  \@startsection{subparagraph}{4}{\parindent}
+    {-13\p@ \@plus -3.25\p@ \@minus -3.25\p@}
+    {-0.5em}
+    {\normalfont\normalsize\rmfamily\raggedright}%
+}
+
+\def\@seccntformat#1{\csname the#1\endcsname\hskip5pt}% 
+
+\newcommand\appendixname{Appendix}
+
+\newcommand\appendix{\par
+  \@addtoreset{equation}{section}%
+  \@addtoreset{figure}{section}%
+  \@addtoreset{table}{section}%
+  \setcounter{section}\z@
+  \renewcommand\thesection{\@Alph\c@section}%
+  \renewcommand\theequation{\thesection\,\@arabic\c@equation}%
+  \renewcommand\thefigure{\thesection\,\@arabic\c@figure}%
+  \renewcommand\thetable{\thesection\,\@arabic\c@table}%
+}
+
+\setcounter{secnumdepth}{3}
+
+\newcounter{part}
+\newcounter{section}
+\newcounter{subsection}[section]
+\newcounter{subsubsection}[subsection]
+\newcounter{paragraph}[subsubsection]
+\newcounter{subparagraph}[paragraph]
+\renewcommand\thepart          {\@arabic\c@part}
+\renewcommand\thesection       {\@arabic\c@section}
+\renewcommand\thesubsection    {\thesection.\@arabic\c@subsection}
+\renewcommand\thesubsubsection {\thesubsection.\@arabic\c@subsubsection}
+\renewcommand\theparagraph     {\thesubsubsection.\@arabic\c@paragraph}
+\renewcommand\thesubparagraph  {\theparagraph.\@arabic\c@subparagraph}
+
+\newskip\@leftskip  \@leftskip=\z@
+
+\setlength\leftmargini   {13pt}
+\setlength\leftmarginii  {15.2pt}
+\setlength\leftmarginiii {1.5em}
+\setlength\leftmarginiv  {1.5em}
+\setlength\leftmarginv   {1em}
+\setlength\leftmarginvi  {1em}
+\setlength\leftmargin    {\leftmargini}
+\setlength\labelsep      {5\p@}
+\setlength\labelwidth    {\leftmargini}
+\addtolength\labelwidth  {-\labelsep}
+
+\newcommand\makeRLlabel[1]{\rlap{#1}\hss}
+\newcommand\makeRRlabel[1]{\hss\llap{#1}}
+
+\def\@listI{\leftmargin\leftmargini\advance\leftmargin11.5pt
+  \parsep \z@ \topsep 6.5\p@ \@plus 3\p@ \@minus 3\p@
+  \itemsep \z@ \@plus 1\p@ \@minus 1\p@
+  \let\makelabel\makeRLlabel}
+
+\def\@listii{\leftmargin\leftmarginii
+  \labelwidth\leftmarginii
+  \advance\labelwidth-\labelsep
+  \topsep 3\p@ \@plus 1\p@ \@minus 1\p@
+  \parsep \z@ \itemsep \parsep
+  \let\makelabel\makeRLlabel}
+
+\def\@listiii{\leftmargin\leftmarginiii
+  \labelwidth\leftmarginiii
+  \advance\labelwidth-\labelsep
+  \topsep 3\p@ \@plus 1\p@ \@minus 1\p@
+  \parsep \z@ \partopsep \z@
+  \itemsep \topsep
+  \let\makelabel\makeRLlabel}
+
+\def\@listiv{\leftmargin\leftmarginiv
+  \labelwidth\leftmarginiv
+  \advance\labelwidth-\labelsep
+  \let\makelabel\makeRLlabel}
+
+\def\@listv{\leftmargin\leftmarginv
+  \labelwidth\leftmarginv
+  \advance\labelwidth-\labelsep
+  \let\makelabel\makeRLlabel}
+
+\def\@listvi{\leftmargin\leftmarginvi
+  \labelwidth\leftmarginvi
+  \advance\labelwidth-\labelsep
+  \let\makelabel\makeRLlabel}
+
+\let\@listi\@listI
+\@listi
+
+\def\itemize{% FROM LATEX.LTX
+  \ifnum \@itemdepth >\thr@@ \@toodeep\else
+     \advance\@itemdepth \@ne
+     \edef\@itemitem{labelitem\romannumeral\the\@itemdepth}%
+     \expandafter
+     \list
+       \csname\@itemitem\endcsname
+       {\let\makelabel\makeRRlabel\advance\itemindent0pt\advance\leftmargin.5pt}%
+  \fi
+}
+
+\newif\ifhyphen\global\hyphenfalse
+
+\newcommand\labelitemi{\ifhyphen \normalfont\bfseries ---\else
+$\m@th\bullet$\fi}
+
+%\newcommand\labelitemi{$\m@th\bullet$}
+\newcommand\labelitemii{\normalfont\bfseries ---}
+\newcommand\labelitemiii{\normalfont\bfseries --}
+\newcommand\labelitemiv{$\m@th\cdot$}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  unnumlist %%%%%%%%%%%%%%%%%%%%%%%%%%%%% TB
+%
+\def\unnumlistfont{\fontsize{10}{13}\selectfont}
+
+\newenvironment{unnumlist}{\par%
+    \unnumlistfont%
+    \list{}{%
+    \topsep6pt plus2pt
+    \itemindent-10pt
+    \leftmargin10pt
+    \parsep0pt
+    \itemsep0pt
+    \partopsep0pt}
+    \def\makelable##1{##1}%
+}{%
+    \endlist%
+}%
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  unnumlist %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\def\enumerate{% FROM LATEX.LTX
+  \ifnum \@enumdepth >\thr@@ \@toodeep\else
+    \advance\@enumdepth \@ne
+    \edef\@enumctr{enum\romannumeral\the\@enumdepth}%
+  \fi
+  \@ifnextchar [{\@enumeratetwo}{\@enumerateone}%
+}
+
+\def\@enumerateone{%
+  \expandafter
+   \list
+     \csname label\@enumctr\endcsname
+     {\usecounter{\@enumctr}%
+      \let\makelabel\makeRRlabel}%
+}
+
+\def\@enumeratetwo[#1]{%
+  \expandafter
+  \list
+    \csname label\@enumctr\endcsname
+    {\usecounter{\@enumctr}%
+     \settowidth\labelwidth{\normalfont\rmfamily #1}%
+    \itemindent0pt\leftmargin\labelwidth\advance\leftmargin\labelsep\advance\leftmargin13pt
+     \let\makelabel\makeRRlabel}%
+}
+
+\newcommand\labelenumi  {{\normalfont\rmfamily\theenumi.}}
+\newcommand\labelenumii {{\normalfont\rmfamily(\theenumii)}}
+\newcommand\labelenumiii{{\normalfont\rmfamily\theenumiii}}
+\newcommand\labelenumiv {{\normalfont\rmfamily\theenumiv}}
+
+\renewcommand\theenumi{\@arabic\c@enumi}
+\renewcommand\theenumii{\@alph\c@enumii}
+\renewcommand\theenumiii{\@roman\c@enumiii}
+\renewcommand\theenumiv{\@Alph\c@enumiv}
+
+\renewcommand\p@enumii{\theenumi}
+\renewcommand\p@enumiii{\theenumi(\theenumii)}
+\renewcommand\p@enumiv{\p@enumiii\theenumiii}
+
+\newcommand*\descriptionlabel[1]{\hspace\labelsep \normalfont\bfseries #1}
+
+\newenvironment{description}
+  {\list{}{\leftmargin 1em \labelwidth\z@ \itemindent-\leftmargin
+   \let\makelabel\descriptionlabel}}
+  {\endlist}
+
+\newenvironment{verse}
+  {\let\\=\@centercr
+   \list{}{\itemsep\z@
+   \itemindent -2.5em%
+   \listparindent \itemindent
+   \rightmargin\leftmargin
+   \advance\leftmargin 2.5em}\item[]}
+  {\endlist}
+
+\newenvironment{extract}  %quotation
+  {\list{}{\vskip6pt\listparindent\parindent
+   \topsep6pt\itemindent\listparindent
+   \leftmargin\z@ \rightmargin\leftmargin
+   \parsep \z@ \@plus 1\p@}\item[]%
+   \normalfont\small\rmfamily}
+  {\endlist}
+
+
+\newenvironment{quote}  %quotation
+  {\par\vskip5pt\itshape\leftskip0pt plus1fill\rightskip0pt plus 0fill}
+  {\par}
+
+\newenvironment{qtsource}  %quotation source
+  {\par\leftskip0pt plus1fill\rightskip0pt plus 0fill}
+  {\par}
+
+\def\quotespace{\vspace*{6.5pt}}
+
+\newenvironment{letter}  %quotation
+  {\list{}{\listparindent\z@
+   \topsep6pt\itemindent\listparindent
+   \leftmargin24pt \rightmargin\z@
+   \parsep \z@ \@plus 1\p@}\item[]%
+   \normalfont\itshape}
+  {\endlist}
+
+
+\newif\ifrembrks
+\newcommand\removebrackets{\rembrkstrue}
+
+\def\@begintheorem#1#2{% FROM LATEX.LTX
+  \normalfont\rmfamily
+  \trivlist
+    \item[\hskip \labelsep{\normalfont\itshape #1\ #2}]%
+    \item[]%
+}
+
+\def\@opargbegintheorem#1#2#3{% FROM LATEX.LTX
+  \normalfont\rmfamily
+  \trivlist
+    \item[\hskip \labelsep{\normalfont\itshape #1\ #2\ %
+    \ifrembrks #3\/\global\rembrksfalse\else {\upshape(}#3\/{\upshape)}\fi}]%
+    \item[]%
+}
+
+\newsavebox{\proofsavebox}
+
+
+%% \newtheorem{lemma}{Lemma}[section]
+%% \newtheorem{example}{Example}[section]
+%% \newtheorem{theorem}{Theorem}[section]
+%% \newtheorem{definition}{Definition}[section]
+%% \newtheorem{corollary}{Corollary}[section]
+
+
+  \sbox{\proofsavebox}
+    {\unitlength 1pt\begin{picture}(6.5,6.5)%
+     \put(0,0){\framebox(6.5,6.5){}}\end{picture}}
+  \newcommand\proofbox{\usebox{\proofsavebox}\relax}
+
+\newcommand\mathproofbox{\rlap{\quad\proofbox}}
+
+\def\@nprf{\normalfont\rmfamily \trivlist
+  \item[\hskip \labelsep {\normalfont\itshape Proof}]%
+  \item[]}
+
+\def\@oprf[#1]{\normalfont\rmfamily \trivlist
+  \item[\hskip \labelsep {\normalfont\itshape #1\ }]%
+  \item[]}
+
+\newenvironment{proof}
+  {\@ifnextchar[{\@oprf}{\@nprf}}
+  {\hspace*{15pt}\hbox{\proofbox}\endtrivlist}
+
+\newenvironment{proof*}
+  {\proof}
+  {\endtrivlist}
+
+\renewcommand\theequation{\@arabic\c@equation}
+
+\setlength\arraycolsep{5\p@}
+\setlength\tabcolsep{0\p@}
+\setlength\arrayrulewidth{.5\p@}
+\setlength\doublerulesep{1.5\p@}
+\setlength\tabbingsep{\labelsep}
+\setlength{\skip\@mpfootins}{\skip\footins}
+\setlength\fboxsep{3\p@}
+\setlength\fboxrule{.5\p@}
+
+\newcommand\maketitle{\@ifnextchar [{\m@ketitleone}{\m@ketitleone[n]}}
+
+\def\m@ketitleone[#1]{\par
+  \begingroup
+    \newpage
+    \global\@topnum\z@
+    \titlefntrue
+    \def\thefootnote{\@fnsymbol\c@footnote}%
+    \def\@makefnmark{\hbox{$\@thefnmark$}}%
+    \@maketitle{#1}%
+    \thispagestyle{titlepage}\@thanks
+  \endgroup
+  \global\let\@maketitle\relax
+  \global\let\@thanks\@empty
+  \global\let\@title\@empty
+  \global\let\@author\@empty
+  \global\let\maketitle\relax
+  \global\let\thanks\relax
+  \setcounter{footnote}\z@
+}
+
+\def\pe@rl#1{%
+  \if t#1 {\tpe@rl}\else
+    \if T#1 {\Tpe@rl}\else
+      \if f#1 {\fpe@rl}\else
+        \if F#1 {\Fpe@rl}\else
+          \if e#1 {\edpe@rl}\else
+            \if E#1 {\Edpe@rl}\else
+              \if o#1 {\otherpearl}\else
+                \vspace*{32\p@}%
+              \fi
+            \fi
+          \fi
+        \fi
+      \fi
+    \fi
+  \fi
+}
+%
+\newenvironment{bookrevauthor}{\par\vskip5pt\noindent\ignorespaces}{\par}
+
+\def\bookreventryfont{\fontsize{10}{13}\selectfont}
+\newenvironment{bookreventry}{\par\bookreventryfont\noindent\leftskip18pt\rightskip18pt\ignorespaces}{\vskip7pt\@endparenv\@ignoretrue}
+\newenvironment{question}{\par\vskip6.5pt\tablefont\noindent\ignorespaces}{\vskip6.5pt\@endparenv\@ignoretrue}
+%
+\def\spe@rl{\vspace*{32\p@}\normalfont\LARGE\rmfamily}
+\def\epe@rl#1{\par\vspace*{6.5\p@}\xdef\@shorttitle{#1}}
+
+\def\tpe@rl{\spe@rl T\ls H\ls E\ls O\ls R\ls E\ls T\ls
+  I\ls C\ls A\ls L\ns  P\ls E\ls A\ls R\ls L\ls S%
+  \epe@rl{Theoretical pearls}%
+}
+
+\def\Tpe@rl{\spe@rl T\ls H\ls E\ls O\ls R\ls E\ls T\ls
+  I\ls C\ls A\ls L\ns  P\ls E\ls A\ls R\ls L%
+  \epe@rl{Theoretical pearl}%
+}
+
+\def\fpe@rl{\spe@rl F\ls U\ls N\ls C\ls T\ls I\ls O\ls
+  N\ls A\ls L\ns  P\ls E\ls A\ls R\ls L\ls S%
+  \epe@rl{Functional pearls}%
+}
+
+\def\Fpe@rl{\spe@rl F\ls U\ls N\ls C\ls T\ls I\ls O\ls
+  N\ls A\ls L\ns  P\ls E\ls A\ls R\ls L%
+  \epe@rl{Functional pearl}%
+}
+
+\def\edpe@rl{\spe@rl E\ls D\ls U\ls C\ls A\ls T\ls I\ls O\ls N\ls A\ls L\ns 
+  P\ls E\ls A\ls R\ls L\ls S%
+  \epe@rl{Educational pearls}%
+}
+
+\def\Edpe@rl{\spe@rl E\ls D\ls U\ls C\ls A\ls T\ls I\ls O\ls N\ls A\ls L\ns 
+  P\ls E\ls A\ls R\ls L%
+  \epe@rl{Educational pearl}%
+}
+
+\def\otherpearl{\spe@rl
+  \@ifundefined{othrpearl}
+    {Please define {\normalfont\ttfamily\char92 othrpearl} to obtain\\ the correct title!}
+    {\othrpearl}%
+  \epe@rl{Short title--please redefine with {\normalfont\ttfamily\char92 shorttitle}}%
+}
+
+\def\authormark#1{\xdef\@authormark{#1}}
+
+\def\author{\@ifnextchar [{\@authortwo}{\@authorone}}
+\def\@authortwo[#1]#2{\@author{#2}\xdef\@authormark{#1}}
+\def\@authorone#1{\@author{#1}\xdef\@authormark{#1}}
+%
+%\def\@author#1{\global\advance\authorcount by 1
+%    \expandafter\xdef\csname author\romannumeral\the\authorcount\endcsname{#1}\affil{}}
+%
+\def\@author#1{\global\advance\authorcount by 1
+    \expandafter\gdef\csname author\romannumeral\the\authorcount\endcsname{#1}}
+%
+\def\affil#1{\expandafter\gdef\csname affil\romannumeral\the\authorcount\endcsname{#1}}
+\def\email#1{\expandafter\gdef\csname email\romannumeral\the\authorcount\endcsname{\normalfont\rmfamily
+  \itshape\textup{(}e-mail: \textup{\texttt{#1})}}}
+%
+\def\and{{\reset@font and}}
+%
+\def\authorsep{\unskip, }
+\newcount\authorcount\authorcount=0
+\newcount\tempcount
+\newcount\authortempcount
+%
+\def\@authors{%
+    \ifnum\authorcount>0%  %%%% Authors available
+       \tempcount=1%
+       \loop%
+       \ifnum\authorcount>0%
+          \noindent{\reset@font\authorsize\csname author\romannumeral\the\tempcount \endcsname}\par\vskip3pt%
+          \noindent{\baselineskip10pt\normalfont\reset@font\affilsize\itshape\csname affil\romannumeral\the\tempcount \endcsname\par}%
+          \noindent{\baselineskip10pt\normalfont\affilsize\itshape\csname email\romannumeral\the\tempcount \endcsname\par}%
+%             \ifnum\authorcount>1\ifnum\authorcount>2\ \else \ \and\  \fi\fi%
+           \global\advance\authorcount by -1%
+          \advance\tempcount by 1 %
+         \vskip7pt
+       \repeat
+       \global\authortempcount\tempcount
+    \fi}%
+%
+\def\spchapter{\@ifnextchar[{\@@spchapter}{\@@spchapter[]}}
+
+\def\@@spchapter[#1]#2{\gdef\@spchapter{#2}}
+\spchapter{}
+%
+\ifindex
+   \def\@maketitle#1{\cleardoublepage\bgroup%
+                    {\vspace*{18pt}\indexheadfont
+\indexname\par}\vskip43pt
+                    \egroup
+                  }%
+\else
+\def\@maketitle#1{%
+  \newpage\null
+  \ifbookreview\vskip-29pt\else\vskip-25\p@\fi%
+  {\centering \sloppy
+   \pe@rl{#1}%
+   \ifsptitle
+      \ifx\@spchapetr\@empty\else{\spchapterfont\@spchapter}\par\vskip7pt\fi%
+   \else
+      \ifsplissue
+       \ifx\@spchapetr\@empty\else{\splissuefont\@spchapter}\par\fi%
+        \else
+      \fi
+   \fi
+   {\normalfont\LARGE\itshape \@title\par}%
+   \ifx\@subtitle\@empty%
+   \else%
+      	\vskip8pt%
+	{\subtitlefont \@subtitle\par}%
+%	\vskip4pt%
+   \fi%
+   \vskip 16\p@
+   {%
+      \@authors
+   \par}%
+  }%
+  \ifsptitle\vspace*{-4\p@}\else\vskip 13.5\p@ \fi\ifbookreview\vskip26.5pt\fi%\@plus 2\p@ \@minus 1\p@
+}
+\fi
+\def\abs@header#1{%
+  \vbox{\hrule \@height .25pt  \@width30.05pc
+  \vskip 8\p@ \@plus 3\p@ \@minus 1\p@
+  \centerline{\normalfont\normalsize\bfseries #1}}%
+}
+
+\def\abs@body{%
+  \list{}{\leftmargin\z@ \rightmargin\leftmargin
+    \listparindent 1em \parsep \z@ \@plus 1\p@
+    \topsep 8\p@ %\@plus 3\p@ \@minus 1\p@
+    }%
+  \item[]\normalfont\small\rmfamily
+}
+
+\newcommand\abstractname{Abstract}
+\newenvironment{abstract}
+  {\ifsptitle\vspace*{17.3\p@}\else\fi\abs@header{\abstractname}\abs@body}
+  {\endlist\vbox{\hrule \@height .25pt \@width 30.05pc}%
+   \gdef\abs@header##1{\vskip 2\p@
+     \centerline{\normalfont\normalsize\bfseries ##1}}}
+
+\newcommand\capsulename{Capsule Review}
+\newenvironment{capsule}
+  {\abs@header{\capsulename}\abs@body}
+  {\endabstract}
+
+
+\mark{{}{}}
+
+\newcommand\shortauthor[1]{\gdef\@shortauthor{#1}}
+\gdef\@shortauthor{}
+
+\renewcommand\title{\@ifnextchar [{\@titletwo}{\@titleone}}
+\def\@titleone#1{\gdef\@title{#1}\xdef\@shorttitle{#1}}
+\def\@titletwo[#1]#2{\gdef\@title{#2}\xdef\@shorttitle{#1}}
+\gdef\@title{\mbox{}}
+
+\newcommand\subtitle[1]{\xdef\@subtitle{#1}}
+\subtitle{}
+
+\newcommand\shorttitle[1]{\xdef\@shorttitle{#1}}
+
+\newcommand\volume[1]{\gdef\@volume{#1}}
+\gdef\@volume{{\normalfont\bfseries 1} (1):}
+
+\newcommand\pagerange[1]{\gdef\@pagerange{#1}}
+\gdef\@pagerange{1--000}
+
+\newcommand\pubyear[1]{\gdef\@year{#1}}
+\gdef\@year{19XX}
+
+\newcommand\jdate[1]{\gdef\@jdate{#1}}
+\gdef\@jdate{January \@year}
+
+\newcommand\doi[1]{\gdef\@doi{10.1017/#1}}
+\gdef\@doi{10.1017/S0000000000000000}
+
+%% TB
+
+\def\Copyright{\raise.2pt\hbox{\fontsize{8}{8}\selectfont\ooalign{\hfil\raise.9pt\hbox{\hskip-.3pt{\normalfont\fontsize{7.5}{7.5}\selectfont
+c}}%
+                \hfil\crcr\mathhexbox20D}}}
+
+\newcommand\journal[1]{\gdef\@journal{#1}}
+%
+\def\pubonline#1{\gdef\@pubonline{#1}}
+\def\@pubonline{}
+%
+\ifonline
+  \def\@journal{%
+  \vbox to 8.6\p@{\noindent\parbox[t]{4.8in}{\normalfont\onlineaffilsize\rmfamily
+    {\itshape JFP\/}\ {\bf \@volume}\ (\@issue):\ \ifonepage\thepage\else\thepage--\pageref{lastpage}\fi* %
+      (First pubd online \@cpyyear)\hskip5pt \Copyright\ 
+      \@cpyyear\ Cambridge University Press\ doi:\@doi\\[2\p@]
+    *Provisional -- final page numbers to be inserted when paper edition is published}% published
+  \vss}}
+\else
+ \ifincremental
+  \def\@journal{%
+    \vbox to 8.6\p@{\noindent\parbox[t]{4.8in}{\sluglinefont%
+    {\it JFP\kern-1pt{:}\/}\ page \ifonepage\thepage\else\thepage\ of\ \pageref{lastpage}\fi.\hskip7.5pt %
+    \Copyright\ \@cpyyear\ Cambridge University Press\\[2\p@]
+    doi:\@doi}%
+  \vss}}%
+\else
+  \def\@journal{%
+    \vbox to 8.6\p@{\noindent\parbox[t]{4.8in}{\sluglinefont%
+    {\itshape JFP\/}\ {\bf \@volume}\ (\@issue):\ \ifonepage\thepage\else\thepage--\pageref{lastpage}\fi, %
+     \@pubyear.\hskip7.5pt \Copyright\ 
+      \@cpyyear\ Cambridge University Press\\[2\p@]
+      doi:\@doi\hskip5pt \ifx\@pubonline\empty\else First published online \@pubonline\fi\hskip5pt  {Printed in the United Kingdom}}%{Printed in the United Kingdom}}%
+  \vss}%
+}
+\fi\fi
+
+\def\@underjournal{%
+  \vbox to 5.6\p@{\noindent\parbox[t]{4.8in}{\normalfont\affilsize\rmfamily
+    {\itshape Under consideration for publication in
+     J.\ Functional Programming\/}\\[2.5\p@]
+     \ }%
+  \vss}%
+}
+%% 
+\def\bookrevmark#1{\gdef\@bookrevmark{#1}}
+\bookrevmark{Book review}
+%
+\def\rhfont{\fontsize{11}{11}\selectfont}
+%%
+\def\ps@headings{\let\@mkboth\markboth
+  \def\@oddhead{\hfil{\ifbookreview\fontsize{10}{13}\selectfont\fi\itshape\@shorttitle}\hfil \llap{\rhfont\thepage}}%
+  \def\@evenhead{\rlap{\rhfont\thepage}\hfil\ifbookreview{\fontsize{10}{13}\selectfont\itshape\@bookrevmark}\else\itshape\@authormark\fi\hfil}%
+  \let\@oddfoot\@empty
+  \let\@evenfoot\@oddfoot
+  \def\sectionmark##1{\markboth{##1}{}}%
+  \def\subsectionmark##1{\markright{##1}}%
+}
+
+\def\ps@Empty{%
+      \def\@oddfoot{}%
+      \let\@evenfoot\@oddfoot
+      \def\@evenhead{}%
+      \def\@oddhead{}%
+      \let\@mkboth\markboth
+      \let\chaptermark\@gobble
+      \let\sectionmark\@gobble%
+}
+
+\def\ps@myheadings{\let\@mkboth\@gobbletwo
+  \def\@oddhead{\hfil{\itshape\rightmark}\hfil \llap{\rhfont\thepage}}%
+  \def\@evenhead{\rlap{\rhfont\thepage}\hfil\itshape\leftmark\hfil}%
+  \let\@oddfoot\@empty
+  \let\@evenfoot\@oddfoot
+  \let\sectionmark\@gobble
+  \let\subsectionmark\@gobble
+}
+
+\def\@indjournal{%
+  \vbox to 6.5\p@{\noindent\parbox[t]{4.8in}{\normalfont\affilsize\rmfamily
+    {\itshape J. Functional Programming\/}\ {\bf \@volume}\ (\@issue):\
+\thepage--\pageref{lastpage}, \@pubyear\hskip7.5pt {Printed in
+United Kingdom}}%
+  \vss}%
+}
+
+\ifprodtf
+  \let\@j@urnal\@journal
+\else
+  \let\@j@urnal\@underjournal
+\fi
+
+\def\ps@titlepage{\leftskip\z@ \let\@mkboth\@gobbletwo
+  \def\@oddhead{\ifindex\@indjournal
+\hfil\hbox{\llap{\rhfont\thepage}}\else\@j@urnal \hfil\raise1.6pt\hbox{\llap{\rhfont\thepage}}\fi}%
+  \let\@evenhead\@oddhead
+  \let\@oddfoot\@empty
+  \let\@evenfoot\@oddfoot
+  \let\sectionmark\@gobble
+  \let\subsectionmark\@gobble
+}
+
+\def\@pnumwidth{1.55em}
+\def\@tocrmarg {2.55em}
+\def\@dotsep{4.5}
+\setcounter{tocdepth}{2}
+
+\def\@dottedtocline#1#2#3#4#5{% FROM LATEX.LTX
+  \ifnum #1>\c@tocdepth \else
+    \vskip \z@ \@plus.2\p@
+    {\leftskip #2\relax \rightskip \@tocrmarg \parfillskip -\rightskip
+     \parindent #2\relax\@afterindenttrue
+     \interlinepenalty\@M
+     \leavevmode
+     \@tempdima #3\relax
+     \advance\leftskip \@tempdima \null\hskip -\leftskip
+     {#4}\nobreak
+     \leaders\hbox{$\m@th
+        \mkern \@dotsep mu\hbox{\phantom{.}}\mkern \@dotsep
+        mu$}\hfill
+     \nobreak
+     \hb@xt@\@pnumwidth{\hfil\normalfont \normalcolor #5}%
+     \par}%
+  \fi}
+
+\newcommand\contentsname{Contents}
+
+\newcommand\tableofcontents{%
+  \section*{\contentsname}%
+  \@starttoc{toc}\par
+  \vspace{13\p@}%
+}
+
+\newcommand*\l@part[2]{%
+  \ifnum \c@tocdepth >-2\relax
+    \addpenalty{-\@highpenalty}%
+    \addvspace{.5\baselineskip \@plus 1\p@}%
+    \begingroup
+      \parindent \z@ \rightskip \@pnumwidth
+      \parfillskip -\@pnumwidth
+      {\leavevmode
+       \normalfont\rmfamily
+       #1\hfil \hb@xt@\@pnumwidth{\hfil}}\par
+       \nobreak
+       \if@compatibility
+         \global\@nobreaktrue
+         \everypar{\global\@nobreakfalse\everypar{}}%
+      \fi
+    \endgroup
+    \vskip .25\baselineskip \@plus 1\p@
+  \fi
+}
+
+\newcommand*\l@section[2]{%
+  \ifnum \c@tocdepth >\z@
+    \addpenalty\@secpenalty
+    \setlength\@tempdima{1.5em}%
+    \begingroup
+      \parindent \z@ \rightskip \@pnumwidth
+      \parfillskip -\@pnumwidth
+      \leavevmode \normalfont\rmfamily
+      \advance\leftskip\@tempdima
+      \hskip -\leftskip
+      {\bfseries #1}\nobreak\hfil \nobreak\hb@xt@\@pnumwidth{\hss #2}\par
+    \endgroup
+  \fi}
+
+\newcommand*\l@subsection{\@dottedtocline{2}{1.5em}{2.3em}}
+\newcommand*\l@subsubsection{\@dottedtocline{3}{3.8em}{3.2em}}
+\newcommand*\l@paragraph{\@dottedtocline{4}{7.0em}{4.1em}}
+\newcommand*\l@subparagraph{\@dottedtocline{5}{10em}{5em}}
+
+\newcommand\listfigurename{List of Figures}
+\newcommand\listoffigures{%
+  \section*{\listfigurename}%
+  \@starttoc{lof}\par
+  \vskip 13\p@
+}
+
+\newcommand*\l@figure{\@dottedtocline{1}{1.5em}{2.3em}}
+
+\newcommand\listtablename{List of Tables}
+\newcommand\listoftables{%
+  \section*{\listtablename}%
+  \@starttoc{lot}\par
+  \vskip 13\p@
+}
+
+\let\l@table\l@figure
+
+\renewcommand\footnoterule{%
+  \kern-3\p@
+  \hrule \@width .4\columnwidth height \z@
+  \kern 3\p@}
+
+\newif\iftitlefn
+
+%%
+\newbox\tempbox
+\newdimen\@footmax
+\def\footmax#1{%
+  \setbox\tempbox\hbox{\footnotesize$^{#1}$}%
+  \global\@footmax\wd\tempbox\global\advance\@footmax.5em}
+%
+\footmax{0}
+%%
+\newcommand\@makefntext[1]{%
+  \leavevmode\@hangfrom{\hb@xt@ \@footmax{\hss$\iftitlefn\else^\fi{\@thefnmark}\hskip.5em$}}#1}
+%%
+
+\ifprodtf \else \let\highast\ast\fi
+
+\def\@fnsymbol#1{\ensuremath{% FROM LATEX.LTX
+  \ifcase#1\or \hbox{$\highast$}\or \dagger\or \ddagger\or
+    \mathchar "278\or \mathchar "27B\or \|\or \hbox{$\highast\highast$}\or
+    \dagger\dagger\or \ddagger\ddagger\or \mathchar "278\mathchar "278\or
+    \mathchar "27B\mathchar "27B\or \|\|\or \else\@ctrerr\fi}%
+}
+
+\renewcommand\@makefnmark{\hbox{$^{\@thefnmark}$}}% FROM LATEX.LTX
+\renewcommand\thefootnote{\@arabic\c@footnote}% FROM LATEX.LTX
+\renewcommand\thempfootnote{\mathit{\@alph\c@mpfootnote}}% FROM LATEX.LTX
+
+\setcounter{topnumber}{2}
+\renewcommand\topfraction{.9}
+\setcounter{bottomnumber}{1}
+\renewcommand\bottomfraction{.9}
+\setcounter{totalnumber}{3}
+\renewcommand\textfraction{.1}
+\renewcommand\floatpagefraction{.9}
+\setcounter{dbltopnumber}{2}
+\renewcommand\dbltopfraction{.9}
+\renewcommand\dblfloatpagefraction{.5}
+
+\newcounter{table}
+\renewcommand\thetable{\@arabic\c@table}
+\def\fps@table{tbp}
+\def\ftype@table{1}
+\def\ext@table{lot}
+\newcommand\tablename{Table}
+\def\fnum@table{\tablename\ \thetable}
+
+\newenvironment{table}
+  {\@float{table}}
+  {\end@float}
+
+\newenvironment{table*}
+  {\@dblfloat{table}}
+  {\end@dblfloat}
+
+\def\fstyle@table{\normalfont\small\rmfamily}
+\def\fjust@table{\centering}
+\def\fcapjust@table{\centering}
+\def\fcapsize@table{\normalfont\normalsize\rmfamily}
+\def\fcapstyle@table{\normalfont\normalsize\itshape}
+
+\newcommand\contname{(cont.)}
+\newcommand\continuedfigure{%
+  \addtocounter{figure}\m@ne
+  \let\curr@thefigure\thefigure
+  \def\thefigure{\curr@thefigure\ \contname}%
+}
+
+\newcommand\continuedtable{%
+  \addtocounter{table}\m@ne
+  \let\curr@thetable\thetable
+  \def\thetable{\curr@thetable\ \contname}%
+}
+
+\newif\ifrem@fullpt
+\newcommand\removefullpoint{\global\rem@fullpttrue}
+
+\newif\ifbot@fig
+\newenvironment{bottomfigure}{\def\fps@figure{b}%
+  \setcounter{bottomnumber}{1}%
+  \global\bot@figtrue
+  \@float{figure}\fstyle@figure}
+  {\end@float}
+
+\newbox\@tempboxb
+
+\def\enskip{\hskip4.5pt}
+\long\def\@makecaption#1#2{%
+  \ifbot@fig \rule{30.05pc}{.25\p@}\fi
+  \vskip 0\p@ %\@plus .4\p@ \@minus .4\p@
+  \begingroup
+  \setbox\@tempboxb\hbox{#2}%
+  \def\@xtra{\ifdim\wd\@tempboxb>\z@ \ifrem@fullpt\else .\enskip\fi\fi}%
+  \setbox\@tempboxa\hbox{#1\@xtra #2}%
+  \ifdim\wd\@tempboxa>\tw@\textwidth
+    {\let\centering\relax #1\@xtra #2\par}%
+  \else
+    #1\@xtra #2\par
+  \fi
+  \endgroup
+  \global\bot@figfalse
+  \global\rem@fullptfalse
+}
+
+\newcounter{figure}
+\renewcommand\thefigure{\@arabic\c@figure}
+\def\fps@figure{tbp}
+\def\ftype@figure{2}
+\def\ext@figure{lof}
+\newcommand\figurename{Fig.}
+\def\fnum@figure{\figurename\ \thefigure}
+
+\newenvironment{figure}
+  {\@float{figure}}
+  {\end@float}
+
+\newenvironment{figure*}
+  {\@dblfloat{figure}}
+  {\end@dblfloat}
+
+\def\fstyle@figure{\normalfont\small\rmfamily}
+\def\fjust@figure{\centering}
+\def\fcapjust@figure{\centering}
+\def\fcapsize@figure{\normalfont\small\rmfamily}
+\def\fcapstyle@figure{\normalfont\small\rmfamily}
+
+\long\def\@caption#1[#2]#3{% FROM LATEX.LTX
+  \par
+  \addcontentsline{\csname ext@#1\endcsname}{#1}%
+    {\protect\numberline{\csname the#1\endcsname}{\ignorespaces #2}}%
+  \begingroup
+    \@parboxrestore
+    \if@minipage
+      \@setminipage
+    \fi
+    \normalsize
+    \@makecaption{\csname fcapjust@#1\endcsname
+                  \csname fcapsize@#1\endcsname
+                  \csname fnum@#1\endcsname}%
+                 {\csname fcapstyle@#1\endcsname \ignorespaces #3}\par
+  \endgroup
+}
+
+\def\@xfloat #1[#2]{% FROM LATEX.LTX
+  \@nodocument
+  \def\@captype {#1}%
+  \def\@fps {#2}%
+  \@onelevel@sanitize \@fps
+  \def \reserved@b {!}%
+  \ifx \reserved@b \@fps
+    \@fpsadddefault
+  \else
+    \ifx \@fps \@empty
+      \@fpsadddefault
+    \fi
+  \fi
+  \ifhmode
+    \@bsphack
+    \@floatpenalty-\@Mii
+  \else
+    \@floatpenalty-\@Miii
+  \fi
+  \ifinner
+    \@parmoderr\@floatpenalty\z@
+  \else
+    \@next\@currbox\@freelist
+      {%
+       \@tempcnta \sixt@@n
+       \expandafter \@tfor \expandafter \reserved@a
+         \expandafter :\expandafter =\@fps
+         \do
+          {%
+           \if \reserved@a h%
+             \ifodd \@tempcnta
+             \else
+               \advance \@tempcnta \@ne
+             \fi
+           \fi
+           \if \reserved@a t%
+             \@setfpsbit \tw@
+           \fi
+           \if \reserved@a b%
+             \@setfpsbit 4%
+           \fi
+           \if \reserved@a p%
+             \@setfpsbit 8%
+           \fi
+           \if \reserved@a !%
+             \ifnum \@tempcnta>15
+               \advance\@tempcnta -\sixt@@n\relax
+             \fi
+           \fi
+           }%
+       \@tempcntb \csname ftype@\@captype \endcsname
+       \multiply \@tempcntb \@xxxii
+       \advance \@tempcnta \@tempcntb
+       \global \count\@currbox \@tempcnta
+       }%
+    \@fltovf
+  \fi
+  \global \setbox\@currbox
+    \color@vbox
+      \normalcolor
+      \vbox \bgroup
+        \hsize\columnwidth
+        \@parboxrestore
+        \@floatboxreset
+        \csname fstyle@\@captype\endcsname
+        \csname fjust@\@captype\endcsname
+}
+
+\let\oldtabular\tabular
+\let\endoldtabular\endtabular
+
+\def\tabular{% FROM LATEX.LTX
+  \def\@halignto{to \textwidth}\tabskip\tabcolsep \@plus 1fil\@ttabular
+}
+
+\def\@ttabular{\leavevmode \hbox \bgroup $\let\@acol\@tabacol
+   \let\@classz\@tabclassz
+   \let\@classiv\@tabclassiv \let\\\@tabularcr\@ttabarray}
+
+\def\@ttabarray{\m@th\@ifnextchar[\@tarray{\@ttarray}}
+
+\def\@tarray[#1]#2{\t@barray[#1]{@{\tabskip\tw@\tabcolsep \@plus 3\p@}#2}}
+\def\@ttarray#1{\t@barray[c]{@{\tabskip\tw@\tabcolsep \@plus 3\p@}#1}}
+
+\def\t@barray[#1]#2{%
+  \if #1t\vtop \else \if#1b\vbox \else \vcenter \fi\fi
+  \bgroup
+  \setbox\@arstrutbox\hbox{%
+    \vrule \@height\arraystretch\ht\strutbox
+           \@depth\arraystretch \dp\strutbox
+           \@width\z@}%
+  \@mkpream{#2}%
+  \edef\@preamble{%
+    \halign \noexpand\@halignto
+      \bgroup \tabskip\z@skip \@arstrut \@preamble \tabskip\tabcolsep \@plus 1fil\cr}%
+  \let\@startpbox\@@startpbox \let\@endpbox\@@endpbox
+  \let\tabularnewline\\%
+  \let\par\@empty
+  \let\@sharp##%
+  \set@typeset@protect
+  \lineskip\z@skip\baselineskip\z@skip
+  \@preamble}
+
+\newcommand\ls{\kern.15em\relax}
+\newcommand\ns{\kern.55em\relax}
+
+\def\hline{% FROM LATEX.LTX
+  \noalign{\ifnum0=`}\fi \vskip 6\p@
+  \hrule \@height \arrayrulewidth \vskip 6\p@
+  \futurelet \reserved@a\@xhline}
+
+\def\@xhline{% FROM LATEX.LTX
+  \ifx\reserved@a\hline
+    \vskip -12\p@
+    \vskip\doublerulesep
+  \fi
+  \ifnum0=`{\fi}}
+
+\newcommand\today{}
+\edef\today{\number\day\ \ifcase\month\or
+  January\or February\or March\or April\or May\or June\or
+  July\or August\or September\or October\or November\or December
+ \fi \ \number\year}
+
+\renewcommand\@biblabel[1]{}% FROM LATEX.LTX
+\newcommand\newblock{\hskip .11em \@plus .33em \@minus .07em}
+
+\newcommand\refname{References}
+\newenvironment{thebibliography}[1]
+  {\section*{\refname}%
+   \normalfont\small\rmfamily
+   \addcontentsline{toc}{section}{\refname}%
+   \list{}{\usecounter{enumiv}\labelwidth\z@ \leftmargin 9pt \itemindent -9pt}%
+   \parindent\z@
+   \parskip 2\p@ \@plus .1\p@
+   \sloppy\clubpenalty\z@ \widowpenalty\@M
+   \sfcode`\.\@m\relax}
+  {\def\@noitemerr
+   {\@latex@warning{Empty `thebibliography' environment}}%
+   \endlist}
+%
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  End Bibliography Section %%%%%%%%%%%%%%%%
+\def\@citex[#1]#2{% FROM LATEX.LTX
+  \let\@citea\@empty
+  \@cite{\@for\@citeb:=#2\do
+    {\@citea\def\@citea{; }%
+     \edef\@citeb{\expandafter\@firstofone\@citeb}%
+     \if@filesw\immediate\write\@auxout{\string\citation{\@citeb}}\fi
+     \@ifundefined{b@\@citeb}{\mbox{\reset@font\bfseries ?}%
+       \G@refundefinedtrue
+       \@latex@warning
+         {Citation `\@citeb' on page \thepage \space undefined}}%
+       {\csname b@\@citeb\endcsname}}}{#1}}
+
+\def\@cite#1#2{{\if@tempswa #2\else (#1)\fi}}% FROM LATEX.LTX
+
+\let\@internalcite\cite
+\def\cite{\def\citename##1{##1}\@internalcite}
+\DeclareRobustCommand\shortcite{\def\citename##1{}\@internalcite}
+
+\newif\iffontfound
+\newcommand\checkfont[1]{%
+  \batchmode
+  \font\test=#1\relax
+  \errorstopmode
+  \fontfoundfalse
+  \ifx\test\nullfont \else \fontfoundtrue\fi
+}
+%%%%%%%%%%%
+%
+\def\ct@indenttext#1{\parindent24pt{\par\hangindent48pt #1\par}}
+\def\ct@Indenttext#1{\parindent48pt{\par\hangindent48pt #1\par}}
+%
+%
+%
+\newcount\minute
+\newcount\hour
+\def\currenttime{%
+     \minute\time
+     \hour\minute
+     \divide\hour60
+     \the\hour:\multiply\hour60\advance\minute-\hour\the\minute}
+%%%%%
+\def\gray{\special{color CMYK 0 0 0 0.5}}
+\def\@questionmark{\vbox to 0pt{\vskip13pc\hskip-5pc
+                  \hbox to \textwidth{\special{color push}\gray\fontsize{270}{270}\selectfont ?
+                  \special{color pop}\hss}}}
+\def\questionmark#1{\xdef\@questionmark{#1}}%
+%
+\def\@TotalChars{}
+\def\TotalChars#1{\xdef\@TotalChars{#1}}%
+%%
+\def\document{\endgroup
+  \ifx\@unusedoptionlist\@empty\else
+    \@latex@warning@no@line{Unused global option(s):^^J%
+            \@spaces[\@unusedoptionlist]}%
+  \fi
+  \@colht\textheight
+  \@colroom\textheight \vsize\textheight
+  \columnwidth\textwidth
+  \@clubpenalty\clubpenalty
+  \if@twocolumn
+    \advance\columnwidth -\columnsep
+    \divide\columnwidth\tw@ \hsize\columnwidth \@firstcolumntrue
+  \fi
+  \hsize\columnwidth \linewidth\hsize
+  \begingroup\@floatplacement\@dblfloatplacement
+    \makeatletter\let\@writefile\@gobbletwo
+    \global \let \@multiplelabels \relax
+    \@input{\jobname.aux}%
+  \endgroup
+  \if@filesw
+     \immediate\openout\@mainaux=\jobname.aux
+     \immediate\write\@mainaux{\relax}
+  \fi
+  \process@table
+  \let\glb@currsize\@empty  %% Force math initialization.
+  \normalsize
+  \everypar{}%
+  \ifx\normalsfcodes\@empty
+    \ifnum\sfcode`\.=\@m
+      \let\normalsfcodes\frenchspacing
+    \else
+      \let\normalsfcodes\nonfrenchspacing
+    \fi
+  \fi
+  \@noskipsecfalse
+  \let \@refundefined \relax
+  \let\AtBeginDocument\@firstofone
+  \@begindocumenthook
+  \ifdim\topskip<1sp\global\topskip 1sp\relax\fi
+  \global\@maxdepth\maxdepth
+  \global\let\@begindocumenthook\@undefined
+  \ifx\@listfiles\@undefined
+    \global\let\@filelist\relax
+    \global\let\@addtofilelist\@gobble
+  \fi
+  \gdef\do##1{\global\let ##1\@notprerr}%
+  \@preamblecmds
+  \global\let \@nodocument \relax
+  \global\let\do\noexpand
+  \ignorespaces}
+%
+%%
+\def\enddocument{\label{lastpage}%
+   \@checkend{document}%
+   \@enddocumenthook
+   \ifodd\c@page\cleardoublepage\else\clearpage\fi
+   \begingroup
+     \if@filesw
+       \immediate\write\@mainaux{\string\questionmark{}}%
+       \immediate\closeout\@mainaux
+       \let\@setckpt\@gobbletwo
+       \let\@newl@bel\@testdef
+       \@tempswafalse
+       \makeatletter
+       \catcode`\\0
+       \catcode`\{1
+       \catcode`\}2
+       \catcode`\^=7
+       \catcode`\_=8
+       \catcode`\&=4
+       \catcode`\$=3  
+       \catcode`\@11
+       \catcode`\#6
+       \catcode`\"=12
+       \input\jobname.aux
+     \fi
+     \@dofilelist
+     \ifdim \font@submax >\fontsubfuzz\relax
+       \@font@warning{Size substitutions with differences\MessageBreak
+                  up to \font@submax\space have occured.\@gobbletwo}%
+     \fi
+     \@defaultsubs
+     \@refundefined
+     \if@filesw
+       \ifx \@multiplelabels \relax
+         \if@tempswa
+           \@latex@warning@no@line{Label(s) may have changed.
+               Rerun to get cross-references right}%
+         \fi
+       \else
+         \@multiplelabels
+       \fi
+     \fi
+   \endgroup
+   \deadcycles\z@\@@end}
+%%
+\def\@outputpage{%
+\begingroup           % the \endgroup is put in by \aftergroup
+  \let \protect \noexpand
+  \@resetactivechars
+  \@parboxrestore
+  \shipout \vbox{%
+    \set@typeset@protect
+    \aftergroup \endgroup
+    \aftergroup \set@typeset@protect
+                                % correct? or just restore by ending
+                                % the group?
+  \if@specialpage
+    \global\@specialpagefalse\@nameuse{ps@\@specialstyle}%
+  \fi
+  \if@twoside
+    \ifodd\count\z@ \let\@thehead\@oddhead \let\@thefoot\@oddfoot
+         \let\@themargin\oddsidemargin
+    \else \let\@thehead\@evenhead
+       \let\@thefoot\@evenfoot \let\@themargin\evensidemargin
+    \fi
+  \fi
+  \reset@font
+  \normalsize
+  \normalsfcodes
+  \let\label\@gobble
+  \let\index\@gobble
+  \let\glossary\@gobble
+  \baselineskip\z@skip \lineskip\z@skip \lineskiplimit\z@
+    \@begindvi\trimmarks
+    \vskip \topmargin
+    \moveright\@themargin \vbox {%
+      \setbox\@tempboxa \vbox to\headheight{%
+        \vfil
+        \color@hbox
+          \normalcolor
+          \hb@xt@\textwidth{\@thehead}%
+        \color@endbox
+        }%                        %% 22 Feb 87
+      \dp\@tempboxa \z@
+      \box\@tempboxa
+      \vskip \headsep
+      \box\@outputbox
+      \baselineskip \footskip
+      \color@hbox
+        \normalcolor
+        \hb@xt@\textwidth{\@thefoot}%
+      \color@endbox
+      }%
+    }%
+  \global \@colht \textheight
+  \stepcounter{page}%
+  \let\firstmark\botmark
+  \ifodd\c@page
+     \ifspreadlong\global\spreadlongfalse
+     \enlargethispage{\@spreadlong}\fi
+  \fi
+}
+%%%%%
+\newif\ifspreadlong
+\def\spreadlong#1{\ifodd\c@page\wlog{Ignoring spreadlong}
+                  \else
+                     \spreadlongtrue\gdef\@spreadlong{#1}%
+                     \enlargethispage{#1}%
+                  \fi}
+% check specs and enable one or both of these commands
+\def\leaflong#1{\enlargethispage{#1}}
+%%%%%
+\def\trimmarks{%
+  \vbox to 0pt{%
+     \vskip-25pt\parindent0pt
+     \draftnote\offinterlineskip}%
+  \ifdraft
+    \vbox to 0pt{\hsize\trimwidth\offinterlineskip
+    \parindent0pt\leftskip0pt\rightskip0pt
+    \fboxsep0pt\fboxrule\draftrule
+    \fbox{\vbox{\vskip\trimheight\hskip\trimwidth}}}%
+%
+    \vbox to 0pt{\hsize\trimwidth\offinterlineskip
+    \parindent0pt\leftskip0pt\rightskip0pt
+    \vbox to \trimheight{\offinterlineskip\parindent0pt
+    \hbox to \trimwidth{\vbox to 2pc{\vskip-3.5pc\hbox{\vrule height2pc width\trimrule}}\raisebox{2pc}{\hbox{\hskip-3.5pc\vrule width2pc height\trimrule}}\hfill
+      \raisebox{2pc}{\vrule width2pc height\trimrule\hskip-3.75pc}
+      \vbox to 2pc{\vskip-3.5pc\hbox{\vrule height2pc width\trimrule}}%
+    }\vfill
+    \hbox to \trimwidth{\hbox{\hskip-3.5pc\vrule height\trimrule width2pc}\vbox to 3pc{\vspace*{4.5pc}\hbox{\hskip1.5pc\vrule width\trimrule height2pc}}\hfill
+    \vbox to 3.5pc{\vskip5pc\hbox{\vrule height2pc width\trimrule}}\rlap{\hskip1.5pc\vrule width2pc height\trimrule}}}}%
+%    
+  \else
+    \vbox to 0pt{\hsize\trimwidth\offinterlineskip
+    \parindent0pt\leftskip0pt\rightskip0pt
+    \vbox to \trimheight{\offinterlineskip\parindent0pt
+    \hbox to \trimwidth{\vbox to 2pc{\vskip-3.5pc\hbox{\vrule height2pc width\trimrule}}\raisebox{2pc}{\hbox{\hskip-3.5pc\vrule width2pc height\trimrule}}\hfill
+      \raisebox{2pc}{\vrule width2pc height\trimrule\hskip-3.75pc}
+      \vbox to 2pc{\vskip-3.5pc\hbox{\vrule height2pc width\trimrule}}%
+    }\vfill
+    \hbox to \trimwidth{\hbox{\hskip-3.5pc\vrule height\trimrule width2pc}\vbox to 3pc{\vspace*{4.5pc}\hbox{\hskip1.5pc\vrule width\trimrule height2pc}}\hfill
+    \vbox to 3.5pc{\vskip5pc\hbox{\vrule height2pc width\trimrule}}\rlap{\hskip1.5pc\vrule width2pc height\trimrule}}}}
+\fi
+\insidedraftrules}
+%
+\def\insidedraftrules{\overfullrule0pt\leftskip0pt\rightskip0pt\vbox to 0pt{%
+  \offinterlineskip\parindent0pt
+  \vskip \topmargin
+  \tempdimen\normaltextheight
+  \advance\tempdimen\headheight
+  \advance\tempdimen\headsep
+  \moveright\@themargin
+  \vbox{\vbox to 0pt{\vskip\headheight\vskip\headsep\vskip.2pt
+   \vrule height\draftrule width\textwidth
+   }
+   \hbox{\fboxsep0pt\fboxrule\draftrule
+        \fbox{\vbox to \tempdimen
+                    {\hsize\textwidth\hskip\textwidth}}}}}}%
+%
+
+%%
+%%
+\usepackage{rotating}
+%%
+\ifprinter
+   \def\draftnote{}
+   \def\Qauthor{}
+\else
+\def\draftnote{\vbox to 0pt{\vskip-12pt
+   \hbox{\ \footnotesize}}%\TeXversion
+   \hbox{\ \footnotesize ZU064-05-FPR\qquad\jobname\qquad\today\qquad\currenttime\qquad %Char Count= \@TotalChars
+   \@questionmark\hfil}}%
+   \def\Qauthor#1{\marginpar{{\raggedright\footnotesize\bf #1\endgraf}}}
+\fi
+%%
+\newdimen\figheight
+\newdimen\figwidth
+%
+\def\ArtDir{art/}%
+\input epsf.sty
+%
+\newbox\figtempbox
+\def\ArtPiece#1{\epsfbox{\ArtDir#1}}%
+%
+\def\figurebox#1#2{%
+    \@ifnextchar[{\@figurebox{#1}{#2}}{\@figurebox{#1}{#2}[]}}
+%
+\def\@figurebox#1#2[#3]{%
+      \gdef\@thirdarg{#3}%
+      \ifx\@thirdarg\empty
+         \global\figheight=#1
+         \global\figwidth=#2
+      \else 
+         \setbox\figtempbox=\hbox{\epsfbox{\ArtDir\@thirdarg}}%
+         \global\figwidth=\wd\figtempbox
+         \global\figheight=\ht\figtempbox
+      \fi
+       \centerline{\figbox}
+    \vskip7pt}%
+%
+\def\figbox{%
+     \ifx\@thirdarg\empty
+        \vbox{\vskip.3pt\hsize\figwidth
+        \hrule\hbox to\figwidth{\vrule\hfill\vbox to\figheight{%
+              \hsize\figwidth\vfill}\vrule}\hrule}%
+     \else
+        \vbox{\hsize\figwidth
+ 	      \hbox to\figwidth{\vbox to\figheight{\hsize\figwidth\box\figtempbox}}}%
+    \fi}
+%
+%
+%
+\newdimen\tabledim
+\newskip\tableleftskip
+\newskip\tablerightskip
+\newskip\tabnoteleftskip
+\newskip\tabnoterightskip
+\newdimen\tablewidth
+%
+
+%
+\def\tbl#1#2{%
+  \setbox\tempbox\hbox{\tablefont#2}%
+  \tabledim\hsize
+  \advance\tabledim-\wd\tempbox
+  \ifdim\tabledim>0pt
+		 		\divide\tabledim2
+  \else
+  			\global\tabledim0pt
+  \fi
+  \global\tableleftskip\tabledim 
+  \global\tablerightskip\tabledim plus.5fill
+  \global\tabnoteleftskip\tabledim
+  \global\tabnoterightskip\tabledim
+  \caption{\tablefont #1}%
+  {\centerline{\box\tempbox}}}%
+%
+\let\bulletlist\itemize
+\let\endbulletlist\enditemize
+\let\arabiclist\enumerate
+\let\endarabiclist\endenumerate
+\let\ulist\unnumlist
+\let\endulist\endunnumlist
+\def\bibauthor#1{{#1}}
+\def\x{@{\extracolsep{\fill}}}
+\def\tablefont{\fontsize{9}{11}\selectfont}%\leftskip\tableleftskip\rightskip\tablerightskip\mathversion{normal}}% use plus 1fill if needed
+\def\tablecaptionfont{\fontsize{10}{12}\selectfont\itshape\leftskip\tableleftskip\rightskip\tablerightskip}%\itshape
+\def\tablecaptionnumfont{\reset@font\fontsize{10}{12}\selectfont}% 
+\def\TCHfont{\fontsize{9}{13}\selectfont}%
+\def\TSCHfont{}%
+\def\tabnotefont{\fontsize{9}{11}\selectfont\leftskip\tabnoteleftskip\rightskip\tabnoterightskip}% use plus 1fill if needed
+\def\toprule{\\[-5pt]\Hline\\[-9pt]\Hline\\[-7.1pt]}
+\def\colrule{\\[-7.8pt]\HHline\\[-7pt]}
+\def\Colrule{\\[-8.6pt]\HHline\\[-5.2pt]}
+\def\botrule{\\[-8.3pt]\Hline\\[-9pt]\Hline}
+\def\crule#1{\\[-10.9pt]#1\\[-21.4pt]}
+%
+\def\Hline{%
+  \noalign{\ifnum0=`}\fi\hrule \@height .5pt \futurelet%\@height \arrayrulewidth
+   \@tempa\@xhline}
+%
+\def\HHline{%
+  \noalign{\ifnum0=`}\fi\hrule \@height .5pt \futurelet%\@height \arrayrulewidth
+   \@tempa\@xhline}
+%
+%
+%
+\def\pubDate#1{(#1)}
+%
+\newenvironment{ack}{\par\addvspace{\baselineskip}}{\par}
+%
+\def\@Afterheading{%
+  \global\@nobreaktrue
+  \everypar{%
+    \if@nobreak
+      \global\@nobreakfalse
+      \clubpenalty \@M
+      \if@afterindent \else
+        {\setbox\z@\lastbox}%
+      \fi
+    \else
+      \clubpenalty \@clubpenalty
+      \everypar{}%
+    \fi}}
+%
+\def\getBIBNUM#1{%
+     \expandafter\getstring#1\@}
+%
+\def\getstring #1#2#3#4\@{\gdef\@@getstr{#1#2#3}}
+%
+\let\summary\abstract
+\let\endsummary\endabstract
+\let\makechaptertitle\relax
+%
+\@namedef{equation*}{$$}
+\@namedef{endequation*}{$$}
+%
+\gdef\zero@{0}
+\gdef\REF{ref}
+\gdef\removedash#1-#2-#3#4#5#6#7#8#9{%
+\gdef\tempa{#2}%
+\gdef\tempb{#3}%
+\ifx\tempa\REF%
+\else%
+\ifx\tempb\N%
+\expandafter\removezeros#7#8#9%
+\else%
+\fi%
+\fi%
+\gdef\tempa{}\gdef\tempb{}}
+%
+\gdef\N{n}
+%
+\gdef\removezeros#1#2#3{%
+\gdef\tempd{#1}%
+\gdef\tempe{#2}%
+\gdef\tempf{#3}%
+\ifnum\tempd=\zero@%
+  \ifnum\tempe=\zero@%
+    $^\tempf$%
+  \else%
+    $^{\tempe\tempf}$%
+   \fi%
+\else%
+    $^{\tempd\tempe\tempf}$%
+\fi
+\gdef\tempd{}\gdef\tempe{}\gdef\tempf{}}
+\newcount\colcount
+\newcount\firstcol
+\newcount\lastcol
+\def\getCOLNUM#1#2{
+\global\colcount\expandafter\getnumber#2
+\global\advance\colcount-\expandafter\getnumber#1
+\global\advance\colcount1
+\global\firstcol\expandafter\getnumber#1
+\global\lastcol\expandafter\getnumber#2}
+%
+%\def\getnumber col#1{#1}
+\def\getnumber #1{#1}
+%
+\gdef\removexref#1-#2-#3#4#5#6#7#8{%
+\thechapter.\expandafter\removexzeros#6#7#8}
+%
+\gdef\removehash#1#2{#2}
+\gdef\removexzeros#1#2#3{%
+\gdef\tempd{#1}%
+\gdef\tempe{#2}%
+\gdef\tempf{#3}%
+\ifnum\tempd=\zero@%
+  \ifnum\tempe=\zero@%
+{\tempf}%
+  \else%
+{\tempe\tempf}%
+   \fi%
+\else%
+{\tempd\tempe\tempf}%
+\fi
+\gdef\tempd{}\gdef\tempe{}\gdef\tempf{}}
+%
+\newif\ifframed
+\newif\ifnotablenum
+%
+\renewcommand{\textellipsis}{%
+   .\kern\fontdimen3\font
+   .\kern\fontdimen3\font
+   .\kern\fontdimen3\font}
+%
+%
+\let\thenotes\Notes
+\let\endthenotes\endNotes
+\let\endnote\Enote
+\def\listhead#1{}
+\let\parahead\prhead
+%
+\let\@chaptertitle\@chaptitle
+%
+\def\Pound{\hbox{\char'243}}%
+%
+\newbox\tempbox
+%
+\def\pubyear#1{\gdef\@pubyear{#1}}%\pubyear{2002}
+\def\cpyyear#1{\gdef\@cpyyear{#1}}%\pubyear{2002}
+\cpyyear{}
+%\def\volume#1{\gdef\@volume{#1}}%\volume{xxx}
+\def\issue#1{\gdef\@issue{#1}}%\volume{xxx}
+\issue{}
+\def\doi#1{\gdef\@doi{#1}}%\doi{10.1017$/$S002211200100622X}
+%
+\let\chapter\title
+%
+\def\indexfont{\fontsize{9}{10}\selectfont}
+%
+\def\alphabet#1{{\bf#1}\par\vskip.5\baselineskip}
+
+%
+\def\indexheadfont{\fontsize{18.5}{20.5}\selectfont\bfseries\centering}
+\newcommand\indexname{Author index}
+\newenvironment{theindex}[2][\relax]{\thispagestyle{empty}\authormark{\indexname}%\global\indextrue%%
+      \ifx#2\relax\else\gdef\indexname{#2}\fi%
+      \ifx#1\relax\else\gdef\indexhead{#1}\fi%
+      \maketitle\indexfont%
+      \parindent\z@
+      \let\item\@idxitem
+}{%
+      \par%\global\indexfalse
+}
+\newcommand\@idxitem  {\par\hangindent9pt}
+\newcommand\subitem   {\par\hangindent2em\hspace*{1em}}
+\newcommand\subsubitem{\par\hangindent2em\hspace*{2em}}
+\newcommand\indexspace{\par \vskip\baselineskip}
+%
+\newenvironment{indexpara}{\setbox\tempbox\hbox\bgroup}{\egroup}
+\def\au#1{{\indexfont\scshape#1}}
+\def\ttl#1{{\indexfont#1}}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%\newcommand\email[1]{\par{\normalfont\rmfamily
+%  \itshape\textup{(}e-mail: \textup{\texttt{#1})}}\par}
+
+\edef\r@{\ifprodtf mtr\else cmr\fi}
+%\edef\s@{\ifprodtf mtss\else cmr\fi}
+
+\let\real@font@warning\@font@warning
+\DeclareMathVersion{program}
+\let\@font@warning\@gobble
+\SetSymbolFont{letters}{program}{OT1}{\r@}{m}{sl}
+\let\@font@warning\real@font@warning
+\SetMathAlphabet{\mathnormal}{program}{OT1}{\r@}{m}{sl}
+
+
+\newcommand{\programmath}{\mathversion{program}}
+\newcommand{\unprogrammath}{\mathversion{normal}}
+\newcommand{\figrule}{\begin{center}\hrule\end{center}}
+
+\DeclareRobustCommand\dplus{\mathbin{+\!\!+}}
+\DeclareRobustCommand\dequals{\mathbin{==}}
+\DeclareRobustCommand\dcolon{\mathbin{::}}
+\DeclareRobustCommand\dcolonequals{\mathbin{::=}}
+
+\pagestyle{headings}
+\pagenumbering{arabic}
+\frenchspacing
+\flushbottom
+
+\def\parahead#1{}
+
+\ifprinter
+\voffset-18.4mm
+\hoffset-25.4mm
+\else
+\voffset2.3pc
+\hoffset-1pc
+\fi
+%%
+\ifcompmod
+\else
+   \usepackage{mathptmx,bm}
+   \DeclareMathVersion{bold}
+   \usepackage{amsfonts}
+\fi
+%%
+\endinput
+
+% end of file jfp.cls
\ No newline at end of file
diff --git a/jfp-paper/latexrun b/jfp-paper/latexrun
new file mode 100755
index 0000000000000000000000000000000000000000..b669d9fbbc0ff0b15a3dea0e2d21fe873ab1a9bf
--- /dev/null
+++ b/jfp-paper/latexrun
@@ -0,0 +1,1936 @@
+#!/usr/bin/env python3
+
+# Copyright (c) 2013, 2014 Austin Clements
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+import sys
+import os
+import errno
+import argparse
+import shlex
+import json
+import subprocess
+import re
+import collections
+import hashlib
+import shutil
+import curses
+import filecmp
+import io
+import traceback
+import time
+
+try:
+    import fcntl
+except ImportError:
+    # Non-UNIX platform
+    fcntl = None
+
+def debug(string, *args):
+    if debug.enabled:
+        print(string.format(*args), file=sys.stderr)
+debug.enabled = False
+
+def debug_exc():
+    if debug.enabled:
+        traceback.print_exc()
+
+def main():
+    # Parse command-line
+    arg_parser = argparse.ArgumentParser(
+        description='''A 21st century LaTeX wrapper,
+        %(prog)s runs latex (and bibtex) the right number of times so you
+        don't have to,
+        strips the log spew to make errors visible,
+        and plays well with standard build tools.''')
+    arg_parser.add_argument(
+        '-o', metavar='FILE', dest='output', default=None,
+        help='Output file name (default: derived from input file)')
+    arg_parser.add_argument(
+        '--latex-cmd', metavar='CMD', default='pdflatex',
+        help='Latex command (default: %(default)s)')
+    arg_parser.add_argument(
+        '--latex-args', metavar='ARGS', type=arg_parser_shlex,
+        help='Additional command-line arguments for latex.'
+        ' This will be parsed and split using POSIX shell rules.')
+    arg_parser.add_argument(
+        '--bibtex-cmd', metavar='CMD', default='bibtex',
+        help='Bibtex command (default: %(default)s)')
+    arg_parser.add_argument(
+        '--bibtex-args', metavar='ARGS', type=arg_parser_shlex,
+        help='Additional command-line arguments for bibtex')
+    arg_parser.add_argument(
+        '--max-iterations', metavar='N', type=int, default=10,
+        help='Max number of times to run latex before giving up'
+        ' (default: %(default)s)')
+    arg_parser.add_argument(
+        '-W', metavar='(no-)CLASS',
+        action=ArgParserWarnAction, dest='nowarns', default=set(['underfull']),
+        help='Enable/disable warning from CLASS, which can be any package name, '
+        'LaTeX warning class (e.g., font), bad box type '
+        '(underfull, overfull, loose, tight), or "all"')
+    arg_parser.add_argument(
+        '-O', metavar='DIR', dest='obj_dir', default='latex.out',
+        help='Directory for intermediate files and control database '
+        '(default: %(default)s)')
+    arg_parser.add_argument(
+        '--color', choices=('auto', 'always', 'never'), default='auto',
+        help='When to colorize messages')
+    arg_parser.add_argument(
+        '--verbose-cmds', action='store_true', default=False,
+        help='Print commands as they are executed')
+    arg_parser.add_argument(
+        '--debug', action='store_true',
+        help='Enable detailed debug output')
+    actions = arg_parser.add_argument_group('actions')
+    actions.add_argument(
+        '--clean-all', action='store_true', help='Delete output files')
+    actions.add_argument(
+        'file', nargs='?', help='.tex file to compile')
+    args = arg_parser.parse_args()
+    if not any([args.clean_all, args.file]):
+        arg_parser.error('at least one action is required')
+    args.latex_args = args.latex_args or []
+    args.bibtex_args = args.bibtex_args or []
+
+    verbose_cmd.enabled = args.verbose_cmds
+    debug.enabled = args.debug
+
+    # A note about encodings: POSIX encoding is a mess; TeX encoding
+    # is a disaster.  Our goal is to make things no worse, so we want
+    # byte-accurate round-tripping of TeX messages.  Since TeX
+    # messages are *basically* text, we use strings and
+    # surrogateescape'ing for both input and output.  I'm not fond of
+    # setting surrogateescape globally, but it's far easier than
+    # dealing with every place we pass TeX output through.
+    # Conveniently, JSON can round-trip surrogateescape'd strings, so
+    # our control database doesn't need special handling.
+    sys.stdout = io.TextIOWrapper(
+        sys.stdout.buffer, encoding=sys.stdout.encoding,
+        errors='surrogateescape', line_buffering=sys.stdout.line_buffering)
+    sys.stderr = io.TextIOWrapper(
+        sys.stderr.buffer, encoding=sys.stderr.encoding,
+        errors='surrogateescape', line_buffering=sys.stderr.line_buffering)
+
+    Message.setup_color(args.color)
+
+    # Open control database.
+    dbpath = os.path.join(args.obj_dir, '.latexrun.db')
+    if not os.path.exists(dbpath) and os.path.exists('.latexrun.db'):
+        # The control database used to live in the source directory.
+        # Support this for backwards compatibility.
+        dbpath = '.latexrun.db'
+    try:
+        db = DB(dbpath)
+    except (ValueError, OSError) as e:
+        print('error opening {}: {}'.format(e.filename if hasattr(e, 'filename')
+                                            else dbpath, e),
+              file=sys.stderr)
+        debug_exc()
+        sys.exit(1)
+
+    # Clean
+    if args.clean_all:
+        try:
+            db.do_clean(args.obj_dir)
+        except OSError as e:
+            print(e, file=sys.stderr)
+            debug_exc()
+            sys.exit(1)
+
+    # Build
+    if not args.file:
+        return
+    task_commit = None
+    try:
+        task_latex = LaTeX(db, args.file, args.latex_cmd, args.latex_args,
+                           args.obj_dir, args.nowarns)
+        task_commit = LaTeXCommit(db, task_latex, args.output)
+        task_bibtex = BibTeX(db, task_latex, args.bibtex_cmd, args.bibtex_args,
+                             args.nowarns, args.obj_dir)
+        tasks = [task_latex, task_commit, task_bibtex]
+        stable = run_tasks(tasks, args.max_iterations)
+
+        # Print final task output and gather exit status
+        status = 0
+        for task in tasks:
+            status = max(task.report(), status)
+
+        if not stable:
+            print('error: files are still changing after {} iterations; giving up'
+                  .format(args.max_iterations), file=sys.stderr)
+            status = max(status, 1)
+    except TaskError as e:
+        print(str(e), file=sys.stderr)
+        debug_exc()
+        status = 1
+
+    # Report final status, if interesting
+    fstatus = 'There were errors' if task_commit is None else task_commit.status
+    if fstatus:
+        output = args.output
+        if output is None:
+            if task_latex.get_outname() is not None:
+                output = os.path.basename(task_latex.get_outname())
+            else:
+                output = 'output'
+        if Message._color:
+            terminfo.send('bold', ('setaf', 1))
+        print('{}; {} not updated'.format(fstatus, output))
+        if Message._color:
+            terminfo.send('sgr0')
+    sys.exit(status)
+
+def arg_parser_shlex(string):
+    """Argument parser for shell token lists."""
+    try:
+        return shlex.split(string)
+    except ValueError as e:
+        raise argparse.ArgumentTypeError(str(e)) from None
+
+class ArgParserWarnAction(argparse.Action):
+    def __call__(self, parser, namespace, value, option_string=None):
+        nowarn = getattr(namespace, self.dest)
+        if value == 'all':
+            nowarn.clear()
+        elif value.startswith('no-'):
+            nowarn.add(value[3:])
+        else:
+            nowarn.discard(value)
+        setattr(namespace, self.dest, nowarn)
+
+def verbose_cmd(args, cwd=None, env=None):
+    if verbose_cmd.enabled:
+        cmd = ' '.join(map(shlex.quote, args))
+        if cwd is not None:
+            cmd = '(cd {} && {})'.format(shlex.quote(cwd), cmd)
+        if env is not None:
+            for k, v in env.items():
+                if os.environ.get(k) != v:
+                    cmd = '{}={} {}'.format(k, shlex.quote(v), cmd)
+        print(cmd, file=sys.stderr)
+verbose_cmd.enabled = False
+
+def mkdir_p(path):
+    try:
+        os.makedirs(path)
+    except OSError as exc:
+        if exc.errno == errno.EEXIST and os.path.isdir(path):
+            pass
+        else: raise
+
+class DB:
+    """A latexrun control database."""
+
+    _VERSION = 'latexrun-db-v2'
+
+    def __init__(self, filename):
+        self.__filename = filename
+
+        # Make sure database directory exists
+        if os.path.dirname(self.__filename):
+            os.makedirs(os.path.dirname(self.__filename), exist_ok=True)
+
+        # Lock the database if possible. We don't release this lock
+        # until the process exits.
+        lockpath = self.__filename + '.lock'
+        if fcntl is not None:
+            lockfd = os.open(lockpath, os.O_CREAT|os.O_WRONLY|os.O_CLOEXEC, 0o666)
+            # Note that this is actually an fcntl lock, not a lockf
+            # lock. Don't be fooled.
+            fcntl.lockf(lockfd, fcntl.LOCK_EX, 1)
+
+        try:
+            fp = open(filename, 'r')
+        except FileNotFoundError:
+            debug('creating new database')
+            self.__val = {'version': DB._VERSION}
+        else:
+            debug('loading database')
+            self.__val = json.load(fp)
+            if 'version' not in self.__val:
+                raise ValueError('file exists, but does not appear to be a latexrun database'.format(filename))
+            if self.__val['version'] != DB._VERSION:
+                raise ValueError('unknown database version {!r}'
+                                 .format(self.__val['version']))
+
+    def commit(self):
+        debug('committing database')
+        # Atomically commit database
+        tmp_filename = self.__filename + '.tmp'
+        with open(tmp_filename, 'w') as fp:
+            json.dump(self.__val, fp, indent=2, separators=(',', ': '))
+            fp.flush()
+            os.fsync(fp.fileno())
+        os.rename(tmp_filename, self.__filename)
+
+    def get_summary(self, task_id):
+        """Return the recorded summary for the given task or None."""
+        return self.__val.get('tasks', {}).get(task_id)
+
+    def set_summary(self, task_id, summary):
+        """Set the summary for the given task."""
+        self.__val.setdefault('tasks', {})[task_id] = summary
+
+    def add_clean(self, filename):
+        """Add an output file to be cleaned.
+
+        Unlike the output files recorded in the task summaries,
+        cleanable files strictly accumulate until a clean is
+        performed.
+        """
+        self.__val.setdefault('clean', {})[filename] = hash_cache.get(filename)
+
+    def do_clean(self, obj_dir=None):
+        """Remove output files and delete database.
+
+        If obj_dir is not None and it is empty after all files are
+        removed, it will also be removed.
+        """
+
+        for f, want_hash in self.__val.get('clean', {}).items():
+            have_hash = hash_cache.get(f)
+            if have_hash is not None:
+                if want_hash == have_hash:
+                    debug('unlinking {}', f)
+                    hash_cache.invalidate(f)
+                    os.unlink(f)
+                else:
+                    print('warning: {} has changed; not removing'.format(f),
+                          file=sys.stderr)
+        self.__val = {'version': DB._VERSION}
+        try:
+            os.unlink(self.__filename)
+        except FileNotFoundError:
+            pass
+        if obj_dir is not None:
+            try:
+                os.rmdir(obj_dir)
+            except OSError:
+                pass
+
+class HashCache:
+    """Cache of file hashes.
+
+    As latexrun reaches fixed-point, it hashes the same files over and
+    over, many of which never change.  Since hashing is somewhat
+    expensive, we keep a simple cache of these hashes.
+    """
+
+    def __init__(self):
+        self.__cache = {}
+
+    def get(self, filename):
+        """Return the hash of filename, or * if it was clobbered."""
+        try:
+            with open(filename, 'rb') as fp:
+                st = os.fstat(fp.fileno())
+                key = (st.st_dev, st.st_ino)
+                if key in self.__cache:
+                    return self.__cache[key]
+
+                debug('hashing {}', filename)
+                h = hashlib.sha256()
+                while True:
+                    block = fp.read(256*1024)
+                    if not len(block):
+                        break
+                    h.update(block)
+                self.__cache[key] = h.hexdigest()
+                return self.__cache[key]
+        except (FileNotFoundError, IsADirectoryError):
+            return None
+
+    def clobber(self, filename):
+        """If filename's hash is not known, record an invalid hash.
+
+        This can be used when filename was overwritten before we were
+        necessarily able to obtain its hash.  filename must exist.
+        """
+        st = os.stat(filename)
+        key = (st.st_dev, st.st_ino)
+        if key not in self.__cache:
+            self.__cache[key] = '*'
+
+    def invalidate(self, filename):
+        try:
+            st = os.stat(filename)
+        except OSError as e:
+            # Pessimistically wipe the whole cache
+            debug('wiping hash cache ({})', e)
+            self.__cache.clear()
+        else:
+            key = (st.st_dev, st.st_ino)
+            if key in self.__cache:
+                del self.__cache[key]
+hash_cache = HashCache()
+
+class _Terminfo:
+    def __init__(self):
+        self.__tty = os.isatty(sys.stdout.fileno())
+        if self.__tty:
+            curses.setupterm()
+        self.__ti = {}
+
+    def __ensure(self, cap):
+        if cap not in self.__ti:
+            if not self.__tty:
+                string = None
+            else:
+                string = curses.tigetstr(cap)
+                if string is None or b'$<' in string:
+                    # Don't have this capability or it has a pause
+                    string = None
+            self.__ti[cap] = string
+        return self.__ti[cap]
+
+    def has(self, *caps):
+        return all(self.__ensure(cap) is not None for cap in caps)
+
+    def send(self, *caps):
+        # Flush TextIOWrapper to the binary IO buffer
+        sys.stdout.flush()
+        for cap in caps:
+            # We should use curses.putp here, but it's broken in
+            # Python3 because it writes directly to C's buffered
+            # stdout and there's no way to flush that.
+            if isinstance(cap, tuple):
+                s = curses.tparm(self.__ensure(cap[0]), *cap[1:])
+            else:
+                s = self.__ensure(cap)
+            sys.stdout.buffer.write(s)
+terminfo = _Terminfo()
+
+class Progress:
+    _enabled = None
+
+    def __init__(self, prefix):
+        self.__prefix = prefix
+        if Progress._enabled is None:
+            Progress._enabled = (not debug.enabled) and \
+                                terminfo.has('cr', 'el', 'rmam', 'smam')
+
+    def __enter__(self):
+        self.last = ''
+        self.update('')
+        return self
+
+    def __exit__(self, typ, value, traceback):
+        if Progress._enabled:
+            # Beginning of line and clear
+            terminfo.send('cr', 'el')
+            sys.stdout.flush()
+
+    def update(self, msg):
+        if not Progress._enabled:
+            return
+        out = '[' + self.__prefix + ']'
+        if msg:
+            out += ' ' + msg
+        if out != self.last:
+            # Beginning of line, clear line, disable wrap
+            terminfo.send('cr', 'el', 'rmam')
+            sys.stdout.write(out)
+            # Enable wrap
+            terminfo.send('smam')
+            self.last = out
+            sys.stdout.flush()
+
+class Message(collections.namedtuple(
+        'Message', 'typ filename lineno msg')):
+    def emit(self):
+        if self.filename:
+            if self.filename.startswith('./'):
+                finfo = self.filename[2:]
+            else:
+                finfo = self.filename
+        else:
+            finfo = '<no file>'
+        if self.lineno is not None:
+            finfo += ':' + str(self.lineno)
+        finfo += ': '
+        if self._color:
+            terminfo.send('bold')
+        sys.stdout.write(finfo)
+
+        if self.typ != 'info':
+            if self._color:
+                terminfo.send(('setaf', 5 if self.typ == 'warning' else 1))
+            sys.stdout.write(self.typ + ': ')
+        if self._color:
+            terminfo.send('sgr0')
+        sys.stdout.write(self.msg + '\n')
+
+    @classmethod
+    def setup_color(cls, state):
+        if state == 'never':
+            cls._color = False
+        elif state == 'always':
+            cls._color = True
+        elif state == 'auto':
+            cls._color = terminfo.has('setaf', 'bold', 'sgr0')
+        else:
+            raise ValueError('Illegal color state {:r}'.format(state))
+
+
+##################################################################
+# Task framework
+#
+
+terminate_task_loop = False
+start_time = time.time()
+
+def run_tasks(tasks, max_iterations):
+    """Execute tasks in round-robin order until all are stable.
+
+    This will also exit if terminate_task_loop is true.  Tasks may use
+    this to terminate after a fatal error (even if that fatal error
+    doesn't necessarily indicate stability; as long as re-running the
+    task will never eliminate the fatal error).
+
+    Return True if fixed-point is reached or terminate_task_loop is
+    set within max_iterations iterations.
+    """
+
+    global terminate_task_loop
+    terminate_task_loop = False
+
+    nstable = 0
+    for iteration in range(max_iterations):
+        for task in tasks:
+            if task.stable():
+                nstable += 1
+                if nstable == len(tasks):
+                    debug('fixed-point reached')
+                    return True
+            else:
+                task.run()
+                nstable = 0
+                if terminate_task_loop:
+                    debug('terminate_task_loop set')
+                    return True
+    debug('fixed-point not reached')
+    return False
+
+class TaskError(Exception):
+    pass
+
+class Task:
+    """A deterministic computation whose inputs and outputs can be captured."""
+
+    def __init__(self, db, task_id):
+        self.__db = db
+        self.__task_id = task_id
+
+    def __debug(self, string, *args):
+        if debug.enabled:
+            debug('task {}: {}', self.__task_id, string.format(*args))
+
+    def stable(self):
+        """Return True if running this task will not affect system state.
+
+        Functionally, let f be the task, and s be the system state.
+        Then s' = f(s).  If it must be that s' == s (that is, f has
+        reached a fixed point), then this function must return True.
+        """
+        last_summary = self.__db.get_summary(self.__task_id)
+        if last_summary is None:
+            # Task has never run, so running it will modify system
+            # state
+            changed = 'never run'
+        else:
+            # If any of the inputs have changed since the last run of
+            # this task, the result may change, so re-run the task.
+            # Also, it's possible something else changed an output
+            # file, in which case we also want to re-run the task, so
+            # check the outputs, too.
+            changed = self.__summary_changed(last_summary)
+
+        if changed:
+            self.__debug('unstable (changed: {})', changed)
+            return False
+        else:
+            self.__debug('stable')
+            return True
+
+    def __summary_changed(self, summary):
+        """Test if any inputs changed from summary.
+
+        Returns a string describing the changed input, or None.
+        """
+        for dep in summary['deps']:
+            fn, args, val = dep
+            method = getattr(self, '_input_' + fn, None)
+            if method is None:
+                return 'unknown dependency method {}'.format(fn)
+            if method == self._input_unstable or method(*args) != val:
+                return '{}{}'.format(fn, tuple(args))
+        return None
+
+    def _input(self, name, *args):
+        """Register an input for this run.
+
+        This calls self._input_<name>(*args) to get the value of this
+        input.  This function should run quickly and return some
+        projection of system state that affects the result of this
+        computation.
+
+        Both args and the return value must be JSON serializable.
+        """
+        method = getattr(self, '_input_' + name)
+        val = method(*args)
+        if [name, args, val] not in self.__deps:
+            self.__deps.append([name, args, val])
+        return val
+
+    def run(self):
+        # Before we run the task, pre-hash any files that were output
+        # files in the last run.  These may be input by this run and
+        # then clobbered, at which point it will be too late to get an
+        # input hash.  Ideally we would only hash files that were
+        # *both* input and output files, but latex doesn't tell us
+        # about input files that didn't exist, so if we start from a
+        # clean slate, we often require an extra run because we don't
+        # know a file is input/output until after the second run.
+        last_summary = self.__db.get_summary(self.__task_id)
+        if last_summary is not None:
+            for io_filename in last_summary['output_files']:
+                self.__debug('pre-hashing {}', io_filename)
+                hash_cache.get(io_filename)
+
+        # Run the task
+        self.__debug('running')
+        self.__deps = []
+        result = self._execute()
+
+        # Clear cached output file hashes
+        for filename in result.output_filenames:
+            hash_cache.invalidate(filename)
+
+        # If the output files change, then the computation needs to be
+        # re-run, so record them as inputs
+        for filename in result.output_filenames:
+            self._input('file', filename)
+
+        # Update task summary in database
+        self.__db.set_summary(self.__task_id,
+                              self.__make_summary(self.__deps, result))
+        del self.__deps
+
+        # Add output files to be cleaned
+        for f in result.output_filenames:
+            self.__db.add_clean(f)
+
+        try:
+            self.__db.commit()
+        except OSError as e:
+            raise TaskError('error committing control database {}: {}'.format(
+                getattr(e, 'filename', '<unknown path>'), e)) from e
+
+    def __make_summary(self, deps, run_result):
+        """Construct a new task summary."""
+        return {
+            'deps': deps,
+            'output_files': {f: hash_cache.get(f)
+                             for f in run_result.output_filenames},
+            'extra': run_result.extra,
+        }
+
+    def _execute(self):
+        """Abstract: Execute this task.
+
+        Subclasses should implement this method to execute this task.
+        This method must return a RunResult giving the inputs that
+        were used by the task and the outputs it produced.
+        """
+        raise NotImplementedError('Task._execute is abstract')
+
+    def _get_result_extra(self):
+        """Return the 'extra' result from the previous run, or None."""
+        summary = self.__db.get_summary(self.__task_id)
+        if summary is None:
+            return None
+        return summary['extra']
+
+    def report(self):
+        """Report the task's results to stdout and return exit status.
+
+        This may be called when the task has never executed.
+        Subclasses should override this.  The default implementation
+        reports nothing and returns 0.
+        """
+        return 0
+
+    # Standard input functions
+
+    def _input_env(self, var):
+        return os.environ.get(var)
+
+    def _input_file(self, path):
+        return hash_cache.get(path)
+
+    def _input_unstable(self):
+        """Mark this run as unstable, regardless of other inputs."""
+        return None
+
+    def _input_unknown_input(self):
+        """An unknown input that may change after latexrun exits.
+
+        This conservatively marks some unknown input that definitely
+        won't change while latexrun is running, but may change before
+        the user next runs latexrun.  This allows the task to
+        stabilize during this invocation, but will cause the task to
+        re-run on the next invocation.
+        """
+        return start_time
+
+class RunResult(collections.namedtuple(
+        'RunResult', 'output_filenames extra')):
+    """The result of a single task execution.
+
+    This captures all files written by the task, and task-specific
+    results that need to be persisted between runs (for example, to
+    enable reporting of a task's results).
+    """
+    pass
+
+##################################################################
+# LaTeX task
+#
+
+def normalize_input_path(path):
+    # Resolve the directory of the input path, but leave the file
+    # component alone because it affects TeX's behavior.
+    head, tail = os.path.split(path)
+    npath = os.path.join(os.path.realpath(head), tail)
+    return os.path.relpath(path)
+
+class LaTeX(Task):
+    def __init__(self, db, tex_filename, cmd, cmd_args, obj_dir, nowarns):
+        super().__init__(db, 'latex::' + normalize_input_path(tex_filename))
+        self.__tex_filename = tex_filename
+        self.__cmd = cmd
+        self.__cmd_args = cmd_args
+        self.__obj_dir = obj_dir
+        self.__nowarns = nowarns
+
+        self.__pass = 0
+
+    def _input_args(self):
+        # If filename starts with a character the tex command-line
+        # treats specially, then tweak it so it doesn't.
+        filename = self.__tex_filename
+        if filename.startswith(('-', '&', '\\')):
+            filename = './' + filename
+        # XXX Put these at the beginning in case the provided
+        # arguments are malformed.  Might want to do a best-effort
+        # check for incompatible user-provided arguments (note:
+        # arguments can be given with one or two dashes and those with
+        # values can use an equals or a space).
+        return [self.__cmd] + self.__cmd_args + \
+            ['-interaction', 'nonstopmode', '-recorder',
+             '-output-directory', self.__obj_dir, filename]
+
+    def _execute(self):
+        # Run latex
+        self.__pass += 1
+        args = self._input('args')
+        debug('running {}', args)
+        try:
+            os.makedirs(self.__obj_dir, exist_ok=True)
+        except OSError as e:
+            raise TaskError('failed to create %s: ' % self.__obj_dir + str(e)) \
+                from e
+        try:
+            verbose_cmd(args)
+            p = subprocess.Popen(args,
+                                 stdin=subprocess.DEVNULL,
+                                 stdout=subprocess.PIPE,
+                                 stderr=subprocess.STDOUT)
+            stdout, has_errors, missing_includes = self.__feed_terminal(p.stdout)
+            status = p.wait()
+        except OSError as e:
+            raise TaskError('failed to execute latex task: ' + str(e)) from e
+
+        # Register environment variable inputs
+        for env_var in ['TEXMFOUTPUT', 'TEXINPUTS', 'TEXFORMATS', 'TEXPOOL',
+                        'TFMFONTS', 'PATH']:
+            self._input('env', env_var)
+
+        jobname, outname = self.__parse_jobname(stdout)
+        inputs, outputs = self.__parse_recorder(jobname)
+
+        # LaTeX overwrites its own inputs.  Mark its output files as
+        # clobbered before we hash its input files.
+        for path in outputs:
+            # In some abort cases (e.g., >=100 errors), LaTeX claims
+            # output files that don't actually exist.
+            if os.path.exists(path):
+                hash_cache.clobber(path)
+        # Depend on input files.  Task.run pre-hashed outputs from the
+        # previous run, so if this isn't the first run and as long as
+        # the set of outputs didn't change, we'll be able to get the
+        # input hashes, even if they were clobbered.
+        for path in inputs:
+            self._input('file', path)
+
+        if missing_includes:
+            # Missing \includes are tricky.  Ideally we'd depend on
+            # the absence of some file, but in fact we'd have to
+            # depend on the failure of a whole kpathsea lookup.
+            # Rather than try to be clever, just mark this as an
+            # unknown input so we'll run at least once on the next
+            # invocation.
+            self._input('unknown_input')
+
+        if not self.__create_outdirs(stdout) and has_errors:
+            # LaTeX reported unrecoverable errors (other than output
+            # directory errors, which we just fixed).  We could
+            # continue to stabilize the document, which may change
+            # some of the other problems reported (but not the
+            # unrecoverable errors), or we can just abort now and get
+            # back to the user quickly with the major errors.  We opt
+            # for the latter.
+            global terminate_task_loop
+            terminate_task_loop = True
+            # This error could depend on something we failed to track.
+            # It would be really confusing if we continued to report
+            # the error after the user fixed it, so be conservative
+            # and force a re-run next time.
+            self._input('unknown_input')
+
+        return RunResult(outputs,
+                         {'jobname': jobname, 'outname': outname,
+                          'status': status})
+
+    def __feed_terminal(self, stdout):
+        prefix = 'latex'
+        if self.__pass > 1:
+            prefix += ' ({})'.format(self.__pass)
+        with Progress(prefix) as progress:
+            buf = []
+            filt = LaTeXFilter()
+            while True:
+                # Use os.read to read only what's available on the pipe,
+                # without waiting to fill a buffer
+                data = os.read(stdout.fileno(), 4096)
+                if not data:
+                    break
+                # See "A note about encoding" above
+                data = data.decode('ascii', errors='surrogateescape')
+                buf.append(data)
+                filt.feed(data)
+                file_stack = filt.get_file_stack()
+                if file_stack:
+                    tos = file_stack[-1]
+                    if tos.startswith('./'):
+                        tos = tos[2:]
+                    progress.update('>' * len(file_stack) + ' ' + tos)
+                else:
+                    progress.update('')
+
+            # Were there unrecoverable errors?
+            has_errors = any(msg.typ == 'error' for msg in filt.get_messages())
+
+            return ''.join(buf), has_errors, filt.has_missing_includes()
+
+    def __parse_jobname(self, stdout):
+        """Extract the job name and output name from latex's output.
+
+        We get these from latex because they depend on complicated
+        file name parsing rules, are affected by arguments like
+        -output-directory, and may be just "texput" if things fail
+        really early.  The output name may be None if there were no
+        pages of output.
+        """
+        jobname = outname = None
+        for m in re.finditer(r'^Transcript written on "?(.*)\.log"?\.$', stdout,
+                             re.MULTILINE | re.DOTALL):
+            jobname = m.group(1).replace('\n', '')
+        if jobname is None:
+            print(stdout, file=sys.stderr)
+            raise TaskError('failed to extract job name from latex log')
+        for m in re.finditer(r'^Output written on "?(.*\.[^ ."]+)"? \([0-9]+ page',
+                             stdout, re.MULTILINE | re.DOTALL):
+            outname = m.group(1).replace('\n', '')
+        if outname is None and not \
+           re.search(r'^No pages of output\.$|^! Emergency stop\.$'
+                     r'|^!  ==> Fatal error occurred, no output PDF file produced!$',
+                     stdout, re.MULTILINE):
+            print(stdout, file=sys.stderr)
+            raise TaskError('failed to extract output name from latex log')
+
+        # LuaTeX (0.76.0) doesn't include the output directory in the
+        # logged transcript or output file name.
+        if os.path.basename(jobname) == jobname and \
+           os.path.exists(os.path.join(self.__obj_dir, jobname + '.log')):
+            jobname = os.path.join(self.__obj_dir, jobname)
+            if outname is not None:
+                outname = os.path.join(self.__obj_dir, outname)
+
+        return jobname, outname
+
+    def __parse_recorder(self, jobname):
+        """Parse file recorder output."""
+        # XXX If latex fails because a file isn't found, that doesn't
+        # go into the .fls file, but creating that file will affect
+        # the computation, so it should be included as an input.
+        # Though it's generally true that files can be added earlier
+        # in search paths and will affect the output without us knowing.
+        #
+        # XXX This is a serious problem for bibtex, since the first
+        # run won't depend on the .bbl file!  But maybe the .aux file
+        # will always cause a re-run, at which point the .bbl will
+        # exist?
+        filename = jobname + '.fls'
+        try:
+            recorder = open(filename)
+        except OSError as e:
+            raise TaskError('failed to open file recorder output: ' + str(e)) \
+                from e
+        pwd, inputs, outputs = '', set(), set()
+        for linenum, line in enumerate(recorder):
+            parts = line.rstrip('\n').split(' ', 1)
+            if parts[0] == 'PWD':
+                pwd = parts[1]
+            elif parts[0] in ('INPUT', 'OUTPUT'):
+                if parts[1].startswith('/'):
+                    path = parts[1]
+                else:
+                    # Try to make "nice" paths, especially for clean
+                    path = os.path.relpath(os.path.join(pwd, parts[1]))
+                if parts[0] == 'INPUT':
+                    inputs.add(path)
+                else:
+                    outputs.add(path)
+            else:
+                raise TaskError('syntax error on line {} of {}'
+                                .format(linenum, filename))
+        # Ironically, latex omits the .fls file itself
+        outputs.add(filename)
+        return inputs, outputs
+
+    def __create_outdirs(self, stdout):
+        # In some cases, such as \include'ing a file from a
+        # subdirectory, TeX will attempt to create files in
+        # subdirectories of the output directory that don't exist.
+        # Detect this, create the output directory, and re-run.
+        m = re.search('^! I can\'t write on file `(.*)\'\\.$', stdout, re.M)
+        if m and m.group(1).find('/') > 0 and '../' not in m.group(1):
+            debug('considering creating output sub-directory for {}'.
+                  format(m.group(1)))
+            subdir = os.path.dirname(m.group(1))
+            newdir = os.path.join(self.__obj_dir, subdir)
+            if os.path.isdir(subdir) and not os.path.isdir(newdir):
+                debug('creating output subdirectory {}'.format(newdir))
+                try:
+                    mkdir_p(newdir)
+                except OSError as e:
+                    raise TaskError('failed to create output subdirectory: ' +
+                                    str(e)) from e
+                self._input('unstable')
+                return True
+
+    def report(self):
+        extra = self._get_result_extra()
+        if extra is None:
+            return 0
+
+        # Parse the log
+        logfile = open(extra['jobname'] + '.log', 'rt', errors='surrogateescape')
+        for msg in self.__clean_messages(
+                LaTeXFilter(self.__nowarns).feed(
+                    logfile.read(), True).get_messages()):
+            msg.emit()
+
+        # Return LaTeX's exit status
+        return extra['status']
+
+    def __clean_messages(self, msgs):
+        """Make some standard log messages more user-friendly."""
+        have_undefined_reference = False
+        for msg in msgs:
+            if msg.msg == '==> Fatal error occurred, no output PDF file produced!':
+                msg = msg._replace(typ='info',
+                                   msg='Fatal error (no output file produced)')
+            if msg.msg.startswith('[LaTeX] '):
+                # Strip unnecessary package name
+                msg = msg._replace(msg=msg.msg.split(' ', 1)[1])
+            if re.match(r'Reference .* undefined', msg.msg):
+                have_undefined_reference = True
+            if have_undefined_reference and \
+               re.match(r'There were undefined references', msg.msg):
+                # LaTeX prints this at the end so the user knows it's
+                # worthwhile looking back at the log.  Since latexrun
+                # makes the earlier messages obvious, this is
+                # redundant.
+                continue
+            yield msg
+
+    def get_tex_filename(self):
+        return self.__tex_filename
+
+    def get_jobname(self):
+        extra = self._get_result_extra()
+        if extra is None:
+            return None
+        return extra['jobname']
+
+    def get_outname(self):
+        extra = self._get_result_extra()
+        if extra is None:
+            return None
+        return extra['outname']
+
+    def get_status(self):
+        extra = self._get_result_extra()
+        if extra is None:
+            return None
+        return extra['status']
+
+class LaTeXCommit(Task):
+    def __init__(self, db, latex_task, output_path):
+        super().__init__(db, 'latex_commit::' +
+                         normalize_input_path(latex_task.get_tex_filename()))
+        self.__latex_task = latex_task
+        self.__output_path = output_path
+        self.status = 'There were errors'
+
+    def _input_latex(self):
+        return self.__latex_task.get_status(), self.__latex_task.get_outname()
+
+    def _execute(self):
+        self.status = 'There were errors'
+
+        # If latex succeeded with output, atomically commit the output
+        status, outname = self._input('latex')
+        if status != 0 or outname is None:
+            debug('not committing (status {}, outname {})', status, outname)
+            if outname is None:
+                self.status = 'No pages of output'
+            return RunResult([], None)
+
+        commit = self.__output_path or os.path.basename(outname)
+        if os.path.abspath(commit) == os.path.abspath(outname):
+            debug('skipping commit (outname is commit name)')
+            self.status = None
+            return RunResult([], None)
+
+        try:
+            if os.path.exists(commit) and filecmp.cmp(outname, commit):
+                debug('skipping commit ({} and {} are identical)',
+                      outname, commit)
+                # To avoid confusion, touch the output file
+                open(outname, 'r+b').close()
+            else:
+                debug('commiting {} to {}', outname, commit)
+                shutil.copy(outname, outname + '~')
+                os.rename(outname + '~', commit)
+        except OSError as e:
+            raise TaskError('error committing latex output: {}'.format(e)) from e
+        self._input('file', outname)
+        self.status = None
+        return RunResult([commit], None)
+
+class LaTeXFilter:
+    TRACE = False               # Set to enable detailed parse tracing
+
+    def __init__(self, nowarns=[]):
+        self.__data = ''
+        self.__restart_pos = 0
+        self.__restart_file_stack = []
+        self.__restart_messages_len = 0
+        self.__messages = []
+        self.__first_file = None
+        self.__fatal_error = False
+        self.__missing_includes = False
+        self.__pageno = 1
+        self.__restart_pageno = 1
+
+        self.__suppress = {cls: 0 for cls in nowarns}
+
+    def feed(self, data, eof=False):
+        """Feed LaTeX log data to the parser.
+
+        The log data can be from LaTeX's standard output, or from the
+        log file.  If there will be no more data, set eof to True.
+        """
+
+        self.__data += data
+        self.__data_complete = eof
+
+        # Reset to last known-good restart point
+        self.__pos = self.__restart_pos
+        self.__file_stack = self.__restart_file_stack.copy()
+        self.__messages = self.__messages[:self.__restart_messages_len]
+        self.__lstart = self.__lend = -1
+        self.__pageno = self.__restart_pageno
+
+        # Parse forward
+        while self.__pos < len(self.__data):
+            self.__noise()
+
+        # Handle suppressed warnings
+        if eof:
+            msgs = ['%d %s warning%s' % (count, cls, "s" if count > 1 else "")
+                    for cls, count in self.__suppress.items() if count]
+            if msgs:
+                self.__message('info', None,
+                               '%s not shown (use -Wall to show them)' %
+                               ', '.join(msgs), filename=self.__first_file)
+
+        if eof and len(self.__file_stack) and not self.__fatal_error:
+            # Fatal errors generally cause TeX to "succumb" without
+            # closing the file stack, so don't complain in that case.
+            self.__message('warning', None,
+                           "unbalanced `(' in log; file names may be wrong")
+        return self
+
+    def get_messages(self):
+        """Return a list of warning and error Messages."""
+        return self.__messages
+
+    def get_file_stack(self):
+        """Return the file stack for the data that has been parsed.
+
+        This results a list from outermost file to innermost file.
+        The list may be empty.
+        """
+
+        return self.__file_stack
+
+    def has_missing_includes(self):
+        """Return True if the log reported missing \\include files."""
+        return self.__missing_includes
+
+    def __save_restart_point(self):
+        """Save the current state as a known-good restart point.
+
+        On the next call to feed, the parser will reset to this point.
+        """
+        self.__restart_pos = self.__pos
+        self.__restart_file_stack = self.__file_stack.copy()
+        self.__restart_messages_len = len(self.__messages)
+        self.__restart_pageno = self.__pageno
+
+    def __message(self, typ, lineno, msg, cls=None, filename=None):
+        if cls is not None and cls in self.__suppress:
+            self.__suppress[cls] += 1
+            return
+        filename = filename or (self.__file_stack[-1] if self.__file_stack
+                                else self.__first_file)
+        self.__messages.append(Message(typ, filename, lineno, msg))
+
+    def __ensure_line(self):
+        """Update lstart and lend."""
+        if self.__lstart <= self.__pos < self.__lend:
+            return
+        self.__lstart = self.__data.rfind('\n', 0, self.__pos) + 1
+        self.__lend = self.__data.find('\n', self.__pos) + 1
+        if self.__lend == 0:
+            self.__lend = len(self.__data)
+
+    @property
+    def __col(self):
+        """The 0-based column number of __pos."""
+        self.__ensure_line()
+        return self.__pos - self.__lstart
+
+    @property
+    def __avail(self):
+        return self.__pos < len(self.__data)
+
+    def __lookingat(self, needle):
+        return self.__data.startswith(needle, self.__pos)
+
+    def __lookingatre(self, regexp, flags=0):
+        return re.compile(regexp, flags=flags).match(self.__data, self.__pos)
+
+    def __skip_line(self):
+        self.__ensure_line()
+        self.__pos = self.__lend
+
+    def __consume_line(self, unwrap=False):
+        self.__ensure_line()
+        data = self.__data[self.__pos:self.__lend]
+        self.__pos = self.__lend
+        if unwrap:
+            # TeX helpfully wraps all terminal output at 79 columns
+            # (max_print_line).  If requested, unwrap it.  There's
+            # simply no way to do this perfectly, since there could be
+            # a line that happens to be 79 columns.
+            #
+            # We check for >=80 because a bug in LuaTeX causes it to
+            # wrap at 80 columns instead of 79 (LuaTeX #900).
+            while self.__lend - self.__lstart >= 80:
+                if self.TRACE: print('<{}> wrapping'.format(self.__pos))
+                self.__ensure_line()
+                data = data[:-1] + self.__data[self.__pos:self.__lend]
+                self.__pos = self.__lend
+        return data
+
+    # Parser productions
+
+    def __noise(self):
+        # Most of TeX's output is line noise that combines error
+        # messages, warnings, file names, user errors and warnings,
+        # and echos of token lists and other input.  This attempts to
+        # tease these apart, paying particular attention to all of the
+        # places where TeX echos input so that parens in the input do
+        # not confuse the file name scanner.  There are three
+        # functions in TeX that echo input: show_token_list (used by
+        # runaway and show_context, which is used by print_err),
+        # short_display (used by overfull/etc h/vbox), and show_print
+        # (used in issue_message and the same places as
+        # show_token_list).
+        lookingat, lookingatre = self.__lookingat, self.__lookingatre
+        if self.__col == 0:
+            # The following messages are always preceded by a newline
+            if lookingat('! '):
+                return self.__errmessage()
+            if lookingat('!pdfTeX error: '):
+                return self.__pdftex_fail()
+            if lookingat('Runaway '):
+                return self.__runaway()
+            if lookingatre(r'(Overfull|Underfull|Loose|Tight) \\[hv]box \('):
+                return self.__bad_box()
+            if lookingatre('(Package |Class |LaTeX |pdfTeX )?(\w+ )?warning: ', re.I):
+                return self.__generic_warning()
+            if lookingatre('No file .*\\.tex\\.$', re.M):
+                # This happens with \includes of missing files.  For
+                # whatever reason, LaTeX doesn't consider this even
+                # worth a warning, but I do!
+                self.__message('warning', None,
+                               self.__simplify_message(
+                                   self.__consume_line(unwrap=True).strip()))
+                self.__missing_includes = True
+                return
+            # Other things that are common and irrelevant
+            if lookingatre(r'(Package|Class|LaTeX) (\w+ )?info: ', re.I):
+                return self.__generic_info()
+            if lookingatre(r'(Document Class|File|Package): '):
+                # Output from "\ProvidesX"
+                return self.__consume_line(unwrap=True)
+            if lookingatre(r'\\\w+=\\[a-z]+\d+\n'):
+                # Output from "\new{count,dimen,skip,...}"
+                return self.__consume_line(unwrap=True)
+
+        # print(self.__data[self.__lstart:self.__lend].rstrip())
+        # self.__pos = self.__lend
+        # return
+
+        # Now that we've substantially reduced the spew and hopefully
+        # eliminated all input echoing, we're left with the file name
+        # stack, page outs, and random other messages from both TeX
+        # and various packages.  We'll assume at this point that all
+        # parentheses belong to the file name stack or, if they're in
+        # random other messages, they're at least balanced and nothing
+        # interesting happens between them.  For page outs, ship_out
+        # prints a space if not at the beginning of a line, then a
+        # "[", then the page number being shipped out (this is
+        # usually, but not always, followed by "]").
+        m = re.compile(r'[(){}\n]|(?<=[\n ])\[\d+', re.M).\
+            search(self.__data, self.__pos)
+        if m is None:
+            self.__pos = len(self.__data)
+            return
+        self.__pos = m.start() + 1
+        ch = self.__data[m.start()]
+        if ch == '\n':
+            # Save this as a known-good restart point for incremental
+            # parsing, since we definitely didn't match any of the
+            # known message types above.
+            self.__save_restart_point()
+        elif ch == '[':
+            # This is printed at the end of a page, so we're beginning
+            # page n+1.
+            self.__pageno = int(self.__lookingatre(r'\d+').group(0)) + 1
+        elif ((self.__data.startswith('`', m.start() - 1) or
+               self.__data.startswith('`\\', m.start() - 2)) and
+               self.__data.startswith('\'', m.start() + 1)):
+            # (, ), {, and } sometimes appear in TeX's error
+            # descriptions, but they're always in `'s (and sometimes
+            # backslashed)
+            return
+        elif ch == '(':
+            # XXX Check that the stack doesn't drop to empty and then re-grow
+            first = self.__first_file is None and self.__col == 1
+            filename = self.__filename()
+            self.__file_stack.append(filename)
+            if first:
+                self.__first_file = filename
+            if self.TRACE:
+                print('<{}>{}enter {}'.format(
+                    m.start(), ' '*len(self.__file_stack), filename))
+        elif ch == ')':
+            if len(self.__file_stack):
+                if self.TRACE:
+                    print('<{}>{}exit {}'.format(
+                        m.start(), ' '*len(self.__file_stack),
+                        self.__file_stack[-1]))
+                self.__file_stack.pop()
+            else:
+                self.__message('warning', None,
+                               "extra `)' in log; file names may be wrong ")
+        elif ch == '{':
+            # TeX uses this for various things we want to ignore, like
+            # file names and print_mark.  Consume up to the '}'
+            epos = self.__data.find('}', self.__pos)
+            if epos != -1:
+                self.__pos = epos + 1
+            else:
+                self.__message('warning', None,
+                               "unbalanced `{' in log; file names may be wrong")
+        elif ch == '}':
+            self.__message('warning', None,
+                           "extra `}' in log; file names may be wrong")
+
+    def __filename(self):
+        initcol = self.__col
+        first = True
+        name = ''
+        # File names may wrap, but if they do, TeX will always print a
+        # newline before the open paren
+        while first or (initcol == 1 and self.__lookingat('\n')
+                        and self.__col >= 79):
+            if not first:
+                self.__pos += 1
+            m = self.__lookingatre(r'[^(){} \n]*')
+            name += m.group()
+            self.__pos = m.end()
+            first = False
+        return name
+
+    def __simplify_message(self, msg):
+        msg = re.sub(r'^(?:Package |Class |LaTeX |pdfTeX )?([^ ]+) (?:Error|Warning): ',
+                     r'[\1] ', msg, flags=re.I)
+        msg = re.sub(r'\.$', '', msg)
+        msg = re.sub(r'has occurred (while \\output is active)', r'\1', msg)
+        return msg
+
+    def __errmessage(self):
+        # Procedure print_err (including \errmessage, itself used by
+        # LaTeX's \GenericError and all of its callers), as well as
+        # fatal_error.  Prints "\n!  " followed by error text
+        # ("Emergency stop" in the case of fatal_error).  print_err is
+        # always followed by a call to error, which prints a period,
+        # and a newline...
+        msg = self.__consume_line(unwrap=True)[1:].strip()
+        is_fatal_error = (msg == 'Emergency stop.')
+        msg = self.__simplify_message(msg)
+        # ... and then calls show_context, which prints the input
+        # stack as pairs of lines giving the context.  These context
+        # lines are truncated so they never wrap.  Each pair of lines
+        # will start with either "<something> " if the context is a
+        # token list, "<*> " for terminal input (or command line),
+        # "<read ...>" for stream reads, something like "\macroname
+        # #1->" for macros (though everything after \macroname is
+        # subject to being elided as "..."), or "l.[0-9]+ " if it's a
+        # file.  This is followed by the errant input with a line
+        # break where the error occurred.
+        lineno = None
+        found_context = False
+        stack = []
+        while self.__avail:
+            m1 = self.__lookingatre(r'<([a-z ]+|\*|read [^ >]*)> |\\.*(->|...)')
+            m2 = self.__lookingatre('l\.[0-9]+ ')
+            if m1:
+                found_context = True
+                pre = self.__consume_line().rstrip('\n')
+                stack.append(pre)
+            elif m2:
+                found_context = True
+                pre = self.__consume_line().rstrip('\n')
+                info, rest = pre.split(' ', 1)
+                lineno = int(info[2:])
+                stack.append(rest)
+            elif found_context:
+                # Done with context
+                break
+            if found_context:
+                # Consume the second context line
+                post = self.__consume_line().rstrip('\n')
+                # Clean up goofy trailing ^^M TeX sometimes includes
+                post = re.sub(r'\^\^M$', '', post)
+                if post[:len(pre)].isspace() and not post.isspace():
+                    stack.append(len(stack[-1]))
+                    stack[-2] += post[len(pre):]
+            else:
+                # If we haven't found the context, skip the line.
+                self.__skip_line()
+        stack_msg = ''
+        for i, trace in enumerate(stack):
+            stack_msg += ('\n         ' + (' ' * trace) + '^'
+                          if isinstance(trace, int) else
+                          '\n      at ' + trace.rstrip() if i == 0 else
+                          '\n    from ' + trace.rstrip())
+
+        if is_fatal_error:
+            # fatal_error always prints one additional line of message
+            info = self.__consume_line().strip()
+            if info.startswith('*** '):
+                info = info[4:]
+            msg += ': '  + info.lstrip('(').rstrip(')')
+
+        self.__message('error', lineno, msg + stack_msg)
+        self.__fatal_error = True
+
+    def __pdftex_fail(self):
+        # Procedure pdftex_fail.  Prints "\n!pdfTeX error: ", the
+        # message, and a newline.  Unlike print_err, there's never
+        # context.
+        msg = self.__consume_line(unwrap=True)[1:].strip()
+        msg = self.__simplify_message(msg)
+        self.__message('error', None, msg)
+
+    def __runaway(self):
+        # Procedure runaway.  Prints "\nRunaway ...\n" possibly
+        # followed by token list (user text).  Always followed by a
+        # call to print_err, so skip lines until we see the print_err.
+        self.__skip_line()      # Skip "Runaway ...\n"
+        if not self.__lookingat('! ') and self.__avail:
+            # Skip token list, which is limited to one line
+            self.__skip_line()
+
+    def __bad_box(self):
+        # Function hpack and vpack.  hpack prints a warning, a
+        # newline, then a short_display of the offending text.
+        # Unfortunately, there's nothing indicating the end of the
+        # offending text, but it should be on one (possible wrapped)
+        # line.  vpack prints a warning and then, *unless output is
+        # active*, a newline.  The missing newline is probably a bug,
+        # but it sure makes our lives harder.
+        origpos = self.__pos
+        msg = self.__consume_line()
+        m = re.search(r' in (?:paragraph|alignment) at lines ([0-9]+)--([0-9]+)', msg) or \
+            re.search(r' detected at line ([0-9]+)', msg)
+        if m:
+            # Sometimes TeX prints crazy line ranges like "at lines
+            # 8500--250".  The lower number seems roughly sane, so use
+            # that.  I'm not sure what causes this, but it may be
+            # related to shipout routines messing up line registers.
+            lineno = min(int(m.group(1)), int(m.groups()[-1]))
+            msg = msg[:m.start()]
+        else:
+            m = re.search(r' while \\output is active', msg)
+            if m:
+                lineno = None
+                msg = msg[:m.end()]
+            else:
+                self.__message('warning', None,
+                               'malformed bad box message in log')
+                return
+        # Back up to the end of the known message text
+        self.__pos = origpos + m.end()
+        if self.__lookingat('\n'):
+            # We have a newline, so consume it and look for the
+            # offending text.
+            self.__pos += 1
+            # If there is offending text, it will start with a font
+            # name, which will start with a \.
+            if 'hbox' in msg and self.__lookingat('\\'):
+                self.__consume_line(unwrap=True)
+        msg = self.__simplify_message(msg) + ' (page {})'.format(self.__pageno)
+        cls = msg.split(None, 1)[0].lower()
+        self.__message('warning', lineno, msg, cls=cls)
+
+    def __generic_warning(self):
+        # Warnings produced by LaTeX's \GenericWarning (which is
+        # called by \{Package,Class}Warning and \@latex@warning),
+        # warnings produced by pdftex_warn, and other random warnings.
+        msg, cls = self.__generic_info()
+        # Most warnings include an input line emitted by \on@line
+        m = re.search(' on input line ([0-9]+)', msg)
+        if m:
+            lineno = int(m.group(1))
+            msg = msg[:m.start()]
+        else:
+            lineno = None
+        msg = self.__simplify_message(msg)
+        self.__message('warning', lineno, msg, cls=cls)
+
+    def __generic_info(self):
+        # Messages produced by LaTeX's \Generic{Error,Warning,Info}
+        # and things that look like them
+        msg = self.__consume_line(unwrap=True).strip()
+        # Package and class messages are continued with lines
+        # containing '(package name)            '
+        pkg_name = msg.split(' ', 2)[1]
+        prefix = '(' + pkg_name + ')            '
+        while self.__lookingat(prefix):
+            # Collect extra lines.  It's important that we keep these
+            # because they may contain context information like line
+            # numbers.
+            extra = self.__consume_line(unwrap=True)
+            msg += ' ' + extra[len(prefix):].strip()
+        return msg, pkg_name.lower()
+
+##################################################################
+# BibTeX task
+#
+
+class BibTeX(Task):
+    def __init__(self, db, latex_task, cmd, cmd_args, nowarns, obj_dir):
+        super().__init__(db, 'bibtex::' + normalize_input_path(
+            latex_task.get_tex_filename()))
+        self.__latex_task = latex_task
+        self.__cmd = cmd
+        self.__cmd_args = cmd_args
+        self.__obj_dir = obj_dir
+
+    def stable(self):
+        # If bibtex doesn't have its inputs, then it's stable because
+        # it has no effect on system state.
+        jobname = self.__latex_task.get_jobname()
+        if jobname is None:
+            # We don't know where the .aux file is until latex has run
+            return True
+        if not os.path.exists(jobname + '.aux'):
+            # Input isn't ready, so bibtex will simply fail without
+            # affecting system state.  Hence, this task is trivially
+            # stable.
+            return True
+        if not self.__find_bib_cmds(os.path.dirname(jobname), jobname + '.aux'):
+            # The tex file doesn't refer to any bibliographic data, so
+            # don't run bibtex.
+            return True
+
+        return super().stable()
+
+    def __find_bib_cmds(self, basedir, auxname, stack=()):
+        debug('scanning for bib commands in {}'.format(auxname))
+        if auxname in stack:
+            raise TaskError('.aux file loop')
+        stack = stack + (auxname,)
+
+        try:
+            aux_data = open(auxname, errors='surrogateescape').read()
+        except FileNotFoundError:
+            # The aux file may not exist if latex aborted
+            return False
+        if re.search(r'^\\bibstyle\{', aux_data, flags=re.M) or \
+           re.search(r'^\\bibdata\{',  aux_data, flags=re.M):
+            return True
+
+        if re.search(r'^\\abx@aux@cite\{', aux_data, flags=re.M):
+            # biber citation
+            return True
+
+        # Recurse into included aux files (see aux_input_command), in
+        # case \bibliography appears in an \included file.
+        for m in re.finditer(r'^\\@input\{([^}]*)\}', aux_data, flags=re.M):
+            if self.__find_bib_cmds(basedir, os.path.join(basedir, m.group(1)),
+                                    stack):
+                return True
+
+        return False
+
+    def _input_args(self):
+        if self.__is_biber():
+            aux_name = os.path.basename(self.__latex_task.get_jobname())
+        else:
+            aux_name = os.path.basename(self.__latex_task.get_jobname()) + '.aux'
+        return [self.__cmd] + self.__cmd_args + [aux_name]
+
+    def _input_cwd(self):
+        return os.path.dirname(self.__latex_task.get_jobname())
+
+    def _input_auxfile(self, auxname):
+        # We don't consider the .aux files regular inputs.
+        # Instead, we extract just the bit that BibTeX cares about
+        # and depend on that.  See get_aux_command_and_process in
+        # bibtex.web.
+        debug('hashing filtered aux file {}', auxname)
+        try:
+            with open(auxname, 'rb') as aux:
+                h = hashlib.sha256()
+                for line in aux:
+                    if line.startswith((b'\\citation{', b'\\bibdata{',
+                                        b'\\bibstyle{', b'\\@input{',
+                                        b'\\abx@aux@cite{')):
+                        h.update(line)
+                return h.hexdigest()
+        except FileNotFoundError:
+            debug('{} does not exist', auxname)
+            return None
+
+    def __path_join(self, first, rest):
+        if rest is None:
+            # Append ':' to keep the default search path
+            return first + ':'
+        return first + ':' + rest
+
+    def __is_biber(self):
+        return "biber" in self.__cmd
+
+    def _execute(self):
+        # This gets complicated when \include is involved.  \include
+        # switches to a different aux file and records its path in the
+        # main aux file.  However, BibTeX does not consider this path
+        # to be relative to the location of the main aux file, so we
+        # have to run BibTeX *in the output directory* for it to
+        # follow these includes (there's no way to tell BibTeX other
+        # locations to search).  Unfortunately, this means BibTeX will
+        # no longer be able to find local bib or bst files, but so we
+        # tell it where to look by setting BIBINPUTS and BSTINPUTS
+        # (luckily we can control this search).  We have to pass this
+        # same environment down to Kpathsea when we resolve the paths
+        # in BibTeX's log.
+        args, cwd = self._input('args'), self._input('cwd')
+        debug('running {} in {}', args, cwd)
+
+        env = os.environ.copy()
+        env['BIBINPUTS'] = self.__path_join(os.getcwd(), env.get('BIBINPUTS'))
+        env['BSTINPUTS'] = self.__path_join(os.getcwd(), env.get('BSTINPUTS'))
+
+        try:
+            verbose_cmd(args, cwd, env)
+            p = subprocess.Popen(args, cwd=cwd, env=env,
+                                 stdin=subprocess.DEVNULL,
+                                 stdout=subprocess.PIPE,
+                                 stderr=subprocess.STDOUT)
+            stdout = self.__feed_terminal(p.stdout)
+            status = p.wait()
+        except OSError as e:
+            raise TaskError('failed to execute bibtex task: ' + str(e)) from e
+
+        inputs, auxnames, outbase = self.__parse_inputs(stdout, cwd, env)
+        if not inputs and not auxnames:
+            # BibTeX failed catastrophically.
+            print(stdout, file=sys.stderr)
+            raise TaskError('failed to execute bibtex task')
+
+        # Register environment variable inputs
+        for env_var in ['TEXMFOUTPUT', 'BSTINPUTS', 'BIBINPUTS', 'PATH']:
+            self._input('env', env_var)
+
+        # Register file inputs
+        for path in auxnames:
+            self._input('auxfile', path)
+        for path in inputs:
+            self._input('file', path)
+
+        if self.__is_biber():
+            outbase = os.path.join(cwd, outbase)
+        outputs = [outbase + '.bbl', outbase + '.blg']
+        return RunResult(outputs, {'outbase': outbase, 'status': status,
+                                   'inputs': inputs})
+
+    def __feed_terminal(self, stdout):
+        with Progress('bibtex') as progress:
+            buf, linebuf = [], ''
+            while True:
+                data = os.read(stdout.fileno(), 4096)
+                if not data:
+                    break
+                # See "A note about encoding" above
+                data = data.decode('ascii', errors='surrogateescape')
+                buf.append(data)
+                linebuf += data
+                while '\n' in linebuf:
+                    line, _, linebuf = linebuf.partition('\n')
+                    if line.startswith('Database file'):
+                        progress.update(line.split(': ', 1)[1])
+        return ''.join(buf)
+
+    def __parse_inputs(self, log, cwd, env):
+        # BibTeX conveniently logs every file that it opens, and its
+        # log is actually sensible (see calls to a_open_in in
+        # bibtex.web.)  The only trick is that these file names are
+        # pre-kpathsea lookup and may be relative to the directory we
+        # ran BibTeX in.
+        #
+        # Because BibTeX actually depends on very little in the .aux
+        # file (and it's likely other things will change in the .aux
+        # file), we don't count the whole .aux file as an input, but
+        # instead depend only on the lines that matter to BibTeX.
+        kpathsea = Kpathsea('bibtex')
+        inputs = []
+        auxnames = []
+        outbase = None
+        for line in log.splitlines():
+            m = re.match('(?:The top-level auxiliary file:'
+                         '|A level-[0-9]+ auxiliary file:) (.*)', line)
+            if m:
+                auxnames.append(os.path.join(cwd, m.group(1)))
+                continue
+            m = re.match('(?:(The style file:)|(Database file #[0-9]+:)) (.*)',
+                         line)
+            if m:
+                filename = m.group(3)
+                if m.group(1):
+                    filename = kpathsea.find_file(filename, 'bst', cwd, env)
+                elif m.group(2):
+                    filename = kpathsea.find_file(filename, 'bib', cwd, env)
+
+                # If this path is relative to the source directory,
+                # clean it up for error reporting and portability of
+                # the dependency DB
+                if filename.startswith('/'):
+                    relname = os.path.relpath(filename)
+                    if '../' not in relname:
+                        filename = relname
+
+                inputs.append(filename)
+
+            # biber output
+            m = re.search("Found BibTeX data source '(.*?)'",
+                         line)
+            if m:
+                filename = m.group(1)
+                inputs.append(filename)
+
+            m = re.search("Logfile is '(.*?)'", line)
+            if m:
+                outbase = m.group(1)[:-4]
+
+        if outbase is None:
+            outbase = auxnames[0][:-4]
+
+        return inputs, auxnames, outbase
+
+    def report(self):
+        extra = self._get_result_extra()
+        if extra is None:
+            return 0
+
+        # Parse and pretty-print the log
+        log = open(extra['outbase'] + '.blg', 'rt').read()
+        inputs = extra['inputs']
+        for msg in BibTeXFilter(log, inputs).get_messages():
+            msg.emit()
+
+        # BibTeX exits with 1 if there are warnings, 2 if there are
+        # errors, and 3 if there are fatal errors (sysdep.h).
+        # Translate to a normal UNIX exit status.
+        if extra['status'] >= 2:
+            return 1
+        return 0
+
+class BibTeXFilter:
+    def __init__(self, data, inputs):
+        self.__inputs = inputs
+        self.__key_locs = None
+
+        self.__messages = []
+
+        prev_line = ''
+        for line in data.splitlines():
+            msg = self.__process_line(prev_line, line)
+            if msg is not None:
+                self.__messages.append(Message(*msg))
+            prev_line = line
+
+    def get_messages(self):
+        """Return a list of warning and error Messages."""
+        # BibTeX reports most errors in no particular order.  Sort by
+        # file and line.
+        return sorted(self.__messages,
+                      key=lambda msg: (msg.filename or '', msg.lineno or 0))
+
+    def __process_line(self, prev_line, line):
+        m = None
+        def match(regexp):
+            nonlocal m
+            m = re.match(regexp, line)
+            return m
+
+        # BibTeX has many error paths, but luckily the set is closed,
+        # so we can find all of them.  This first case is the
+        # workhorse format.
+        #
+        # AUX errors: aux_err/aux_err_return/aux_err_print
+        #
+        # BST errors: bst_ln_num_print/bst_err/
+        # bst_err_print_and_look_for_blank_line_return/
+        # bst_warn_print/bst_warn/
+        # skip_token/skip_token_print/
+        # bst_ext_warn/bst_ext_warn_print/
+        # bst_ex_warn/bst_ex_warn_print/
+        # bst_mild_ex_warn/bst_mild_ex_warn_print/
+        # bst_string_size_exceeded
+        #
+        # BIB errors: bib_ln_num_print/
+        # bib_err_print/bib_err/
+        # bib_warn_print/bib_warn/
+        # bib_one_of_two_expected_err/macro_name_warning/
+        if match('(.*?)---?line ([0-9]+) of file (.*)'):
+            # Sometimes the real error is printed on the previous line
+            if m.group(1) == 'while executing':
+                # bst_ex_warn.  The real message is on the previous line
+                text = prev_line
+            else:
+                text = m.group(1) or prev_line
+            typ, msg = self.__canonicalize(text)
+            return (typ, m.group(3), int(m.group(2)), msg)
+
+        # overflow/print_overflow
+        if match('Sorry---you\'ve exceeded BibTeX\'s (.*)'):
+            return ('error', None, None, 'capacity exceeded: ' + m.group(1))
+        # confusion/print_confusion
+        if match('(.*)---this can\'t happen$'):
+            return ('error', None, None, 'internal error: ' + m.group(1))
+        # aux_end_err
+        if match('I found (no .*)---while reading file (.*)'):
+            return ('error', m.group(2), None, m.group(1))
+        # bad_cross_reference_print/
+        # nonexistent_cross_reference_error/
+        # @<Complain about a nested cross reference@>
+        #
+        # This is split across two lines.  Match the second.
+        if match('^refers to entry "'):
+            typ, msg = self.__canonicalize(prev_line + ' ' + line)
+            msg = re.sub('^a (bad cross reference)', '\\1', msg)
+            # Try to give this key a location
+            filename = lineno = None
+            m2 = re.search(r'--entry "[^"]"', prev_line)
+            if m2:
+                filename, lineno = self.__find_key(m2.group(1))
+            return (typ, filename, lineno, msg)
+        # print_missing_entry
+        if match('Warning--I didn\'t find a database entry for (".*")'):
+            return ('warning', None, None,
+                    'no database entry for ' + m.group(1))
+        # x_warning
+        if match('Warning--(.*)'):
+            # Most formats give warnings about "something in <key>".
+            # Try to match it up.
+            filename = lineno = None
+            for m2 in reversed(list(re.finditer(r' in ([^, \t\n]+)\b', line))):
+                if m2:
+                    filename, lineno = self.__find_key(m2.group(1))
+                    if filename:
+                        break
+            return ('warning', filename, lineno, m.group(1))
+        # @<Clean up and leave@>
+        if match('Aborted at line ([0-9]+) of file (.*)'):
+            return ('info', m.group(2), int(m.group(1)), 'aborted')
+
+        # biber type errors
+        if match('^.*> WARN - (.*)$'):
+            print ('warning', None, None, m.group(1))
+            m2 = re.match("(.*) in file '(.*?)', skipping ...", m.group(1))
+            if m2:
+                return ('warning', m2.group(2), "0", m2.group(1))
+            return ('warning', None, None, m.group(1))
+
+        if match('^.*> ERROR - (.*)$'):
+            m2 = re.match("BibTeX subsystem: (.*?), line (\d+), (.*)$", m.group(1))
+            if m2:
+                return ('error', m2.group(1), m2.group(2), m2.group(3))
+            return ('error', None, None, m.group(1))
+
+
+    def __canonicalize(self, msg):
+        if msg.startswith('Warning'):
+            msg = re.sub('^Warning-*', '', msg)
+            typ = 'warning'
+        else:
+            typ = 'error'
+        msg = re.sub('^I(\'m| was)? ', '', msg)
+        msg = msg[:1].lower() + msg[1:]
+        return typ, msg
+
+    def __find_key(self, key):
+        if self.__key_locs is None:
+            p = BibTeXKeyParser()
+            self.__key_locs = {}
+            for filename in self.__inputs:
+                data = open(filename, 'rt', errors='surrogateescape').read()
+                for pkey, lineno in p.parse(data):
+                    self.__key_locs.setdefault(pkey, (filename, lineno))
+        return self.__key_locs.get(key, (None, None))
+
+class BibTeXKeyParser:
+    """Just enough of a BibTeX parser to find keys."""
+
+    def parse(self, data):
+        IDENT_RE = '(?![0-9])([^\x00-\x20\x80-\xff \t"#%\'(),={}]+)'
+        self.__pos, self.__data = 0, data
+        # Find the next entry
+        while self.__consume('[^@]*@[ \t\n]*'):
+            # What type of entry?
+            if not self.__consume(IDENT_RE + '[ \t\n]*'):
+                continue
+            typ = self.__m.group(1)
+            if typ == 'comment':
+                continue
+            start = self.__pos
+            if not self.__consume('([{(])[ \t\n]*'):
+                continue
+            closing, key_re = {'{' : ('}', '([^, \t\n}]*)'),
+                               '(' : (')', '([^, \t\n]*)')}[self.__m.group(1)]
+            if typ not in ('preamble', 'string'):
+                # Regular entry; get key
+                if self.__consume(key_re):
+                    yield self.__m.group(1), self.__lineno()
+            # Consume body of entry
+            self.__pos = start
+            self.__balanced(closing)
+
+    def __consume(self, regexp):
+        self.__m = re.compile(regexp).match(self.__data, self.__pos)
+        if self.__m:
+            self.__pos = self.__m.end()
+        return self.__m
+
+    def __lineno(self):
+        return self.__data.count('\n', 0, self.__pos) + 1
+
+    def __balanced(self, closing):
+        self.__pos += 1
+        level = 0
+        skip = re.compile('[{}' + closing + ']')
+        while True:
+            m = skip.search(self.__data, self.__pos)
+            if not m:
+                break
+            self.__pos = m.end()
+            ch = m.group(0)
+            if level == 0 and ch == closing:
+                break
+            elif ch == '{':
+                level += 1
+            elif ch == '}':
+                level -= 1
+
+class Kpathsea:
+    def __init__(self, program_name):
+        self.__progname = program_name
+
+    def find_file(self, name, format, cwd=None, env=None):
+        """Return the resolved path of 'name' or None."""
+
+        args = ['kpsewhich', '-progname', self.__progname, '-format', format,
+                name]
+        try:
+            verbose_cmd(args, cwd, env)
+            path = subprocess.check_output(
+                args, cwd=cwd, env=env, universal_newlines=True).strip()
+        except subprocess.CalledProcessError as e:
+            if e.returncode != 1:
+                raise
+            return None
+        if cwd is None:
+            return path
+        return os.path.join(cwd, path)
+
+if __name__ == "__main__":
+    main()
diff --git a/jfp-paper/mathptmx.sty b/jfp-paper/mathptmx.sty
new file mode 100644
index 0000000000000000000000000000000000000000..85b08b4bfb3b530e0b4c9e04fbda5d8a1c69c142
--- /dev/null
+++ b/jfp-paper/mathptmx.sty
@@ -0,0 +1,42 @@
+\def\filedate{1998/06/30}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{mathptmx}[\filedate\space
+  Times + math package from fontinst]
+\def\rmdefault{ptm}
+\DeclareSymbolFont{operators}   {OT1}{ztmcm}{m}{n}
+\DeclareSymbolFont{letters}     {OML}{ztmcm}{m}{it}
+\DeclareSymbolFont{symbols}     {OMS}{ztmcm}{m}{n}
+\DeclareSymbolFont{largesymbols}{OMX}{ztmcm}{m}{n}
+\DeclareSymbolFont{bold}        {OT1}{ptm}{bx}{n}
+\DeclareSymbolFont{italic}      {OT1}{ptm}{m}{it}
+\@ifundefined{mathbf}{}{\DeclareMathAlphabet{\mathbf}{OT1}{ptm}{bx}{n}}
+\@ifundefined{mathit}{}{\DeclareMathAlphabet{\mathit}{OT1}{ptm}{m}{it}}
+\DeclareMathSymbol{\omicron}{0}{operators}{`\o}
+\thinmuskip=2mu
+\medmuskip=2.5mu plus 1mu minus 1mu
+\thickmuskip=4mu plus 1.5mu minus 1mu
+  \let\@tempa\version@elt
+    \def\version@elt#1{%
+      \ifx\mv@bold#1\else\noexpand\version@elt\noexpand#1\fi}
+    \edef\version@list{\version@list}
+  \let\version@elt\@tempa
+  \let\mv@bold\@undefined
+\def\boldmath{%
+   \PackageWarning{there is no bold Symbol font}%
+   \global\let\boldmath=\relax
+}
+\DeclareMathSizes{5}{5}{5}{5}
+\DeclareMathSizes{6}{6}{5}{5}
+\DeclareMathSizes{7}{7}{5}{5}
+\DeclareMathSizes{8}{8}{6}{5}
+\DeclareMathSizes{9}{9}{7}{5}
+\DeclareMathSizes{10}{10}{7.4}{6}
+\DeclareMathSizes{10.95}{10.95}{8}{6}
+\DeclareMathSizes{12}{12}{9}{7}
+\DeclareMathSizes{14.4}{14.4}{10.95}{8}
+\DeclareMathSizes{17.28}{17.28}{12}{10}
+\DeclareMathSizes{20.74}{20.74}{14.4}{12}
+\DeclareMathSizes{24.88}{24.88}{17.28}{14.4}
+\endinput
+%%
+%% End of file `mathptmx.sty'.
\ No newline at end of file