[ocl] OCL 2022 CG paper, Library camera-ready
diff --git a/ocl/docs/publications/OCL2022CG/.gitignore b/ocl/docs/publications/OCL2022CG/.gitignore
index 3fed747..2eae520 100644
--- a/ocl/docs/publications/OCL2022CG/.gitignore
+++ b/ocl/docs/publications/OCL2022CG/.gitignore
@@ -4,3 +4,4 @@
 /OCLCodeGeneration.bbl
 /OCLCodeGeneration.blg
 /OCLCodeGeneration.out
+/OCL2022CG.zip
diff --git a/ocl/docs/publications/OCL2022CG/ACM-Reference-Format.bst b/ocl/docs/publications/OCL2022CG/ACM-Reference-Format.bst
new file mode 100644
index 0000000..7984639
--- /dev/null
+++ b/ocl/docs/publications/OCL2022CG/ACM-Reference-Format.bst
@@ -0,0 +1,3081 @@
+%%% -*-BibTeX-*-
+%%% ====================================================================
+%%%  @BibTeX-style-file{
+%%%     author          = "Nelson H. F. Beebe, Boris Veytsman and Gerald Murray",
+%%%     version         = "2.1",
+%%%     acmart-version  = "1.79",
+%%%     date            = "14 June 2017",
+%%%     filename        = "ACM-Reference-Format.bst",
+%%%     email           = "borisv@lk.net, boris@varphi.com",
+%%%     codetable       = "ISO/ASCII",
+%%%     keywords        = "ACM Transactions bibliography style; BibTeX",
+%%%     license         = "public domain",
+%%%     supported       = "yes",
+%%%     abstract        = "",
+%%%  }
+%%% ====================================================================
+
+%%% Revision history:  see source in git
+
+ENTRY
+  { address
+    advisor
+    archiveprefix
+    author
+    booktitle
+    chapter
+    city
+    date
+    edition
+    editor
+    eprint
+    eprinttype
+    eprintclass
+    howpublished
+    institution
+    journal
+    key
+    location
+    month
+    note
+    number
+    organization
+    pages
+    primaryclass
+    publisher
+    school
+    series
+    title
+    type
+    volume
+    year
+        % New keys recognized
+        issue         % UTAH: used in, e.g., ACM SIGSAM Bulletin and ACM Communications in Computer Algebra
+        articleno
+        eid
+        day           % UTAH: needed for newspapers, weeklies, bi-weeklies
+        doi           % UTAH
+        url           % UTAH
+        bookpages     % UTAH
+        numpages
+        lastaccessed  % UTAH: used only for @Misc{...}
+        coden         % UTAH
+        isbn          % UTAH
+        isbn-13       % UTAH
+        issn          % UTAH
+        lccn          % UTAH
+	distinctURL   % whether to print url if doi is present
+  }
+  {}
+  { label.year extra.label sort.year sort.label basic.label.year}
+
+INTEGERS { output.state before.all mid.sentence after.sentence after.block }
+
+INTEGERS { show-isbn-10-and-13 }  % initialized below in begin.bib
+
+INTEGERS { nameptr namesleft numnames }
+
+INTEGERS { multiresult }
+
+INTEGERS { len }
+
+INTEGERS { last.extra.num }
+
+STRINGS { s t t.org u }
+
+STRINGS { last.label next.extra }
+
+STRINGS { p1 p2 p3 page.count }
+
+
+FUNCTION { not }
+{
+    { #0 }
+    { #1 }
+  if$
+}
+
+FUNCTION { and }
+{
+    'skip$
+    { pop$ #0 }
+  if$
+}
+
+FUNCTION { or }
+{
+   { pop$ #1 }
+    'skip$
+  if$
+}
+
+
+FUNCTION { dump.stack.1 }
+{
+    duplicate$ "STACK[top] = [" swap$ * "]" * warning$
+}
+
+FUNCTION { dump.stack.2 }
+{
+    duplicate$ "STACK[top  ] = [" swap$ * "]" * warning$
+    swap$
+    duplicate$ "STACK[top-1] = [" swap$ * "]" * warning$
+    swap$
+}
+
+FUNCTION { empty.or.unknown }
+{
+  %% Examine the top stack entry, and push 1 if it is empty, or
+  %% consists only of whitespace, or is a string beginning with two
+  %% queries (??), and otherwise, push 0.
+  %%
+  %% This function provides a replacement for empty$, with the
+  %% convenient feature that unknown values marked by two leading
+  %% queries are treated the same as missing values, and thus, do not
+  %% appear in the output .bbl file, and yet, their presence in .bib
+  %% file(s) serves to mark values which are temporarily missing, but
+  %% are expected to be filled in eventually once more data is
+  %% obtained.  The TeX User Group and BibNet bibliography archives
+  %% make extensive use of this practice.
+  %%
+  %% An empty string cannot serve the same purpose, because just as in
+  %% statistics data processing, an unknown value is not the same as an
+  %% empty value.
+  %%
+  %% At entry: stack = ... top:[string]
+  %% At exit:  stack = ... top:[0 or 1]
+
+  duplicate$ empty$
+    { pop$ #1 }
+    { #1 #2 substring$ "??" = }
+  if$
+}
+
+FUNCTION { empty.or.zero }
+{ 
+  %% Examine the top entry and push 1 if it is empty, or is zero
+  duplicate$ empty$
+    { pop$ #1 }
+    { "0" = }
+  if$
+}
+
+
+FUNCTION { writeln }
+{
+  %% In BibTeX style files, the sequences
+  %%
+  %%     ... "one" "two" output
+  %%     ... "one" "two" output.xxx
+  %%
+  %% ship "one" to the output file, possibly following by punctuation,
+  %% leaving the stack with
+  %%
+  %%     ... "two"
+  %%
+  %% There is thus a one-string lag in output processing that must be
+  %% carefully handled to avoid duplicating a string in the output
+  %% file.  Unless otherwise noted, all output.xxx functions leave
+  %% just one new string on the stack, and that model should be born
+  %% in mind when reading or writing function code.
+  %%
+  %% BibTeX's asynchronous buffering of output from strings from the
+  %% stack is confusing because newline$ bypasses the buffer.  It
+  %% would have been so much easier for newline to be a character
+  %% rather than a state of the output-in-progress.
+  %%
+  %% The documentation in btxhak.dvi is WRONG:  it says
+  %%
+  %%    newline$ Writes onto the bbl file what's accumulated in the
+  %%             output buffer. It writes a blank line if and only
+  %%             if the output buffer is empty. Since write$ does
+  %%             reasonable line breaking, you should use this
+  %%             function only when you want a blank line or an
+  %%             explicit line break.
+  %%
+  %%    write$   Pops the top (string) literal and writes it on the
+  %%             output buffer (which will result in stuff being
+  %%             written onto the bbl file when the buffer fills
+  %%             up).
+  %%
+  %% Examination of the BibTeX source code shows that write$ does
+  %% indeed behave as claimed, but newline$ sends a newline character
+  %% directly to the output file, leaving the stack unchanged.  The
+  %% first line "Writes onto ... buffer." is therefore wrong.
+  %%
+  %% The original BibTeX style files almost always use "write$ newline$"
+  %% in that order, so it makes sense to hide that pair in a private
+  %% function like this one, named after a statement in Pascal,
+  %% the programming language embedded in the BibTeX Web program.
+
+  write$                % output top-of-stack string
+  newline$              % immediate write of newline (not via stack)
+}
+
+FUNCTION { init.state.consts }
+{
+  #0 'before.all :=
+  #1 'mid.sentence :=
+  #2 'after.sentence :=
+  #3 'after.block :=
+}
+
+FUNCTION { output.nonnull }
+{ % Stack in: ... R S T  Stack out: ... R T   File out: S<comma><space>
+  's :=
+  output.state mid.sentence =
+    {
+      ", " * write$
+    }
+    {
+      output.state after.block =
+        {
+          add.period$ writeln
+          "\newblock " write$
+        }
+        {
+          output.state before.all =
+            {
+              write$
+            }
+            {
+              add.period$ " " * write$
+            }
+          if$
+        }
+      if$
+      mid.sentence 'output.state :=
+    }
+  if$
+  s
+}
+
+FUNCTION { output.nonnull.dot.space }
+{ % Stack in: ... R S T  Stack out: ... R T   File out: S<dot><space>
+  's :=
+  output.state mid.sentence =           % { "<DEBUG output.nonnull.dot.space>. " * write$ }
+    {
+      ". " * write$
+    }
+    {
+      output.state after.block =
+        {
+          add.period$ writeln "\newblock " write$
+        }
+        {
+          output.state before.all =
+            {
+              write$
+            }
+            {
+              add.period$ " " * write$
+            }
+          if$
+        }
+      if$
+      mid.sentence 'output.state :=
+    }
+  if$
+  s
+}
+
+FUNCTION { output.nonnull.remove }
+{ % Stack in: ... R S T  Stack out: ... R T   File out: S<space>
+  's :=
+  output.state mid.sentence =
+    {
+      " " * write$
+    }
+    {
+      output.state after.block =
+        {
+          add.period$ writeln "\newblock " write$
+        }
+        {
+          output.state before.all =
+            {
+              write$
+            }
+            {
+              add.period$ " " * write$
+            }
+          if$
+        }
+      if$
+      mid.sentence 'output.state :=
+    }
+  if$
+  s
+}
+
+FUNCTION { output.nonnull.removenospace }
+{ % Stack in: ... R S T  Stack out: ... R T   File out: S
+  's :=
+  output.state mid.sentence =
+    {
+      "" * write$
+    }
+    {
+      output.state after.block =
+        {
+          add.period$ writeln "\newblock " write$
+        }
+        {
+          output.state before.all =
+            {
+              write$
+            }
+            {
+              add.period$ " " * write$
+            }
+          if$
+        }
+      if$
+      mid.sentence 'output.state :=
+    }
+  if$
+  s
+}
+
+FUNCTION { output }
+{ % discard top token if empty, else like output.nonnull
+  duplicate$ empty.or.unknown
+    'pop$
+    'output.nonnull
+  if$
+}
+
+FUNCTION { output.dot.space }
+{ % discard top token if empty, else like output.nonnull.dot.space
+  duplicate$ empty.or.unknown
+    'pop$
+    'output.nonnull.dot.space
+  if$
+}
+
+FUNCTION { output.removenospace }
+{ % discard top token if empty, else like output.nonnull.removenospace
+  duplicate$ empty.or.unknown
+    'pop$
+    'output.nonnull.removenospace
+  if$
+}
+
+FUNCTION { output.check }
+{ % like output, but warn if key name on top-of-stack is not set
+  't :=
+  duplicate$ empty.or.unknown
+    { pop$ "empty " t * " in " * cite$ * warning$ }
+    'output.nonnull
+  if$
+}
+
+FUNCTION { bibinfo.output.check }
+{ % like output.check, adding bibinfo field
+  't :=
+  duplicate$ empty.or.unknown
+    { pop$ "empty " t * " in " * cite$ * warning$ }
+    { "\bibinfo{" t "}{" * * swap$ * "}" *
+      output.nonnull }
+  if$
+}
+
+FUNCTION { output.check.dot.space }
+{ % like output.dot.space, but warn if key name on top-of-stack is not set
+  't :=
+  duplicate$ empty.or.unknown
+    { pop$ "empty " t * " in " * cite$ * warning$ }
+    'output.nonnull.dot.space
+  if$
+}
+
+FUNCTION { fin.block }
+{ % functionally, but not logically, identical to fin.entry
+   add.period$
+   writeln
+}
+
+FUNCTION { fin.entry }
+{
+   add.period$
+   writeln
+}
+
+FUNCTION { new.sentence }
+{ % update sentence state, with neither output nor stack change
+  output.state after.block =
+    'skip$
+    {
+      output.state before.all =
+        'skip$
+        { after.sentence 'output.state := }
+      if$
+    }
+  if$
+}
+
+FUNCTION { fin.sentence }
+{
+   add.period$
+   write$
+   new.sentence
+   ""
+}
+
+FUNCTION { new.block }
+{
+  output.state before.all =
+    'skip$
+    { after.block 'output.state := }
+  if$
+}
+
+FUNCTION { output.coden }       % UTAH
+{ % output non-empty CODEN as one-line sentence (stack untouched)
+  coden empty.or.unknown
+    { }
+    { "\showCODEN{" coden * "}" * writeln }
+  if$
+}
+
+%
+% Sometimes articleno starts with the word 'Article' or 'Paper.
+% (this is a bug of acmdl, sigh)
+% We strip them.  We assume eid or articleno is already on stack
+%
+
+FUNCTION { strip.articleno.or.eid }
+{
+  't :=
+  t #1 #7 substring$ "Article" = 
+    {t #8 t text.length$ substring$ 't :=}
+    { }
+  if$
+  t #1 #7 substring$ "article" = 
+    {t #8 t text.length$ substring$ 't :=}
+    { }
+  if$
+  t #1 #5 substring$ "Paper" = 
+    {t #6 t text.length$ substring$ 't :=}
+    { }
+  if$
+  t #1 #5 substring$ "paper" = 
+    {t #6 t text.length$ substring$ 't :=}
+    { }
+  if$
+  % Strip any left trailing space or ~
+  t #1 #1 substring$ " " =
+    {t #2 t text.length$ substring$ 't :=}
+    { }
+  if$ 
+  t #1 #1 substring$ "~" =
+    {t #2 t text.length$ substring$ 't :=}
+    { }
+  if$
+  t 
+}
+
+
+FUNCTION { format.articleno }
+{
+  articleno empty.or.unknown not eid empty.or.unknown not and
+     { "Both articleno and eid are defined for " cite$ * warning$ }
+     'skip$
+  if$
+  articleno empty.or.unknown eid empty.or.unknown and
+     { "" }
+     {
+        numpages empty.or.unknown
+          { "articleno or eid field, but no numpages field, in "
+            cite$ * warning$ }
+          { }
+        if$
+        eid empty.or.unknown
+          { "Article \bibinfo{articleno}{" articleno strip.articleno.or.eid * "}" * }
+          { "Article \bibinfo{articleno}{" eid strip.articleno.or.eid * "}" * }
+        if$
+     }
+  if$
+}
+
+FUNCTION { format.year }
+{ % push year string or "[n.\,d.]" onto output stack
+  %% Because year is a mandatory field, we always force SOMETHING
+  %% to be output
+  "\bibinfo{year}{"
+  year empty.or.unknown
+    { "[n.\,d.]" }
+    { year }
+  if$
+  *  "}" *
+}
+
+FUNCTION { format.day.month }
+{ % push "day month " or "month " or "" onto output stack
+  day empty.or.unknown
+    {
+      month empty.or.unknown
+        { "" }
+        { "\bibinfo{date}{" month * "} " *}
+      if$
+    }
+    {
+      month empty.or.unknown
+        { "" }
+        { "\bibinfo{date}{" day * " " * month * "} " *}
+      if$
+    }
+  if$
+}
+
+FUNCTION { format.day.month.year }     % UTAH
+{ % if month is empty, push "" else push "(MON.)" or "(DD MON.)"
+  % Needed for frequent periodicals: 2008. ... New York Times C-1, C-2, C-17 (23 Oct.)
+  % acm-*.bst addition: prefix parenthesized date string with
+  % ", Article nnn "
+  articleno empty.or.unknown eid empty.or.unknown and
+    { "" }
+    { output.state after.block =
+       {", " format.articleno * }
+       { format.articleno  }
+      if$
+    }
+  if$
+  " (" * format.day.month * format.year * ")" *
+}
+
+FUNCTION { output.day.month.year }     % UTAH
+{ % if month is empty value, do nothing; else output stack top and
+  % leave with new top string "(MON.)" or "(DD MON.)"
+  % Needed for frequent periodicals: 2008. ... New York Times C-1, C-2, C-17 (23 Oct.)
+  format.day.month.year
+  output.nonnull.remove
+}
+
+FUNCTION { strip.doi } % UTAH
+{ % Strip any Web address prefix to recover the bare DOI, leaving the
+  % result on the output stack, as recommended by CrossRef DOI
+  % documentation.
+  % For example, reduce "http://doi.acm.org/10.1145/1534530.1534545" to
+  % "10.1145/1534530.1534545".  A suitable URL is later typeset and
+  % displayed as the LAST item in the reference list entry.  Publisher Web
+  % sites wrap this with a suitable link to a real URL to resolve the DOI,
+  % and the master https://doi.org/ address is preferred, since publisher-
+  % specific URLs can disappear in response to economic events.  All
+  % journals are encouraged by the DOI authorities to use that typeset
+  % format and link procedures for uniformity across all publications that
+  % include DOIs in reference lists.
+  % The numeric prefix is guaranteed to start with "10.", so we use
+  % that as a test.
+  % 2017-02-04 Added stripping of https:// (Boris)
+  doi #1 #3 substring$ "10." =
+    { doi }
+    {
+      doi 't :=  % get modifiable copy of DOI
+
+      % Change https:// to http:// to strip both prefixes (BV)
+
+      t #1 #8 substring$ "https://" =
+        { "http://"  t #9 t text.length$ #8 - substring$ * 't := }
+        { }
+      if$
+
+      t #1 #7 substring$ "http://" =
+        {
+            t #8 t text.length$ #7 - substring$ 't :=
+
+            "INTERNAL STYLE-FILE ERROR" 's :=
+
+            % search for next "/" and assign its suffix to s
+
+            { t text.length$ }
+            {
+              t #1 #1 substring$ "/" =
+                {
+                  % save rest of string as true DOI (should be 10.xxxx/yyyy)
+                  t #2 t text.length$ #1 - substring$ 's :=
+                  "" 't :=    % empty string t terminates the loop
+                }
+                {
+                  % discard first character and continue loop: t <= substring(t,2,last)
+                  t #2 t text.length$ #1 - substring$ 't :=
+                }
+              if$
+            }
+            while$
+
+            % check for valid DOI (should be 10.xxxx/yyyy)
+            s #1 #3 substring$ "10." =
+              { }
+              { "unrecognized DOI substring " s * " in DOI value [" * doi * "]" * warning$ }
+            if$
+
+            s   % push the stripped DOI on the output stack
+
+        }
+        {
+          "unrecognized DOI value [" doi * "]" * warning$
+          doi   % push the unrecognized original DOI on the output stack
+        }
+      if$
+    }
+  if$
+}
+
+%
+% Change by BV: added standard prefix to URL
+%
+FUNCTION { output.doi } % UTAH
+{ % output non-empty DOI as one-line sentence (stack untouched)
+  doi empty.or.unknown
+    { }
+    {
+      %% Use \urldef here for the same reason it is used in output.url,
+      %% see output.url for further discussion.
+      "\urldef\tempurl%" writeln
+      "\url{https://doi.org/" strip.doi * "}" * writeln
+      "\showDOI{\tempurl}" writeln
+    }
+  if$
+}
+
+FUNCTION { output.isbn }                % UTAH
+{ % output non-empty ISBN-10 and/or ISBN-13 as one-line sentences (stack untouched)
+  show-isbn-10-and-13
+    {
+      %% show both 10- and 13-digit ISBNs
+      isbn empty.or.unknown
+        { }
+        {
+          "\showISBNx{" isbn * "}" * writeln
+        }
+      if$
+      isbn-13 empty.or.unknown
+        { }
+        {
+          "\showISBNxiii{" isbn-13 * "}" * writeln
+        }
+      if$
+    }
+    {
+      %% show 10-digit ISBNs only if 13-digit ISBNs not available
+      isbn-13 empty.or.unknown
+        {
+          isbn empty.or.unknown
+            { }
+            {
+              "\showISBNx{" isbn * "}" * writeln
+            }
+          if$
+        }
+        {
+          "\showISBNxiii{" isbn-13 * "}" * writeln
+        }
+      if$
+    }
+  if$
+}
+
+FUNCTION { output.issn } % UTAH
+{ % output non-empty ISSN as one-line sentence (stack untouched)
+  issn empty.or.unknown
+    { }
+    { "\showISSN{" issn * "}" * writeln }
+  if$
+}
+
+FUNCTION { output.issue }
+{ % output non-empty issue number as a one-line sentence (stack untouched)
+  issue empty.or.unknown
+    { }
+    { "Issue " issue * "." * writeln }
+  if$
+}
+
+FUNCTION { output.lccn } % UTAH
+{ % return with stack untouched
+  lccn empty.or.unknown
+    { }
+    { "\showLCCN{" lccn * "}" * writeln }
+  if$
+}
+
+FUNCTION { output.note } % UTAH
+{ % return with stack empty
+  note empty.or.unknown
+    { }
+    { "\shownote{" note * "}" add.period$ * writeln }
+  if$
+}
+
+FUNCTION { output.note.check } % UTAH
+{ % return with stack empty
+  note empty.or.unknown
+    { "empty note in " cite$ * warning$ }
+    { "\shownote{" note * "}" add.period$ * writeln }
+  if$
+}
+
+FUNCTION { output.eprint } %
+{ % return with stack empty
+  eprint empty.or.unknown
+    { }
+    { "\showeprint"
+         archiveprefix empty.or.unknown
+           { eprinttype empty.or.unknown
+               { }
+               { "[" eprinttype "]" * * * }
+             if$
+           }
+           { "[" archiveprefix "l" change.case$ "]" * * * }
+         if$
+	 "{" eprint "}" * * *
+         primaryclass empty.or.unknown
+           { eprintclass empty.or.unknown
+             { }
+             { "~[" eprintclass "]" * * * }
+             if$
+           }
+           { "~[" primaryclass "]" * * * }
+         if$
+         writeln
+    }
+  if$
+}
+
+
+%
+% Changes by BV 2011/04/15.  Do not output
+% url if doi is defined
+%
+%
+% Changes by BV 2021/11/26.  Output url even if doi is defined
+% if distinctURL is not zero.
+%
+FUNCTION { output.url } % UTAH
+{ % return with stack untouched
+  % output URL and associated lastaccessed fields
+  doi empty.or.unknown distinctURL empty.or.zero not or
+  {
+    url empty.or.unknown
+      { }
+      {
+          %% Use \urldef, outside \showURL, so that %nn, #, etc in URLs work
+          %% correctly.  Put the actual URL on its own line to reduce the
+          %% likelihood of BibTeX's nasty line wrapping after column 79.
+          %% \url{} can undo this, but if that doesn't work for some reason
+          %% the .bbl file would have to be repaired manually.
+          "\urldef\tempurl%" writeln
+          "\url{" url * "}" * writeln
+
+          "\showURL{%" writeln
+          lastaccessed empty.or.unknown
+            { "" }
+            { "Retrieved " lastaccessed * " from " * }
+          if$
+          "\tempurl}" * writeln
+      }
+      if$
+  }
+  { }
+  if$
+}
+
+FUNCTION { output.year.check }
+{ % warn if year empty, output top string and leave " YEAR<label>" on stack in mid-sentence
+  year empty.or.unknown
+     { "empty year in " cite$ * warning$
+       write$
+       " \bibinfo{year}{[n.\,d.]}"
+       "\natexlab{" extra.label * "}" * *
+       mid.sentence 'output.state :=
+     }
+     { write$
+       " \bibinfo{year}{" year * "}"  *
+       "\natexlab{" extra.label * "}" * *
+       mid.sentence 'output.state :=
+     }
+  if$
+}
+
+
+FUNCTION { le }
+{
+  %% test whether first number is less than or equal to second number
+  %% stack in:  n1 n2
+  %% stack out: if n1 <= n2 then 1 else 0
+
+  %% "DEBUG: le " cite$ * warning$
+  > { #0 } { #1 } if$
+}
+
+FUNCTION { ge }
+{
+  %% test whether first number is greater than or equal to second number
+  %% stack in:  n1 n2
+  %% stack out: if n1 >= n2 then 1 else 0
+
+  %% "DEBUG: ge " cite$ * warning$
+  < { #0 } { #1 } if$
+}
+
+FUNCTION { is.leading.digit }
+{
+  %% test whether first character of string is a digit
+  %% stack in:  string
+  %% stack out: if first-char-is-digit then 1 else 0
+
+  #1 #1 substring$                      % replace string by string[1:1]
+  duplicate$                            % string[1:1] string[1:1]
+  chr.to.int$
+  "0" chr.to.int$ swap$ le              % "0" <= string[1:1] --> 0-or-1
+  swap$                                 % 0-or-1 string[1:1]
+  chr.to.int$
+  "9" chr.to.int$ le                    % string[1:1} <= "9" --> 0-or-1
+  and
+}
+
+FUNCTION { skip.digits }
+{
+  %% skip over leading digits in string
+  %% stack in:  string
+  %% stack out: rest-of-string leading-digits
+
+  %% "DEBUG: enter skip.digits " cite$ * warning$
+
+  %% dump.stack.1
+
+  duplicate$
+  't :=
+  't.org :=
+  "" 'u :=
+
+  { t text.length$ }
+  {
+    %% "=================DEBUG: skip.digits   t = [" t * "]" * warning$
+    t is.leading.digit
+      { t #2 t text.length$ #1 - substring$ }
+      {
+        t 'u :=
+        ""
+      }
+    if$
+    't :=
+  }
+  while$
+
+  u                                                             % rest of string
+  t.org #1 t.org text.length$ u text.length$ - substring$       % leading digits
+
+  %% "DEBUG: t.org = [" t.org * "]" * warning$
+  %% "DEBUG: u     = [" u * "]" * warning$
+
+  %% dump.stack.2
+
+  %% "DEBUG: leave skip.digits " cite$ * warning$
+}
+
+FUNCTION { skip.nondigits }
+{
+  %% skip over leading nondigits in string
+  %% stack in:  string
+  %% stack out: rest-of-string
+
+  %% "DEBUG: enter skip.nondigits " cite$ * warning$
+
+  't :=
+  "" 'u :=
+
+  { t text.length$ }
+  {
+    %% "=================DEBUG: skip.nondigits   t = [" t * "]" * warning$
+    t is.leading.digit
+      {
+        t 'u :=
+        ""
+      }
+      { t #2 t text.length$ #1 - substring$ }
+    if$
+    't :=
+  }
+  while$
+
+  u                     % rest of string
+
+  %% dump.stack.1
+  %% "DEBUG: leave skip.nondigits " cite$ * warning$
+}
+
+FUNCTION { parse.next.number }
+{
+  %% stack in:  string
+  %% stack out: rest-of-string next-numeric-part-of-string
+  %% Example:
+  %% stack in:  "123:1--123:59"
+  %% stack out: ":1--123:59" "123"
+
+  's :=
+  s skip.nondigits 's :=
+  s skip.digits
+}
+
+FUNCTION { reduce.pages.to.page.count }
+{
+  %% Stack in:  arbitrary-and-unused
+  %% Stack out: unchanged
+  %%
+  %% For the new-style pagination with article number and numpages or
+  %% pages, we expect to have BibTeX entries containing something like
+  %%     articleno = "17",
+  %%     pages     = "1--23",
+  %% with output "Article 17, 23 pages",
+  %% or
+  %%     articleno = "17",
+  %%     numpages  = "23",
+  %% with output "Article 17, 23 pages",
+  %% or
+  %%     articleno = "17",
+  %%     pages     = "17:1--17:23",
+  %% with output "Article 17, 23 pages",
+  %%
+  %% If articleno is missing or empty, then we should output "1--23",
+  %% "23" (with a warning of a missing articleno), or "17:1--17:23",
+  %% respectively.
+
+  %% "DEBUG: enter reduce.pages.to.page.count " cite$ * warning$
+
+  %% "DEBUG: pages = [" pages * "]" * warning$
+
+  pages
+  parse.next.number 'p1 :=
+  parse.next.number 'p2 :=
+  parse.next.number 'p3 :=
+  parse.next.number 'page.count :=
+
+  duplicate$
+  empty.or.unknown
+    {  }
+    {
+      duplicate$ "unexpected trailing garbage [" swap$ *
+      "] after n:p1--n:p2 in pages = [" *
+      pages *
+      "] in " *
+      cite$ *
+      warning$
+    }
+  if$
+
+  pop$
+
+  %% "DEBUG: reduce.pages.to.page.count: "
+  %% " p1 = " p1 * *
+  %% " p2 = " p2 * *
+  %% " p3 = " p3 * *
+  %% " p4 = " page.count * *
+  %% " in " cite$ * * warning$
+
+  p1 p3 =   p2 "1" =   and   numpages empty.or.unknown   and
+    { "INFO: reduced pages = [" pages * "] to numpages = [" * page.count * "]" * warning$ }
+    {
+      numpages empty.or.unknown
+        { pages }
+        { numpages }
+      if$
+      'page.count :=
+    }
+  if$
+
+  p1 "1" =   p3 empty.or.unknown   and   numpages empty.or.unknown   and
+    {
+      p2 'page.count :=
+      "INFO: reduced pages = [" pages * "] to numpages = [" * page.count * "]" * warning$
+    }
+    {
+      numpages empty.or.unknown
+        { pages }
+        { numpages }
+      if$
+      'page.count :=
+    }
+  if$
+
+  %% "DEBUG: leave reduce.pages.to.page.count " cite$ * warning$
+}
+
+FUNCTION { new.block.checkb }
+{ % issue a new.block only if at least one of top two stack strings is not empty
+  empty.or.unknown
+  swap$ empty.or.unknown
+  and
+    'skip$
+    'new.block
+  if$
+}
+
+FUNCTION { field.or.null }
+{ % convert empty value to null string, else return value
+  duplicate$ empty.or.unknown
+    { pop$ "" }
+    'skip$
+  if$
+}
+
+
+
+FUNCTION { emphasize }
+{ % emphasize a non-empty top string on the stack
+  duplicate$ empty.or.unknown
+    { pop$ "" }
+    { "\emph{" swap$ * "}" * }
+  if$
+}
+
+FUNCTION { comma }
+{ % convert empty string to null string, or brace string and add trailing comma
+  duplicate$ empty.or.unknown
+    { pop$ "" }
+    { "{" swap$ * "}," * }
+  if$
+}
+
+FUNCTION { format.names }
+{
+  % Format bibliographical entries with the first author last name first,
+  % and subsequent authors with initials followed by last name.
+  % All names are formatted in this routine.
+
+  's :=
+  #1 'nameptr :=               % nameptr = 1;
+  s num.names$ 'numnames :=    % numnames = num.name$(s);
+  numnames 'namesleft :=
+    { namesleft #0 > }
+    { nameptr #1 =
+        %NO: BAD ORDER: {"{" s nameptr "{ff~}{ll}{, jj}{, vv}" format.name$ * "}" * 't := }
+        %NO: BAD ORDER: {"{" s nameptr "{ff~}{ll}{, jj}{, vv}" format.name$ * "}" * 't := }
+        {"\bibinfo{person}{" s nameptr "{ff }{vv }{ll}{, jj}" format.name$ * "}" * 't := }
+        {"\bibinfo{person}{" s nameptr "{ff }{vv }{ll}{, jj}" format.name$ * "}" * 't := }
+      if$
+      nameptr #1 >
+        {
+          namesleft #1 >
+            { ", " * t * }
+            {
+              numnames #2 >
+                { "," * }
+                'skip$
+              if$
+              t "\bibinfo{person}{others}" =
+                { " {et~al\mbox{.}}" * } % jrh: avoid spacing problems
+                { " {and} " * t * } % from Chicago Manual of Style
+              if$
+            }
+          if$
+        }
+        't
+      if$
+      nameptr #1 + 'nameptr :=          % nameptr += 1;
+      namesleft #1 - 'namesleft :=      % namesleft =- 1;
+    }
+  while$
+}
+
+FUNCTION { my.full.label }
+{
+  's :=
+  #1 'nameptr :=               % nameptr = 1;
+  s num.names$ 'numnames :=    % numnames = num.name$(s);
+  numnames 'namesleft :=
+    { namesleft #0 > }
+
+    { s nameptr "{vv~}{ll}" format.name$ 't :=  % get the next name
+      nameptr #1 >
+        {
+          namesleft #1 >
+            { ", " * t * }
+            {
+              numnames #2 >
+                { "," * }
+                'skip$
+              if$
+              t "others" =
+                { " et~al\mbox{.}" * } % jrh: avoid spacing problems
+                { " and " * t * } % from Chicago Manual of Style
+              if$
+            }
+          if$
+        }
+        't
+      if$
+      nameptr #1 + 'nameptr :=          % nameptr += 1;
+      namesleft #1 - 'namesleft :=      % namesleft =- 1;
+    }
+  while$
+
+}
+
+FUNCTION { format.names.fml }
+{
+  % Format names in "familiar" format, with first initial followed by
+  % last name. Like format.names, ALL names are formatted.
+  % jtb: The names are NOT put in small caps
+
+  's :=
+  #1 'nameptr :=               % nameptr = 1;
+  s num.names$ 'numnames :=    % numnames = num.name$(s);
+  numnames 'namesleft :=
+    { namesleft #0 > }
+
+    {
+      "\bibinfo{person}{" s nameptr "{ff~}{vv~}{ll}{, jj}" format.name$ * "}" * 't :=
+
+      nameptr #1 >
+        {
+          namesleft #1 >
+            { ", " * t * }
+            {
+              numnames #2 >
+                { "," * }
+                'skip$
+              if$
+              t "\bibinfo{person}{others}" =
+                { " {et~al\mbox{.}}" * }
+                { " {and} " * t * }
+              if$
+            }
+          if$
+        }
+        't
+      if$
+      nameptr #1 + 'nameptr :=          % nameptr += 1;
+      namesleft #1 - 'namesleft :=      % namesleft =- 1;
+    }
+  while$
+}
+
+FUNCTION { format.authors }
+{
+  author empty.or.unknown
+    { "" }
+    {
+      "\bibfield{author}{"
+      author format.names add.period$ * "}" *} % jtb: add period if none before
+  if$
+}
+
+FUNCTION { format.key }
+{
+  empty.or.unknown
+    { key field.or.null }
+    { "" }
+  if$
+}
+
+FUNCTION { format.no.key }
+{
+  empty.or.unknown
+    { "" }
+    { "" }
+  if$
+}
+
+FUNCTION { format.editors.fml }
+{
+  % Format editor names for use in the "in" types: inbook, incollection,
+  % inproceedings: first initial, then last names. When editors are the
+  % LABEL for an entry, then format.editor is used which lists editors
+  % by last name first.
+
+  editor empty.or.unknown
+    { "" }
+    {
+      "\bibfield{editor}{"
+      editor format.names.fml
+      *  "}" *
+      editor num.names$ #1 >
+        { " (Eds.)" * }
+        { " (Ed.)" * }
+      if$
+    }
+  if$
+}
+
+FUNCTION { format.editors }
+{ % format editor names for use in labels, last names first.
+  editor empty.or.unknown
+    { "" }
+    {
+      "\bibfield{editor}{"
+      editor format.names
+      *  "}" *
+      editor num.names$ #1 >
+        { " (Eds.)." * }
+        { " (Ed.)." * }
+      if$
+    }
+  if$
+}
+
+FUNCTION { format.articletitle }
+{
+  title empty.or.unknown
+    { "" }
+    % Use this to preserve lettercase in titles:
+    { "\showarticletitle{" title * "}" * }
+    % Use this for downcase title style:
+    % { \showarticletitle{" title "t" change.case$ * "}" * }
+  if$
+}
+
+FUNCTION { format.title }
+{
+  title empty.or.unknown
+    { "" }
+    % Use this to preserve lettercase in titles:
+    { "\bibinfo{title}{" title * "}" * }
+    % Use this for downcase title style:
+    % { title "t" change.case$ }
+  if$
+}
+
+FUNCTION { n.dashify }
+{
+  't :=
+  ""
+    { t empty.or.unknown 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.a.title.with.edition }
+{
+  "\bibinfo{booktitle}{"
+  swap$ emphasize *
+  edition empty.or.unknown
+    'skip$
+    { " (\bibinfo{edition}{" * edition "l" change.case$ *
+      "} ed.)" * } % jtb: no parens for ed.
+  if$
+  "}" *
+}
+
+FUNCTION { format.btitle }
+{ title format.a.title.with.edition }
+
+FUNCTION { format.emphasize.booktitle }
+{ booktitle format.a.title.with.edition }
+
+
+
+FUNCTION { format.city }
+{
+  % jtb: if the preceding string (the title of the conference) is non-empty,
+  % jtb: append the location, otherwise leave empty (so as to trigger the
+  % jtb: error message in output.check
+
+  duplicate$ empty.or.unknown
+    { }
+    {
+      city empty.or.unknown location empty.or.unknown and
+        {
+          date empty.or.unknown
+            { }
+            { " (" * date * ")" * }
+          if$
+        }
+        {
+          location empty.or.unknown
+            {
+              date empty.or.unknown
+                { " (" * city * ")" * }
+                { " (" * city * ", " * date * ")" * }
+              if$
+            }
+            {
+              date empty.or.unknown
+                { " (" * location * ")" * }
+                { " (" * location * ", " * date * ")" * }
+              if$
+            }
+          if$
+        }
+      if$
+    }
+  if$
+}
+
+FUNCTION { tie.or.space.connect }
+{
+  duplicate$ text.length$ #3 <
+    { "~" }
+    { " " }
+  if$
+  swap$ * *
+}
+
+FUNCTION { either.or.check }
+{
+  empty.or.unknown
+    'pop$
+    { "can't use both " swap$ * " fields in " * cite$ * warning$ }
+  if$
+}
+
+FUNCTION { format.bvolume }
+{
+  % jtb: If there is a series, this is added and the volume trails after it.
+  % jtb: Otherwise, "Vol" is Capitalized.
+
+  volume empty.or.unknown
+    { "" }
+    {
+      series empty.or.unknown
+        { "Vol.~\bibinfo{volume}{" volume "}" * *}
+        { "\bibinfo{series}{" series "}, " * *
+          "Vol.~\bibinfo{volume}{" volume "}" * * *}
+      if$
+      "volume and number" number either.or.check
+    }
+  if$
+}
+
+FUNCTION { format.bvolume.noseries }
+{
+  volume empty.or.unknown
+    { "" }
+    { "Vol.~\bibinfo{volume}{" volume "}" * *
+      "volume and number" number either.or.check
+    }
+  if$
+}
+
+FUNCTION { format.series }
+{
+  series empty.or.unknown
+    {""}
+    {" \emph{(\bibinfo{series}{" * series "}" *
+     volume empty.or.unknown
+       {
+         number empty.or.unknown
+            {")}" *}
+            {", \bibinfo{number}{" number "})}" * * *}
+          if$
+       }
+       {", Vol.~\bibinfo{volume}{" volume "})}" * * *
+        "volume and number" number either.or.check
+       }
+     if$
+    }
+  if$
+}
+
+FUNCTION { format.number.series }
+{
+  volume empty.or.unknown
+    {
+      number empty.or.unknown
+        {
+          volume empty.or.unknown
+          { "" }
+          {
+            series empty.or.unknown
+              { "" }
+              { " (\bibinfo{series}{" series * "})" * }
+            if$
+          }
+          if$
+        }                                       %    { series field.or.null }
+        {
+          output.state mid.sentence =
+            { "Number" }                        % gnp - changed to mixed case always
+            { "Number" }
+          if$
+          number tie.or.space.connect series empty.or.unknown
+            { "there's a number but no series in " cite$ * warning$ }
+            { " in \bibinfo{series}{" * series * "}" * }
+          if$
+        }
+      if$
+    }
+    {
+      ""
+    }
+  if$
+}
+
+FUNCTION { multi.page.check }
+{
+  't :=
+  #0 'multiresult :=
+    { multiresult not
+      t empty.or.unknown 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.pages }
+{
+  pages empty.or.unknown
+    { "" }
+    { "\bibinfo{pages}{"
+      pages multi.page.check
+        { pages n.dashify } % gnp - removed () % jtb: removed pp.
+        { pages }
+      if$
+      * "}" *
+    }
+  if$
+}
+
+FUNCTION { format.pages.check.without.articleno }
+{ %% format pages field only if articleno is absent
+  %% Stack out: pages-specification
+  numpages missing$ pages missing$ and
+    { "page numbers missing in both pages and numpages fields in " cite$ * warning$ }
+    { }
+  if$
+
+  articleno empty.or.unknown eid empty.or.unknown and
+    {
+      pages missing$
+        {
+	   numpages empty.or.unknown
+	     {""}
+             { "\bibinfo{numpages}{" numpages * "}~pages" * }
+	  if$
+	}
+        { format.pages }
+      if$
+    }
+    { "" }
+  if$
+}
+
+FUNCTION { format.pages.check }
+{
+  pages empty.or.unknown
+    { "page numbers missing in " cite$ * warning$ "" }
+    { pages n.dashify }
+  if$
+}
+
+FUNCTION { format.bookpages }
+{
+  bookpages empty.or.unknown
+    { "" }
+    { bookpages "book pages" tie.or.space.connect }
+  if$
+}
+
+FUNCTION { format.named.pages }
+{
+  pages empty.or.unknown
+    { "" }
+    { format.pages "pages" tie.or.space.connect }
+  if$
+}
+
+%
+% Changed by Boris Veytsman, 2011-03-13
+% Now the word "pages" is printed even if
+% there field pages is not empty.
+%
+
+FUNCTION { format.page.count }
+{
+  page.count empty.or.unknown
+    { "" }
+    { "\bibinfo{numpages}{" page.count * "}~pages" * }
+  if$
+}
+
+FUNCTION { format.articleno.numpages }
+{
+  %% There are seven possible outputs, depending on which fields are set.
+  %%
+  %% These four are handled here:
+  %%
+  %%     articleno, numpages, pages     -> "Article articleno-value, numpages-value pages"
+  %%     articleno, numpages            -> "Article articleno-value, numpages-value pages"
+  %%     articleno, pages               -> "Article articleno-value, reduced-pages-value pages"
+  %%     articleno                      -> "Article articleno-value" and warn about missing numpages
+  %%
+  %% The remaining three have already been handled by
+  %% format.pages.check.without.articleno:
+  %%
+  %%     numpages, pages                -> "pages-value"
+  %%     numpages                       -> "numpages-value"
+  %%     pages                          -> "pages-value"
+  %%
+  %% We no longer issue warninig when missing articleno, but having numpages
+
+  articleno empty.or.unknown eid empty.or.unknown and
+    {
+%%      numpages empty.or.unknown
+%%        { }
+%%        { "numpages field, but no articleno or eid field, in "
+%%          cite$ * warning$ }
+%%      if$
+      ""
+    }
+    {
+      numpages empty.or.unknown
+        {
+          pages empty.or.unknown
+            {
+              "articleno or eid, but no pages or numpages field in "
+                 cite$ * warning$
+              "" 'page.count :=
+            }
+            { reduce.pages.to.page.count }
+          if$
+        }
+        { numpages 'page.count := }
+      if$
+
+      %% The Article number is now handled in format.day.month.year because
+      %% ACM prefers the style "Digital Libraries 12, 3, Article 5 (July 2008)"
+      %% over "Digital Libraries 12, 3 (July 2008), Article 5"
+      %% format.articleno output
+      format.page.count
+    }
+  if$
+}
+
+FUNCTION {calc.format.page.count}
+{
+  numpages empty.or.unknown
+   {
+     pages empty.or.unknown
+        {
+        "" 'page.count :=
+        }
+        { reduce.pages.to.page.count }
+     if$
+   }
+   { numpages 'page.count := }
+  if$
+  format.page.count
+}
+
+
+FUNCTION { journal.canon.abbrev }
+{
+  % Returns a canonical abbreviation for 'journal', or else 'journal'
+  % unchanged.
+  journal "ACM Computing Surveys"                                                                       = { "Comput. Surveys"                                 } {
+  journal "{ACM} Computing Surveys"                                                                     = { "Comput. Surveys"                                 } {
+  journal "ACM Transactions on Mathematical Software"                                                   = { "ACM Trans. Math. Software"                       } {
+  journal "{ACM} Transactions on Mathematical Software"                                                 = { "ACM Trans. Math. Software"                       } {
+  journal "ACM SIGNUM Newsletter"                                                                       = { "ACM SIGNUM Newslett."                            } {
+  journal "ACM {SIGNUM} Newsletter"                                                                     = { "ACM SIGNUM Newslett."                            } {
+  journal "{ACM} SIGNUM Newsletter"                                                                     = { "ACM SIGNUM Newslett."                            } {
+  journal "{ACM} {SIGNUM} Newsletter"                                                                   = { "ACM SIGNUM Newslett."                            } {
+  journal "American Journal of Sociology"                                                               = { "Amer. J. Sociology"                              } {
+  journal "American Mathematical Monthly"                                                               = { "Amer. Math. Monthly"                             } {
+  journal "American Mathematical Society Translations"                                                  = { "Amer. Math. Soc. Transl."                        } {
+  journal "Applied Mathematics and Computation"                                                         = { "Appl. Math. Comput."                             } {
+  journal "British Journal of Mathematical and Statistical Psychology"                                  = { "Brit. J. Math. Statist. Psych."                  } {
+  journal "Bulletin of the American Mathematical Society"                                               = { "Bull. Amer. Math. Soc."                          } {
+  journal "Canadian Mathematical Bulletin"                                                              = { "Canad. Math. Bull."                              } {
+  journal "Communications of the ACM"                                                                   = { "Commun. ACM"                                     } {
+  journal "Communications of the {ACM}"                                                                 = { "Commun. ACM"                                     } {
+  journal "Computers and Structures"                                                                    = { "Comput. \& Structures"                           } {
+  journal "Contemporary Mathematics"                                                                    = { "Contemp. Math."                                  } {
+  journal "Crelle's Journal"                                                                            = { "Crelle's J."                                     } {
+  journal "Giornale di Mathematiche"                                                                    = { "Giorn. Mat."                                     } {
+  journal "IEEE Transactions on Aerospace and Electronic Systems"                                       = { "IEEE Trans. Aerospace Electron. Systems"         } {
+  journal "{IEEE} Transactions on Aerospace and Electronic Systems"                                     = { "IEEE Trans. Aerospace Electron. Systems"         } {
+  journal "IEEE Transactions on Automatic Control"                                                      = { "IEEE Trans. Automat. Control"                    } {
+  journal "{IEEE} Transactions on Automatic Control"                                                    = { "IEEE Trans. Automat. Control"                    } {
+  journal "IEEE Transactions on Computers"                                                              = { "IEEE Trans. Comput."                             } {
+  journal "{IEEE} Transactions on Computers"                                                            = { "IEEE Trans. Comput."                             } {
+  journal "IMA Journal of Numerical Analysis"                                                           = { "IMA J. Numer. Anal."                             } {
+  journal "{IMA} Journal of Numerical Analysis"                                                         = { "IMA J. Numer. Anal."                             } {
+  journal "Information Processing Letters"                                                              = { "Inform. Process. Lett."                          } {
+  journal "International Journal for Numerical Methods in Engineering"                                  = { "Internat. J. Numer. Methods Engrg."              } {
+  journal "International Journal of Control"                                                            = { "Internat. J. Control"                            } {
+  journal "International Journal of Supercomputing Applications"                                        = { "Internat. J. Supercomputing Applic."             } {
+  journal "Journal of Computational Physics"                                                            = { "J. Comput. Phys."                                } {
+  journal "Journal of Computational and Applied Mathematics"                                            = { "J. Comput. Appl. Math."                          } {
+  journal "Journal of Computer and System Sciences"                                                     = { "J. Comput. System Sci."                          } {
+  journal "Journal of Mathematical Analysis and Applications"                                           = { "J. Math. Anal. Appl."                            } {
+  journal "Journal of Mathematical Physics"                                                             = { "J. Math. Phys."                                  } {
+  journal "Journal of Parallel and Distributed Computing"                                               = { "J. Parallel and Distrib. Comput."                } {
+  journal "Journal of Research of the National Bureau of Standards"                                     = { "J. Res. Nat. Bur. Standards"                     } {
+  journal "Journal of VLSI and Computer Systems"                                                        = { "J. VLSI Comput. Syst."                           } {
+  journal "Journal of {VLSI} and Computer Systems"                                                      = { "J. VLSI Comput. Syst."                           } {
+  journal "Journal of the ACM"                                                                          = { "J. ACM"                                          } {
+  journal "Journal of the American Statistical Association"                                             = { "J. Amer. Statist. Assoc."                        } {
+  journal "Journal of the Institute of Mathematics and its Applications"                                = { "J. Inst. Math. Appl."                            } {
+  journal "Journal of the Society for Industrial and Applied Mathematics"                               = { "J. Soc. Indust. Appl. Math."                     } {
+  journal "Journal of the Society for Industrial and Applied Mathematics, Series B, Numerical Analysis" = { "J. Soc. Indust. Appl. Math. Ser. B Numer. Anal." } {
+  journal "Linear Algebra and its Applications"                                                         = { "Linear Algebra Appl."                            } {
+  journal "Mathematica Scandinavica"                                                                    = { "Math. Scand."                                    } {
+  journal "Mathematical Tables and Other Aids to Computation"                                           = { "Math. Tables Aids Comput."                       } {
+  journal "Mathematics of Computation"                                                                  = { "Math. Comp."                                     } {
+  journal "Mathematische Annalen"                                                                       = { "Math. Ann."                                      } {
+  journal "Numerische Mathematik"                                                                       = { "Numer. Math."                                    } {
+  journal "Pacific Journal of Mathematics"                                                              = { "Pacific J. Math."                                } {
+  journal "Parallel Computing"                                                                          = { "Parallel Comput."                                } {
+  journal "Philosophical Magazine"                                                                      = { "Philos. Mag."                                    } {
+  journal "Proceedings of the American Mathematical Society"                                            = { "Proc. Amer. Math. Soc."                          } {
+  journal "Proceedings of the IEEE"                                                                     = { "Proc. IEEE"                                      } {
+  journal "Proceedings of the {IEEE}"                                                                   = { "Proc. IEEE"                                      } {
+  journal "Proceedings of the National Academy of Sciences of the USA"                                  = { "Proc. Nat. Acad. Sci. U. S. A."                  } {
+  journal "Quarterly Journal of Mathematics, Oxford, Series (2)"                                        = { "Quart. J. Math. Oxford Ser. (2)"                 } {
+  journal "Quarterly of Applied Mathematics"                                                            = { "Quart. Appl. Math."                              } {
+  journal "Review of the International Statisical Institute"                                            = { "Rev. Inst. Internat. Statist."                   } {
+  journal "SIAM Journal on Algebraic and Discrete Methods"                                              = { "SIAM J. Algebraic Discrete Methods"              } {
+  journal "{SIAM} Journal on Algebraic and Discrete Methods"                                            = { "SIAM J. Algebraic Discrete Methods"              } {
+  journal "SIAM Journal on Applied Mathematics"                                                         = { "SIAM J. Appl. Math."                             } {
+  journal "{SIAM} Journal on Applied Mathematics"                                                       = { "SIAM J. Appl. Math."                             } {
+  journal "SIAM Journal on Computing"                                                                   = { "SIAM J. Comput."                                 } {
+  journal "{SIAM} Journal on Computing"                                                                 = { "SIAM J. Comput."                                 } {
+  journal "SIAM Journal on Matrix Analysis and Applications"                                            = { "SIAM J. Matrix Anal. Appl."                      } {
+  journal "{SIAM} Journal on Matrix Analysis and Applications"                                          = { "SIAM J. Matrix Anal. Appl."                      } {
+  journal "SIAM Journal on Numerical Analysis"                                                          = { "SIAM J. Numer. Anal."                            } {
+  journal "{SIAM} Journal on Numerical Analysis"                                                        = { "SIAM J. Numer. Anal."                            } {
+  journal "SIAM Journal on Scientific and Statistical Computing"                                        = { "SIAM J. Sci. Statist. Comput."                   } {
+  journal "{SIAM} Journal on Scientific and Statistical Computing"                                      = { "SIAM J. Sci. Statist. Comput."                   } {
+  journal "SIAM Review"                                                                                 = { "SIAM Rev."                                       } {
+  journal "{SIAM} Review"                                                                               = { "SIAM Rev."                                       } {
+  journal "Software Practice and Experience"                                                            = { "Software Prac. Experience"                       } {
+  journal "Statistical Science"                                                                         = { "Statist. Sci."                                   } {
+  journal "The Computer Journal"                                                                        = { "Comput. J."                                      } {
+  journal "Transactions of the American Mathematical Society"                                           = { "Trans. Amer. Math. Soc."                         } {
+  journal "USSR Computational Mathematics and Mathematical Physics"                                     = { "U. S. S. R. Comput. Math. and Math. Phys."       } {
+  journal "{USSR} Computational Mathematics and Mathematical Physics"                                   = { "U. S. S. R. Comput. Math. and Math. Phys."       } {
+  journal "Zeitschrift fur Angewandte Mathematik und Mechanik"                                          = { "Z. Angew. Math. Mech."                           } {
+  journal "Zeitschrift fur Angewandte Mathematik und Physik"                                            = { "Z. Angew. Math. Phys."                           } {
+  journal
+  } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$
+  } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$
+  } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$
+  } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$
+  } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$
+  } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$
+  } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$
+  } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$
+}
+
+FUNCTION { format.journal.volume.number.day.month.year }
+{
+  % By Young (and Spencer)
+  % GNP - fixed bugs with missing volume, number, and/or pages
+  %
+  % Format journal, volume, number, pages for article types.
+  %
+  journal empty.or.unknown
+    { "no journal in " cite$ * warning$ "" }
+    { "\bibinfo{journal}{"
+      journal.canon.abbrev emphasize *
+      "}" * }
+  if$
+
+  number empty.or.unknown
+    {
+      volume empty.or.unknown
+        { "no number and no volume in " cite$ * warning$ "" * }
+        { " " * " \bibinfo{volume}{" * volume * "}" * }
+      if$
+    }
+    {
+      volume empty.or.unknown
+        {
+          "unusual to have number, but no volume, for " cite$ * warning$
+          " \bibinfo{number}{" * number * "}" *
+        }
+        { " \bibinfo{volume}{" * volume  * "}, \bibinfo{number}{" *
+          number * "}" *}
+      if$
+    }
+  if$
+  after.block 'output.state :=
+
+  % Sometimes proceedings are published in journals
+  % In this case we do not want to put year, day and month here
+
+  type$ "inproceedings" =
+    { }
+    {format.day.month.year * }
+  if$
+}
+
+FUNCTION { format.chapter.pages }
+{
+  chapter empty.or.unknown
+    'format.pages
+    { type empty.or.unknown
+        { "Chapter" } % gnp - changed to mixed case
+        { type "t" change.case$ }
+      if$
+      chapter tie.or.space.connect
+      pages empty.or.unknown
+        {"page numbers missing in " cite$ * warning$} % gnp - added check
+        { ", " * format.pages * }
+      if$
+    }
+  if$
+}
+
+FUNCTION { format.in.emphasize.booktitle }
+{ % jtb: format for collections or proceedings not appearing in a journal
+  booktitle empty.or.unknown
+  { "" }
+  { "In " format.emphasize.booktitle * }
+  if$
+}
+
+FUNCTION { format.in.booktitle }
+{ % jtb: format for proceedings appearing in a journal
+  booktitle empty.or.unknown
+  { "" }
+  { "In \bibinfo{booktitle}{" booktitle * "}" * }
+  if$
+}
+
+FUNCTION { format.in.ed.booktitle }
+{
+  booktitle empty.or.unknown
+  { "" }
+  { editor empty.or.unknown
+    { "In " format.emphasize.booktitle * }
+                % jtb: swapped editor location
+    { "In " format.emphasize.booktitle * ", " * format.editors.fml * }
+    if$
+  }
+  if$
+}
+
+FUNCTION { format.thesis.type }
+{ % call with default type on stack top
+  type empty.or.unknown
+    'skip$    % use default type
+    {
+      pop$    % discard default type
+      % NO: it is silly to have to brace protect every degree type!:  type "t" change.case$
+      type
+    }
+  if$
+}
+
+FUNCTION { format.tr.number }
+{
+  "\bibinfo{type}{"
+  type empty.or.unknown
+    { "{T}echnical {R}eport" }
+    'type
+  if$
+  "}" * *
+  number empty.or.unknown
+    { "t" change.case$ }
+    %% LOOKS BAD: { "." * number tie.or.space.connect }
+    %% Prefer "Research report RJ687." to "Research report. RJ687."
+    { number tie.or.space.connect }
+  if$
+}
+
+FUNCTION { format.advisor }
+{
+  advisor empty.or.unknown
+    { "" }
+    { "Advisor(s) " advisor * }
+  if$
+}
+
+FUNCTION { format.article.crossref }
+{ "See"
+  "\citeN{" * crossref * "}" *
+}
+
+FUNCTION { format.crossref.editor }
+{
+  editor #1 "{vv~}{ll}" format.name$
+  editor num.names$ duplicate$
+  #2 >
+    { pop$ " et~al\mbox{.}" * }         % jrh: avoid spacing problems
+    { #2 <
+    'skip$
+    { editor #2 "{ff }{vv }{ll}{ jj}" format.name$ "others" =
+        { " et~al\mbox{.}" * }          % jrh: avoid spacing problems
+        { " and " * editor #2 "{vv~}{ll}" format.name$ * }
+      if$
+    }
+      if$
+    }
+  if$
+}
+
+FUNCTION { format.book.crossref }
+{
+  volume empty.or.unknown
+    { "empty volume in " cite$ * "'s crossref of " * crossref * warning$
+      "In "
+    }
+    { "Volume" volume tie.or.space.connect % gnp - changed to mixed case
+      " of " *
+    }
+  if$
+  editor empty.or.unknown
+  editor field.or.null author field.or.null =
+  or
+    { key empty.or.unknown
+    { series empty.or.unknown
+        { "need editor, key, or series for " cite$ * " to crossref " *
+          crossref * warning$
+          "" *
+        }
+        { series emphasize * }
+      if$
+    }
+    { key * }
+      if$
+    }
+    { format.crossref.editor * }
+  if$
+  " \citeN{" * crossref * "}" *
+}
+
+FUNCTION { format.incoll.inproc.crossref }
+{ "See"
+  " \citeN{" * crossref * "}" *
+}
+
+FUNCTION { format.lab.names }
+{
+  % format.lab.names:
+  %
+  % determines "short" names for the abbreviated author information.
+  % "Long" labels are created in calc.label, using the routine my.full.label
+  % to format author and editor fields.
+  %
+  % There are 4 cases for labels.   (n=3 in the example)
+  % a) one author             Foo
+  % b) one to n               Foo, Bar and Baz
+  % c) use of "and others"    Foo, Bar et al.
+  % d) more than n            Foo et al.
+
+  's :=
+  s num.names$ 'numnames :=
+  numnames #2 >    % change number to number of others allowed before
+                   % forcing "et al".
+    { s #1 "{vv~}{ll}" format.name$ " et~al\mbox{.}" * } % jrh: \mbox{} added
+    {
+      numnames #1 - 'namesleft :=
+      #2 'nameptr :=
+      s #1 "{vv~}{ll}" format.name$
+        { namesleft #0 > }
+        { nameptr numnames =
+            { s nameptr "{ff }{vv }{ll}{ jj}" format.name$ "others" =
+                { " et~al\mbox{.}" * }          % jrh: avoid spacing problems
+                { " and " * s nameptr "{vv~}{ll}" format.name$ * }
+              if$
+            }
+            { ", " * s nameptr "{vv~}{ll}" format.name$ * }
+          if$
+          nameptr #1 + 'nameptr :=
+          namesleft #1 - 'namesleft :=
+        }
+      while$
+    }
+  if$
+}
+
+FUNCTION { author.key.label }
+{
+  author empty.or.unknown
+    { key empty.or.unknown
+          { "no key, author in " cite$ * warning$
+            cite$ #1 #3 substring$ }
+         'key
+      if$
+    }
+    { author format.lab.names }
+  if$
+}
+
+FUNCTION { editor.key.organization.label }
+{ % added - gnp. Provide label formatting by organization if editor is null.
+  editor empty.or.unknown
+    { organization empty.or.unknown
+        { key empty.or.unknown
+            { "no key, editor or organization in " cite$ * warning$
+              cite$ #1 #3 substring$ }
+            'key
+          if$
+        }
+        { organization }
+      if$
+    }
+    { editor format.lab.names }
+  if$
+}
+
+FUNCTION { author.editor.key.label }
+{
+  author empty.or.unknown
+    { editor empty.or.unknown
+          { key empty.or.unknown
+               { "no key, author, or editor in " cite$ * warning$
+                 cite$ #1 #3 substring$ }
+             'key
+           if$
+         }
+          { editor format.lab.names }
+      if$
+    }
+    { author format.lab.names }
+  if$
+}
+
+FUNCTION { author.editor.key.organization.label }
+{ % added - gnp. Provide label formatting by organization if author is null.
+  author empty.or.unknown
+    { editor empty.or.unknown
+        { organization empty.or.unknown
+            { key empty.or.unknown
+               { "no key, author, editor or organization in " cite$ * warning$
+                 cite$ #1 #3 substring$ }
+               'key
+              if$
+            }
+            { organization }
+          if$
+        }
+        { editor format.lab.names }
+      if$
+    }
+    { author format.lab.names }
+  if$
+}
+
+% Calculate label and leave it on stack
+FUNCTION { calc.basic.label }
+{
+  type$ "book" =
+  type$ "inbook" =
+  or
+  type$ "article" =
+  or
+    'author.editor.key.label
+    { type$ "proceedings" =
+      type$ "periodical" =
+      or
+        'editor.key.organization.label
+        { type$ "manual" =
+            'author.editor.key.organization.label
+            'author.key.label
+          if$
+        }
+      if$
+    }
+  if$
+  duplicate$
+  year empty.or.unknown
+    { "[n.\,d.]" }
+    { year field.or.null purify$ #-1 #4 substring$}
+  if$
+  *
+  'basic.label.year :=
+}
+
+FUNCTION { calc.label }
+{
+  % Changed - GNP. See also author.editor.organization.sort, editor.organization.sort
+  % Form label for BibTeX entry. The classification of which fields are used
+  % for which type of entry (book, inbook, etc.) are taken from alpha.bst.
+  % The change here from newapa is to also include organization as a
+  % citation label if author or editor is missing.
+
+  calc.basic.label
+
+  author empty.or.unknown  % generate the full label citation information.
+    {
+      editor empty.or.unknown
+        {
+          organization empty.or.unknown
+            {
+              key empty.or.unknown
+                {
+                  "no author, editor, organization, or key in " cite$ * warning$
+                  "??"
+                }
+                { key }
+              if$
+            }
+            { organization }
+          if$
+        }
+        { editor my.full.label }
+      if$
+    }
+    { author my.full.label }
+  if$
+
+  % leave label on the stack, to be popped when required.
+
+  "}{" * swap$ * "}{" *
+  %  year field.or.null purify$ #-1 #4 substring$ *
+  %
+  % save the year for sort processing afterwards (adding a, b, c, etc.)
+  %
+  year empty.or.unknown
+    { "[n.\,d.]" }
+    { year field.or.null purify$ #-1 #4 substring$}
+  if$
+  'label.year :=
+}
+
+
+FUNCTION { output.bibitem }
+{
+  newline$
+  "\bibitem[" write$
+  calc.basic.label write$
+  "(" write$
+  sort.year write$
+  ")" write$
+  "]%" writeln
+  "        {" write$
+  cite$ write$
+  "}" writeln
+  ""
+  before.all 'output.state :=
+}
+
+
+FUNCTION { output.issue.doi.coden.isxn.lccn.url.eprint }
+{ % enter and return with stack empty
+  %% We switch now from buffered output to output of complete lines, so
+  %% that the Issue .. URL data have their own lines, and are less likely
+  %% to be line-wrapped by BibTeX's short-sighted algorithm, which wraps
+  %% lines longer than 79 characters, backtracking to what it thinks is
+  %% a break point in the string.  Any such wrapping MUST be undone to
+  %% prevent percent-newline from appearing in DOIs and URLs.  The
+  %% output data are intentionally wrapped in \showxxx{} macros at
+  %% beginning of line, and that supply their own punctuation (if they
+  %% are not defined to suppress output entirely), to make it easier for
+  %% other software to recover them from .bbl files.
+  %%
+  %% It also makes it possible to later change the macro definitions
+  %% to suppress particular output values, or alter their appearance.
+  %%
+  %% Note that it is possible for theses, technical reports, and
+  %% manuals to have ISBNs, and anything that has an ISBN may also
+  %% have an ISSN.  When there are no values for these keys, there
+  %% is no output generated for them here.
+
+  "\newblock" writeln
+  after.block 'output.state :=
+
+  output.issue
+  output.isbn
+  output.coden  % CODEN is functionally like ISSN, so output them sequentially
+  output.issn
+  output.lccn
+  output.doi    % DOI is ALWAYS last according to CrossRef DOI documentation
+  output.eprint
+  output.url    % but ACM wants URL last
+}
+
+FUNCTION { output.issue.doi.coden.isxn.lccn.url.eprint.note }
+{ % enter with stack empty, return with empty string on stack
+  output.issue.doi.coden.isxn.lccn.url.eprint
+  note empty.or.unknown
+    { }
+    {
+      "\newblock" writeln
+      output.note
+    }
+  if$
+  ""
+}
+
+FUNCTION { output.issue.doi.coden.isxn.lccn.url.eprint.note.check }
+{ % enter with stack empty, return with empty string on stack
+  output.issue.doi.coden.isxn.lccn.url.eprint
+  note empty.or.unknown
+    { }
+    {
+      "\newblock" writeln
+      output.note.check
+    }
+  if$
+  ""
+}
+
+FUNCTION { article }
+{
+  output.bibitem
+
+  author empty.or.unknown
+    {
+      editor empty.or.unknown
+        { "neither author and editor supplied for " cite$ * warning$ }
+        { format.editors "editor" output.check }
+      if$
+    }
+    { format.authors "author" output.check }
+  if$
+
+  author format.no.key output       % added
+  output.year.check                 % added
+  new.block
+  format.articletitle "title" output.check
+  new.block
+  howpublished empty.or.unknown
+    { }
+    { "\bibinfo{howpublished}{" howpublished "}" * * output }
+  if$
+
+  crossref missing$
+    { format.journal.volume.number.day.month.year output}
+    {
+      "cross reference in @Article{...} is unusual" warning$
+      format.article.crossref output.nonnull
+    }
+  if$
+
+  format.pages.check.without.articleno output
+  format.articleno.numpages output
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { book }
+{
+  output.bibitem
+  author empty.or.unknown
+    { format.editors "author and editor" output.check }
+    { format.authors output.nonnull
+      crossref missing$
+        { "author and editor" editor either.or.check }
+        'skip$
+      if$
+    }
+  if$
+  output.year.check       % added
+  new.block
+  format.btitle "title" output.check
+  crossref missing$
+    { new.sentence              % jtb: start a new sentence for series/volume
+      format.bvolume output
+      new.block
+      format.number.series output
+      new.sentence
+      publisher "publisher" bibinfo.output.check
+      address "address" bibinfo.output.check    % jtb: require address
+      fin.sentence
+      pages empty.or.unknown
+        { format.bookpages }    % use bookpages when pages empty
+        { format.pages.check "pages" tie.or.space.connect }
+      if$
+      output
+    }
+    { new.block
+      format.book.crossref output.nonnull
+    }
+  if$
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { booklet }
+{
+  output.bibitem
+  format.authors output
+  author format.key output          % added
+  output.year.check                 % added
+  new.block
+  format.title "title" output.check
+  new.block
+    howpublished empty.or.unknown
+    { }
+    { "\bibinfo{howpublished}{" howpublished "}" * * output }
+  if$
+  address output
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { inbook }
+{
+  output.bibitem
+  author empty.or.unknown
+    { format.editors
+      "author and editor" output.check
+    }
+    { format.authors output.nonnull
+      crossref missing$
+    { "author and editor" editor either.or.check }
+    'skip$
+      if$
+    }
+  if$
+  output.year.check                 % added
+  new.block
+  format.btitle "title" output.check
+  crossref missing$
+    { new.sentence              % jtb: start a new sentence for series/volume
+      format.bvolume output
+      new.block
+      format.number.series output
+      new.sentence
+      publisher "publisher" bibinfo.output.check
+      address "address" bibinfo.output.check    % jtb: require address
+      format.bookpages output
+      format.chapter.pages
+      "chapter and pages" output.check  % jtb: moved from before publisher
+    }
+    {
+      format.bookpages output
+      format.chapter.pages "chapter and pages" output.check
+      new.block
+      format.book.crossref output.nonnull
+    }
+  if$
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { incollection }
+{
+  output.bibitem
+  format.authors "author" output.check
+  author format.key output       % added
+  output.year.check              % added
+  new.block
+  format.articletitle "title" output.check
+  new.block
+  crossref missing$
+    { format.in.ed.booktitle "booktitle" output.check
+      new.sentence                % jtb: start a new sentence for series/volume
+      format.bvolume output
+      format.number.series output
+      new.sentence
+      publisher "publisher" bibinfo.output.check
+      address "address" bibinfo.output.check      % jtb: require address
+      format.bookpages output
+      format.chapter.pages output % gnp - was special.output.nonnull
+                                  % left out comma before page numbers
+                                  % jtb: moved from before publisher
+    }
+    {
+      format.incoll.inproc.crossref output.nonnull
+      format.chapter.pages output
+    }
+  if$
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { inproceedings }
+{
+  output.bibitem
+  format.authors "author" output.check
+  author format.key output            % added
+  output.year.check                   % added
+  new.block
+  format.articletitle "title" output.check
+  howpublished empty.or.unknown
+    { }
+    { "\bibinfo{howpublished}{" howpublished "}" * * output.dot.space }
+  if$
+  crossref missing$
+    {
+      journal missing$          % jtb: proceedings appearing in journals
+        { format.in.emphasize.booktitle format.city "booktitle"  output.check.dot.space
+          format.series output.removenospace
+          format.editors.fml output % BV 2011/09/27 Moved dot to comma
+          series empty.or.unknown
+              { format.bvolume.noseries output }
+              {}
+          if$
+          new.sentence
+          organization output
+          publisher "publisher" bibinfo.output.check % jtb: require publisher (?)
+          address "address" bibinfo.output.check  % jtb: require address
+          format.bookpages output
+        }
+        {
+           format.in.booktitle format.city "booktitle" output.check
+           format.editors.fml output
+           new.sentence
+           format.journal.volume.number.day.month.year output
+        }
+      if$
+      format.articleno output
+      format.pages.check.without.articleno output
+    }
+    {
+      format.incoll.inproc.crossref output.nonnull
+      format.articleno output
+      format.pages.check.without.articleno output
+    }
+  if$
+  format.articleno.numpages output
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { conference } { inproceedings }
+
+FUNCTION { manual }
+{
+  output.bibitem
+  author empty.or.unknown
+    { editor empty.or.unknown
+      { organization "organization" output.check
+        organization format.key output }  % if all else fails, use key
+      { format.editors "author and editor" output.check }
+      if$
+    }
+    { format.authors output.nonnull }
+    if$
+  output.year.check                 % added
+  new.block
+  format.btitle "title" output.check
+  organization address new.block.checkb
+  % jtb: back to normal style: organization, address
+  organization "organization" output.check
+  address output
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { mastersthesis }
+{
+  output.bibitem
+  format.authors "author" output.check
+  author format.key output          % added
+  output.year.check                 % added
+  new.block
+  format.title emphasize "title" output.check  % NB: ACM style requires emphasized thesis title
+  new.block
+  "\bibinfo{thesistype}{Master's\ thesis}" format.thesis.type output
+  new.sentence
+  school "school" bibinfo.output.check
+  address empty.or.unknown
+     { }
+     { "\bibinfo{address}{" address * "}" * output }
+  if$
+  new.block
+  format.advisor output
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { misc }
+{
+  output.bibitem
+  format.authors "author" output.check
+  author format.key output            % added
+  output.year.check                   % added
+  title howpublished new.block.checkb
+  format.title output
+  new.block
+  howpublished empty.or.unknown
+    { }
+    { "\bibinfo{howpublished}{" howpublished "}" * * output }
+  if$
+  "" output.nonnull.dot.space
+  calc.format.page.count output
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { online } { manual }
+
+FUNCTION { game } { manual }
+
+FUNCTION { artifactsoftware } { manual }
+
+FUNCTION { artifactdataset } { manual }
+
+FUNCTION { software } { manual }
+
+FUNCTION { dataset } { manual }
+
+FUNCTION { phdthesis }
+{
+  output.bibitem
+  format.authors "author" output.check
+  author format.key output          % added
+  output.year.check                 % added
+  new.block
+  format.title emphasize "title" output.check  % NB: ACM style requires emphasized thesis title
+  new.block
+  "\bibinfo{thesistype}{Ph.\,D. Dissertation}" format.thesis.type output
+  new.sentence
+  school "school" bibinfo.output.check
+  address empty.or.unknown
+     { }
+     { "\bibinfo{address}{" address * "}" * output }
+  if$
+  new.block
+  format.advisor output
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION {format.date}
+{ year empty.or.unknown
+    { month empty.or.unknown
+        {
+          ""                    % output empty date if year/month both empty
+          day empty.or.unknown
+            {  }
+            { "there's a day but no month or year in " cite$ * warning$ }
+          if$
+        }
+        { "there's a month but no year in " cite$ * warning$
+          month
+          day empty.or.unknown
+            { }
+            { " " * day * }
+          if$
+        }
+      if$
+    }
+    { month empty.or.unknown
+        {
+          year                  % output only year if month empty
+          day empty.or.unknown
+            {  }
+            { "there's a day and year but no month in " cite$ * warning$ }
+          if$
+        }
+        {
+          month " " *
+          day empty.or.unknown
+            { }
+            { day * ", " * }
+          if$
+          year *
+        }
+      if$
+    }
+  if$
+}
+
+FUNCTION {new.block.checka}
+{
+  empty.or.unknown
+    'skip$
+    'new.block
+  if$
+}
+
+FUNCTION { periodical }
+{
+  output.bibitem
+  editor empty.or.unknown
+    { organization output }
+    { format.editors output.nonnull }
+  if$
+  new.block
+  output.year.check
+  new.sentence
+  format.articletitle "title" output.check
+  format.journal.volume.number.day.month.year output
+  calc.format.page.count output
+  fin.entry
+}
+
+FUNCTION { proceedings }
+{
+  output.bibitem
+  editor empty.or.unknown
+    { organization output
+      organization format.key output }  % gnp - changed from author format.key
+    { format.editors output.nonnull }
+  if$
+  % author format.key output             % gnp - removed (should be either
+  %                                        editor or organization
+  output.year.check                    % added (newapa)
+  new.block
+  format.btitle format.city "title" output.check        % jtb: added city
+  new.sentence
+  format.bvolume output
+  format.number.series output
+  new.sentence
+  organization output
+  % jtb: normal order: publisher, address
+  publisher empty.or.unknown
+     { }
+     { "\bibinfo{publisher}{" publisher * "}" * output }
+  if$
+  address empty.or.unknown
+     { }
+     { "\bibinfo{address}{" address * "}" * output }
+  if$
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { collection } { proceedings }
+
+FUNCTION { techreport }
+{
+  output.bibitem
+  format.authors "author" output.check
+  author format.key output             % added
+  output.year.check                    % added
+  new.block
+  format.btitle "title" output.check
+  new.block
+%   format.tr.number output               % jtb: moved month ...
+  format.tr.number output new.sentence    % Gerry  - need dot 2011/09/28
+  institution "institution" bibinfo.output.check
+  address empty.or.unknown
+    { }
+    { "\bibinfo{address}{" address "}" * * output }
+  if$
+  new.sentence
+  format.named.pages output
+  % ACM omits year at end in transactions style
+  % format.day.month.year output.nonnull.dot.space  % jtb: ... to here (no parens)
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { unpublished }
+{
+  output.bibitem
+  format.authors
+  "author" output.check
+  author format.key output              % added
+  output.year.check                     % added
+  new.block
+  format.title "title" output.check
+  fin.sentence
+  output.day.month.year                 % UTAH
+  calc.format.page.count output
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note.check
+  fin.entry
+}
+
+FUNCTION { default.type } { misc }
+
+%%% ACM journal-style month definitions: full name if 1--5 letters, else
+%%% abbreviation of 3 or 4 characters and a dot
+
+MACRO {jan}             {"Jan."}
+
+MACRO {feb}             {"Feb."}
+
+MACRO {mar}             {"March"}
+
+MACRO {apr}             {"April"}
+
+MACRO {may}             {"May"}
+
+MACRO {jun}             {"June"}
+
+MACRO {jul}             {"July"}
+
+MACRO {aug}             {"Aug."}
+
+MACRO {sep}             {"Sept."}
+
+MACRO {oct}             {"Oct."}
+
+MACRO {nov}             {"Nov."}
+
+MACRO {dec}             {"Dec."}
+
+%%% ACM journal names
+
+MACRO {cie}  {"ACM Computers in Entertainment"}
+MACRO {csur}  {"ACM Computing Surveys"}
+MACRO {dgov}  {"Digital Government: Research and Practice"}
+MACRO {dtrap}  {"Digital Threats: Research and Practice"}
+MACRO {health}  {"ACM Transactions on Computing for Healthcare"}
+MACRO {imwut}  {"PACM on Interactive, Mobile, Wearable and Ubiquitous Technologies"}
+MACRO {jacm}  {"Journal of the ACM"}
+MACRO {jdiq}  {"ACM Journal of Data and Information Quality"}
+MACRO {jea}  {"ACM Journal of Experimental Algorithmics"}
+MACRO {jeric}  {"ACM Journal of Educational Resources in Computing"}
+MACRO {jetc}  {"ACM Journal on Emerging Technologies in Computing Systems"}
+MACRO {jocch}  {"ACM Journal on Computing and Cultural Heritage"}
+MACRO {pacmcgit}  {"Proceedings of the ACM on Computer Graphics and Interactive Techniques"}
+MACRO {pacmhci}  {"PACM on Human-Computer Interaction"}
+MACRO {pacmpl}  {"PACM on Programming Languages"}
+MACRO {pomacs}  {"PACM on Measurement and Analysis of Computing Systems"}
+MACRO {taas}  {"ACM Transactions on Autonomous and Adaptive Systems"}
+MACRO {taccess}  {"ACM Transactions on Accessible Computing"}
+MACRO {taco}  {"ACM Transactions on Architecture and Code Optimization"}
+MACRO {talg}  {"ACM Transactions on Algorithms"}
+MACRO {tallip}  {"ACM Transactions on Asian and Low-Resource Language Information Processing"}
+MACRO {tap}  {"ACM Transactions on Applied Perception"}
+MACRO {tcps}  {"ACM Transactions on Cyber-Physical Systems"}
+MACRO {tds}  {"ACM/IMS Transactions on Data Science"}
+MACRO {teac}  {"ACM Transactions on Economics and Computation"}
+MACRO {tecs}  {"ACM Transactions on Embedded Computing Systems"}
+MACRO {telo}  {"ACM Transactions on Evolutionary Learning"}
+MACRO {thri}  {"ACM Transactions on Human-Robot Interaction"}
+MACRO {tiis}  {"ACM Transactions on Interactive Intelligent Systems"}
+MACRO {tiot}  {"ACM Transactions on Internet of Things"}
+MACRO {tissec}  {"ACM Transactions on Information and System Security"}
+MACRO {tist}  {"ACM Transactions on Intelligent Systems and Technology"}
+MACRO {tkdd}  {"ACM Transactions on Knowledge Discovery from Data"}
+MACRO {tmis}  {"ACM Transactions on Management Information Systems"}
+MACRO {toce}  {"ACM Transactions on Computing Education"}
+MACRO {tochi}  {"ACM Transactions on Computer-Human Interaction"}
+MACRO {tocl}  {"ACM Transactions on Computational Logic"}
+MACRO {tocs}  {"ACM Transactions on Computer Systems"}
+MACRO {toct}  {"ACM Transactions on Computation Theory"}
+MACRO {todaes}  {"ACM Transactions on Design Automation of Electronic Systems"}
+MACRO {tods}  {"ACM Transactions on Database Systems"}
+MACRO {tog}  {"ACM Transactions on Graphics"}
+MACRO {tois}  {"ACM Transactions on Information Systems"}
+MACRO {toit}  {"ACM Transactions on Internet Technology"}
+MACRO {tomacs}  {"ACM Transactions on Modeling and Computer Simulation"}
+MACRO {tomm}   {"ACM Transactions on Multimedia Computing, Communications and Applications"}
+MACRO {tompecs}  {"ACM Transactions on Modeling and Performance Evaluation of Computing Systems"}
+MACRO {toms}  {"ACM Transactions on Mathematical Software"}
+MACRO {topc}  {"ACM Transactions on Parallel Computing"}
+MACRO {toplas}  {"ACM Transactions on Programming Languages and Systems"}
+MACRO {tops}  {"ACM Transactions on Privacy and Security"}
+MACRO {tos}  {"ACM Transactions on Storage"}
+MACRO {tosem}  {"ACM Transactions on Software Engineering and Methodology"}
+MACRO {tosn}  {"ACM Transactions on Sensor Networks"}
+MACRO {tqc}  {"ACM Transactions on Quantum Computing"}
+MACRO {trets}  {"ACM Transactions on Reconfigurable Technology and Systems"}
+MACRO {tsas}  {"ACM Transactions on Spatial Algorithms and Systems"}
+MACRO {tsc}  {"ACM Transactions on Social Computing"}
+MACRO {tslp}  {"ACM Transactions on Speech and Language Processing"}
+MACRO {tweb}  {"ACM Transactions on the Web"}
+
+%%% Some traditional macros
+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 {jcss} {"Journal of Computer and System Sciences"}
+
+MACRO {scp} {"Science of Computer Programming"}
+
+MACRO {sicomp} {"SIAM Journal on Computing"}
+
+MACRO {toois} {"ACM Transactions on Office Information Systems"}
+
+MACRO {tcs} {"Theoretical Computer Science"}
+
+
+
+READ
+
+FUNCTION { sortify }
+{
+  purify$
+  "l" change.case$
+}
+
+FUNCTION { chop.word }
+{
+  's :=
+  'len :=
+  s #1 len substring$ =
+    { s len #1 + global.max$ substring$ }
+    's
+  if$
+}
+
+FUNCTION { sort.format.names }
+{
+  's :=
+  #1 'nameptr :=
+  ""
+  s num.names$ 'numnames :=
+  numnames 'namesleft :=
+    { namesleft #0 > }
+    { nameptr #1 >
+          { "   " * }
+         'skip$
+      if$
+      s nameptr "{vv{ } }{ll{ }}{  f{ }}{  jj{ }}" format.name$ 't :=
+      nameptr numnames = t "others" = and
+          { " et~al" * }
+          { t sortify * }
+      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.or.unknown
+    { key empty.or.unknown
+         { "to sort, need author or key in " cite$ * warning$
+           "" }
+         { key sortify }
+      if$
+    }
+    { author sort.format.names }
+  if$
+}
+
+FUNCTION { author.editor.sort }
+{
+  author empty.or.unknown
+    {
+      editor empty.or.unknown
+         {
+           key empty.or.unknown
+             { "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.organization.sort }
+{
+  % added - GNP. Stack editor or organization for sorting (from alpha.bst).
+  % Unlike alpha.bst, we need entire names, not abbreviations
+
+  editor empty.or.unknown
+    { organization empty.or.unknown
+        { key empty.or.unknown
+            { "to sort, need editor, organization, or key in " cite$ * warning$
+              ""
+            }
+            { key sortify }
+          if$
+        }
+        { organization sortify }
+      if$
+    }
+    { editor sort.format.names }
+  if$
+}
+
+FUNCTION { author.editor.organization.sort }
+{
+  % added - GNP. Stack author or organization for sorting (from alpha.bst).
+  % Unlike alpha.bst, we need entire names, not abbreviations
+
+  author empty.or.unknown
+    {
+      editor empty.or.unknown
+        { organization empty.or.unknown
+            { key empty.or.unknown
+                { "to sort, need author, editor, or key in " cite$ * warning$
+                ""
+                }
+                { key sortify }
+              if$
+            }
+            { organization sortify }
+          if$
+        }
+        { editor sort.format.names }
+      if$
+    }
+    { author sort.format.names }
+  if$
+}
+
+FUNCTION { presort }
+{
+  % Presort creates the bibentry's label via a call to calc.label, and then
+  % sorts the entries based on entry type. Chicago.bst adds support for
+  % including organizations as the sort key; the following is stolen from
+  % alpha.bst.
+
+  calc.label
+  basic.label.year
+  swap$
+  "    "
+  swap$
+  * *
+  "    "
+  *
+  sortify
+  year field.or.null purify$ #-1 #4 substring$ * % add year
+  "    "
+  *
+  type$ "book" =
+  type$ "inbook" =
+  or
+  type$ "article" =
+  or
+    'author.editor.sort
+    { type$ "proceedings" =
+      type$ "periodical" =
+      or
+        'editor.organization.sort
+        { type$ "manual" =
+            'author.editor.organization.sort
+            'author.sort
+          if$
+        }
+      if$
+    }
+  if$
+  #1 entry.max$ substring$        % added for newapa
+  'sort.label :=                  % added for newapa
+  sort.label                      % added for newapa
+  *
+  "    "
+  *
+  title field.or.null
+  sort.format.title
+  *
+  #1 entry.max$ substring$
+  'sort.key$ :=
+}
+
+
+
+ITERATE { presort }
+
+SORT             % by label, year, author/editor, title
+
+% From plainnat.bst
+STRINGS { longest.label }
+
+INTEGERS { longest.label.width number.label }
+
+FUNCTION {initialize.longest.label}
+{ "" 'longest.label :=
+  #0 int.to.chr$ 'last.label :=
+  "" 'next.extra :=
+  #0 'longest.label.width :=
+  #0 'last.extra.num :=
+  #0 'number.label :=
+}
+
+
+
+FUNCTION { initialize.extra.label.stuff }
+{ #0 int.to.chr$ 'last.label :=
+  "" 'next.extra :=
+  #0 'last.extra.num :=
+}
+
+FUNCTION { forward.pass }
+{
+  % Pass through all entries, comparing current entry to last one.
+  % Need to concatenate year to the stack (done by calc.label) to determine
+  % if two entries are the same (see presort)
+
+  last.label
+  calc.basic.label year field.or.null purify$ #-1 #4 substring$ * % add year
+  #1 entry.max$ substring$ =     % are they equal?
+     { last.extra.num #1 + 'last.extra.num :=
+       last.extra.num int.to.chr$ 'extra.label :=
+     }
+     { "a" chr.to.int$ 'last.extra.num :=
+       "" 'extra.label :=
+       calc.basic.label year field.or.null purify$ #-1 #4 substring$ * % add year
+       #1 entry.max$ substring$ 'last.label := % assign to last.label
+     }
+  if$
+  number.label #1 + 'number.label :=
+}
+
+FUNCTION { reverse.pass }
+{
+  next.extra "b" =
+    { "a" 'extra.label := }
+     'skip$
+  if$
+  label.year extra.label * 'sort.year :=
+  extra.label 'next.extra :=
+}
+
+EXECUTE {initialize.extra.label.stuff}
+EXECUTE {initialize.longest.label}
+
+
+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             % by sort.label, year, title --- giving final bib. order.
+
+FUNCTION { begin.bib }
+{
+  %% Set to #0 show 13-digit ISBN in preference to 10-digit ISBN.
+  %% Set to #1 to show both 10-digit and 13-digit ISBNs.
+  #1 'show-isbn-10-and-13 :=
+
+  "%%% -*-BibTeX-*-" writeln
+  "%%% Do NOT edit. File created by BibTeX with style" writeln
+  "%%% ACM-Reference-Format-Journals [18-Jan-2012]." writeln
+  "" writeln
+
+  preamble$ empty.or.unknown
+    'skip$
+    { preamble$ writeln }
+  if$
+  "\begin{thebibliography}{" number.label int.to.str$ * "}" * writeln
+  ""                                                                         writeln
+  "%%% ====================================================================" writeln
+  "%%% NOTE TO THE USER: you can override these defaults by providing"       writeln
+  "%%% customized versions of any of these macros before the \bibliography"  writeln
+  "%%% command.  Each of them MUST provide its own final punctuation,"       writeln
+  "%%% except for \shownote{}, \showDOI{}, and \showURL{}.  The latter two"  writeln
+  "%%% do not use final punctuation, in order to avoid confusing it with"    writeln
+  "%%% the Web address."                                                     writeln
+  "%%%"                                                                      writeln
+  "%%% To suppress output of a particular field, define its macro to expand" writeln
+  "%%% to an empty string, or better, \unskip, like this:"                   writeln
+  "%%%"                                                                      writeln
+  "%%% \newcommand{\showDOI}[1]{\unskip}   % LaTeX syntax"                   writeln
+  "%%%"                                                                      writeln
+  "%%% \def \showDOI #1{\unskip}           % plain TeX syntax"               writeln
+  "%%%"                                                                      writeln
+  "%%% ====================================================================" writeln
+  ""                                                                         writeln
+
+  %% ACM publications do not use CODEN, ISSN, and LCCN data, so their default
+  %% macro wrappers expand to \unskip, discarding their values and unwanted
+  %% space.
+  %%
+  %% For other publications, prior definitions like these may be useful:
+  %%
+  %%     Plain TeX:
+  %%         \def \showCODEN     #1{CODEN #1.}
+  %%         \def \showISSN      #1{ISSN #1.}
+  %%         \def \showLCCN      #1{LCCN #1.}
+  %%
+  %%     LaTeX:
+  %%         \newcommand{\showCODEN}[1]{CODEN #1.}
+  %%         \newcommand{\showISSN}[1]#1{ISSN #1.}
+  %%         \newcommand{\showLCCN}[1]{LCCN #1.}
+
+  "\ifx \showCODEN    \undefined \def \showCODEN     #1{\unskip}     \fi" writeln
+  "\ifx \showDOI      \undefined \def \showDOI       #1{#1}\fi" writeln
+  % ACM styles omit ISBNs, but they can be included by suitable definitions of
+  % \showISBNx and \showISBNxiii before the .bbl file is read
+  "\ifx \showISBNx    \undefined \def \showISBNx     #1{\unskip}     \fi" writeln
+  "\ifx \showISBNxiii \undefined \def \showISBNxiii  #1{\unskip}     \fi" writeln
+  "\ifx \showISSN     \undefined \def \showISSN      #1{\unskip}     \fi" writeln
+  "\ifx \showLCCN     \undefined \def \showLCCN      #1{\unskip}     \fi" writeln
+  "\ifx \shownote     \undefined \def \shownote      #1{#1}          \fi" writeln % NB: final period supplied by add.period$ above
+  "\ifx \showarticletitle \undefined \def \showarticletitle #1{#1}   \fi" writeln
+  "\ifx \showURL      \undefined \def \showURL       {\relax}        \fi" writeln
+  "% The following commands are used for tagged output and should be " writeln
+  "% invisible to TeX" writeln
+  "\providecommand\bibfield[2]{#2}" writeln
+  "\providecommand\bibinfo[2]{#2}" writeln
+  "\providecommand\natexlab[1]{#1}" writeln
+  "\providecommand\showeprint[2][]{arXiv:#2}" writeln
+}
+
+EXECUTE {begin.bib}
+
+EXECUTE {init.state.consts}
+
+ITERATE {call.type$}
+
+FUNCTION { end.bib }
+{
+  newline$
+  "\end{thebibliography}"
+  writeln
+}
+
+EXECUTE {end.bib}
diff --git a/ocl/docs/publications/OCL2022CG/OCLCodeGeneration.pdf b/ocl/docs/publications/OCL2022CG/OCLCodeGeneration.pdf
index e49ccb5..26469f6 100644
--- a/ocl/docs/publications/OCL2022CG/OCLCodeGeneration.pdf
+++ b/ocl/docs/publications/OCL2022CG/OCLCodeGeneration.pdf
Binary files differ
diff --git a/ocl/docs/publications/OCL2022CG/OCLCodeGeneration.tex b/ocl/docs/publications/OCL2022CG/OCLCodeGeneration.tex
index 36790e6..4c5ca62 100644
--- a/ocl/docs/publications/OCL2022CG/OCLCodeGeneration.tex
+++ b/ocl/docs/publications/OCL2022CG/OCLCodeGeneration.tex
@@ -11,19 +11,13 @@
 %% values in them; it is your responsibility as an author to replace
 %% the commands and values with those provided to you when you
 %% complete the rights form.
-\setcopyright{acmcopyright}
 \copyrightyear{2022}
 \acmYear{2022}
-\acmDOI{XXXXXXX.XXXXXXX}
-
-%% These commands are for a PROCEEDINGS abstract or paper.
-\acmConference[OCL 2022]{Make sure to enter the correct
-  conference title from your rights confirmation emai}{October 23,
-  2022}{Montreal, Canada}
+\setcopyright{acmlicensed}\acmConference[MODELS '22 Companion]{ACM/IEEE 25th International Conference on Model Driven Engineering Languages and Systems}{October 23--28, 2022}{Montreal, QC, Canada}
+\acmBooktitle{ACM/IEEE 25th International Conference on Model Driven Engineering Languages and Systems (MODELS '22 Companion), October 23--28, 2022, Montreal, QC, Canada}
 \acmPrice{15.00}
-\acmISBN{978-1-4503-XXXX-X/18/06}
-
-%%\acmSubmissionID{123-A56-BU3}
+\acmDOI{10.1145/3550356.3561537}
+\acmISBN{978-1-4503-9467-3/22/10}
 
 %%
 %% For managing citations, it is recommended to use bibliography
@@ -113,9 +107,9 @@
 OCL is primarily a specification language supporting the elaboration
 of often-graphical metamodels with textual constraints.
 
-As shown in Figure~\ref{fig:teaser}, OCL\cite{OCL-2.4} compromises the familiar popularity of typical general purpose languages, such as Java, with formal languages, such as Z. Formal languages are so unfamiliar as to be unacceptable to many programmers. OCL's use, in conjunction with UML\cite{UML-2.5.1}, ensures that OCL has model oriented support. OCL's functional style facilitates a definition of a constraint as a compact expression.
+As shown in Figure~\ref{fig:teaser}, OCL\cite{OCL-2.4} compromises the familiar popularity of typical general purpose languages, such as Java, with formal languages, such as Z. Formal languages are so unfamiliar as to be unacceptable to many programmers. OCL's use, in conjunction with UML\cite{UML-2.5.1}, ensures that OCL has model oriented support. OCL's functional style facilitates the definition of a constraint as a compact expression.
 
-The foregoing contrast is important but just ergonomic. More important for specification purposes is correctness, for which the generality of General Purpose Languages makes correctness proofs very hard if not impossible. In contrast, Formal Languages can be provably correct but the time and skills necessary to provide that proof are not available to many programmers or applications. OCL is positioned nicely between these two extremes. The relevant, accessible syntax means that 20 years on OCL is still the language of choice for writing model constraints. The potential for proof arises from the underlying side-effect-free functional specification principles. Sadly, the potential for proof has not been exploited and so remains just a potential for most specifications.
+The foregoing contrast is important but just ergonomic. More important for specification purposes is correctness, for which the generality of General Purpose Languages makes correctness proofs very hard if not impossible. In contrast, Formal Languages can be provably correct but the time and skills necessary to provide that proof are not available to many programmers or applications. OCL is positioned nicely between these two extremes. The relevant, accessible syntax means that 20 years on OCL is still the language of choice for writing model constraints. The potential for proof arises from the underlying side-effect-free functional specification principles. Sadly, the potential for proof has not been exploited in mainstream tools and so remains just a potential for most specifications.
 
 As a specification language, OCL is just a model-oriented pseudo-code, for which tooling ensures some degree of syntactic consistency with the standard. It is only once OCL's executable capability is realized that the pseudo-code is elevated to functional accuracy.
 
@@ -178,7 +172,7 @@
 Sets.newHashSet(Double.valueOf(1), 1.0).size()
 \end{verbatim} 
 
-We revisit these and many other semantic differences so that a transliteration author can choose whether to resolve each difference by implementation heroism in the transliterator or by supporting a variant OCL subset that we refer to as Java-Friendly OCL (jfOCL).
+We revisit these and many other semantic differences so that a transliteration author can choose whether to resolve each difference by implementation heroism in the transliterator or by compromising to offer only a defective OCL subset that we refer to as Java-Friendly OCL (jfOCL).
 
 % attempts can review the almost inevitable limitations of an OCL-like transliteration when choosing to implement a jfOCL2java rather than OCL2java code generator.
 
@@ -189,7 +183,7 @@
 
 %We will now enumerate some of the significant issues that must be resolved during the CS to AS conversion.
 
-\section{Tool Structure}\label{Tool Structure}
+\section{Tool Structure and Performance}\label{Tool Structure}
 
 To understand what the transliterator does not do, it is helpful to review what standard tooling provides.
 
@@ -268,6 +262,8 @@
 
 There will be control overheads as each opcode such as LD is fetched and dispatched. Each nested term will result in a nested function call. It is easy to see that there are now many additional control overheads that are likely to reduce the efficiency well below 10\%.
 
+The 10\% estimate above and further estimates below are based on experience. The numbers are a little more helpful than purely relative terms such as `really inefficient'. The numbers cannot be precise since a much better performance can be achieved when the programmer is able to adopt a very direct flat bloated style. A more maintainable style that satisfies diverse use cases with many overrideable helper functions may give worse performance. For the particular case of \verb|LD A|, a single assembler instruction may easily bloat to many hundreds of instructions once an interpreted access uses a hierarchy of scoped \verb|Map|s with each access needing to compute a hash code in order to lookup an entry and then invoke an equality test to check on a hit. Contrasting the hundreds of instructions for a \verb|Map| access with the typically better performance of a small \verb|List| search is not the topic of this paper. An efficient code synthesis may require just a single instruction by locating \verb|A| in a local variable.
+
 A LISP-like selective rendering of the OCL ASG is even less direct
 
 \begin{verbatim}
@@ -375,7 +371,7 @@
 
 \paragraph{OCL Type Names}
 
-OCL lacks a distinctive type literal syntax analogous to Java's \texttt{MyClass.class}. Consequently the argument for \texttt{oclIsKindOf(V)} may refer to the type \texttt{V} or the property \texttt{V} or the let-variable \texttt{V} or ...
+OCL lacks a distinctive type literal syntax analogous to Java's \texttt{MyClass.class}. Consequently the argument for \texttt{oclIsKindOf(V)} may refer to at least the type \texttt{V} or the property \texttt{V} or the let-variable \texttt{V}.
 
 OCL is UML-aligned, consequently OCL supports UML templates even though the OCL specification lacks any grammar, concrete or abstract syntax support. Once templates are  supported, template parameters are yet another option for a name reference.
 
@@ -389,7 +385,7 @@
 
 \subsection{Program Structure}
 	
-Java package, class and operation constructs are very similar and more powerful than OCL's so there is little difficulty in using mapping OCL structural concepts to a subset of Java.
+Java package, class and operation constructs are very similar and more powerful than OCL's so there is little difficulty in mapping OCL structural concepts to a subset of Java.
 
 \subsection{Properties}\label{Properties}
 
@@ -409,7 +405,7 @@
 	\item UML Association
 \end{itemize} 
 
-The transliterator must invoke an appropriate helper, since direct use of Java's mechanism is not often correct. Distinct mechanisms will usually be needed depending whether the access is to DataType of Class object and whether the access is to a single object or a collection of objects.
+The transliterator must invoke an appropriate helper, since direct use of Java's mechanism is not often correct. Distinct mechanisms will usually be needed depending whether the access is to a DataType or a Class object and whether the access is to a single object or a collection of objects.
 
 \begin{figure}
 	\includegraphics[width=2.0in]{OCLOpposite.png}
@@ -418,8 +414,8 @@
 	\label{fig:navigation}
 \end{figure}
 
-OCL hides a variety of access mechanisms behind the simple dot-navigation syntax. The implicit opposite syntax is useful and powerful but hard to implement. With respect to Figure~\ref{fig:navigation}, OCL supports the \verb|anX.y| navigation even though \verb|X::y| is not navigable. Implementation of this is discussed in Section \ref{Implicit Opposites}.
-(Further lexical complexities arise when the \verb|y| role is omitted from the metamodel. A default name is available by re-using the name of the target type allowing \verb|anX.Y|. If the auto-generated name is ambiguous the more elaborate \verb|anX.Y[Y::x]| syntax may be used.) 
+OCL hides a variety of access mechanisms behind the simple dot-navigation syntax. The unnavigable opposite syntax is useful and powerful but hard to implement. With respect to Figure~\ref{fig:navigation}, OCL supports the \verb|anX.y| navigation even though \verb|X::y| is not navigable. Implementation of this is discussed in Section \ref{Implicit Opposites}.
+Further lexical complexities arise when the \verb|y| role is omitted from the metamodel. A default name is available by re-using the name of the target type allowing \verb|anX.Y|. If the auto-generated name is ambiguous the more elaborate \verb|anX.Y[Y::x]| syntax may be used.
 
 Yet more complexity arises from
 
@@ -455,17 +451,17 @@
 
 These very different practical semantics are not amenable to naive transliteration.
 
-An implementation may chose to use Java exception semantics throughout the transliteration. Every generation of an OCL \texttt{invalid} must then be replaced by a thrown \texttt{Throwable}. Conversely every OCL operation that may be passed an \texttt{invalid} value must have an operation call that carefully catches any exceptions to create the required \texttt{invalid}. This is inconvenient for ordinary code, it is distinctly awkward when the exception can occur while initializing a let variable.
+An implementation may chose to use Java exception semantics throughout the transliteration. Every generation of an OCL \texttt{invalid} must then be replaced by a thrown \texttt{Throwable}. Conversely every OCL operation that may be passed an \texttt{invalid} value must have an operation call that carefully catches any exceptions to create the required \texttt{invalid}. This is inconvenient for ordinary code, it is distinctly awkward when the exception can occur while initializing a let variable. The awkwardness arises because an exception while evaluating the `init' variable child of a \texttt{LetExp} must be caught so that it may be correctly propagated or suppressed according to the logic of the `in' child.
 
 Alternatively, an implementation may use OCL \texttt{invalid} semantics throughout the transliteration. This then requires every helper to be accurately coded to guarantee that exceptions are returned as \texttt{invalid}, a guarantee that is likely to be overlooked by maintainers. Every call to a helper may therefore need to wrapped in an exception conversion. All helpers must be coded to propagate \texttt{invalid}.
 
 The latter approach could be suitable if \texttt{invalid} was a prolific use case, but hopefully \texttt{invalid} is rare, so it is more efficient to work with, rather than against, Java's natural capabilities. It is appropriate to analyze the potentially invalid flows in order to plan the necessary catch handlers. An accurate analysis can ensure that only those very rare let-variables that can propagate an invalid value incur the overheads.
 
-Implementation of \texttt{invalid} is a significant pain, so tools may follow USE's\cite{USE} example and omit support for \texttt{invalid} altogether. However this is not OCL; it provides support only for OCL programs that never fail. There will be no divide-by-zero, no null-navigation, no index-out-of-bounds on ordered collections.
+Implementation of \texttt{invalid} is a significant pain, so tools may follow USE's\cite{USE} example and omit support for \texttt{invalid} altogether. However this is not OCL; it provides support only for OCL programs that never fail. There can be no divide-by-zero, no null-navigation, no index-out-of-bounds on ordered collections.
 
 None of the above approaches is attractive. Careful study of the OCL specification reveals that it is well-intentioned but irrational~\cite{Willink2021}. A much more practical and sensible design can be compatible with Java exception semantics. Unavoidable exceptions such as a network-failure are classified as desirable exceptions that should always be thrown. Programming errors such as collection-index-out-of-bounds are classified as undesirable exceptions that should be eliminated by analysis at compile time. The challenging need for commutative rather than short-circuit \verb|and|/\verb|or| operators that uncrash can be eliminated by commuting the inputs at compile time to guarantee that only the second input can crash.
 
-The OCL validity analysis \cite{Willink2021} is a non-trivial whole program analysis that cannot possibly be done sentence-by-sentence. However the motivation of the analysis is to prove that the OCL is free of undesirable crashes. jfOCL could define all crashes as desirable avoiding the need to catch any exceptions anywhere. It is only necessary to convert \texttt{invalid} to a thrown exception. This is easily done by providing no reification of \texttt{invalid}; exceptions can be thrown from the outset. With no catching of exceptions, a rational implementation of \verb|and|/\verb|or| that computes first argument first will exhibit the familiar short-circuit behaviour.
+The OCL validity analysis \cite{Willink2021} is a non-trivial whole program analysis that cannot possibly be done sentence-by-sentence. However, while the motivation of the analysis is to prove that the OCL is free of undesirable crashes, jfOCL can follow the principles and define all crashes as desirable avoiding the need to catch any exceptions anywhere. It is only necessary to convert \texttt{invalid} to a thrown exception. This is easily done by providing no reification of \texttt{invalid}; exceptions can be thrown from the outset. With no catching of exceptions, a rational implementation of \verb|and|/\verb|or| that computes first argument first will exhibit the familiar short-circuit behaviour.
 
 \subsection{Type / Value}
 
@@ -473,7 +469,7 @@
 
 Before we examine typical types, we should note one important difference between OCL/UML and Java. UML defines two kinds of Object, Class-typed and DataType-typed. A Class is instantiated as an instance which typically has a unique address and so two distinct class instances are not equal. A DataType defines a value that is often embedded as the attribute of an instance. A DataType does not have a unique address. DataType values are equal when a deep comparison of their information fields finds all are equal.
 
-Java has user-defined Class instances but only built-in primitive DataType values. There is a flexibility to overload \verb|equals()| so that, for instance, a pair of \verb|String| instances can compare equal even when their addresses differ. This is important to avoid the need for \verb|Map| keys to be used without the overhead of interning. This can lead to some surprises whenever \verb|int|, \verb|double|, \verb|Integer| and \verb|Double| are intermixed.
+Java has user-defined Class instances but only built-in primitive DataType values. There is a flexibility to overload \verb|equals()| so that, for instance, a pair of \verb|String| instances can compare equal even when their addresses differ. This is important to avoid the need for \verb|Map| keys to be used without the overhead of interning. However, this can lead to some surprises whenever \verb|int|, \verb|double|, \verb|Integer| and \verb|Double| are intermixed.
 The surprise is demonstrated by the difficulty in transliterating \verb|Set{1, 1.0}->size()| to ensure that the two representations of the one value populate a single-entry Set.
 
 The overt example mixing real and integer literals is perhaps unrealistic so jfOCL could prohibit it. More complex examples might not be apparent to the user, so jfOCL should diagnose them, however the effort required to diagnose them is comparable to the effort required to enforce the common type determined by the regular OCL analysis. jfOCL should really support numeric value uniformity.
@@ -490,9 +486,9 @@
 
 OCL specifies two ideal numeric types \texttt{Real} and \texttt{Integer}, whereas Java specifies many practical types such as \texttt{int}, \texttt{Long} and \texttt{BigInteger} with inconsistently imperfect functionality. A 32 bit integer is sufficient for almost all use cases, but just occasionally position or time calculations need more.
 
-Suppose your salary is represented by a 32 bit integer. Given severe inflation and a persistently generous boss, your salary may grow to the 31 bit threshold. If you are `lucky', your salary may saturate. If `unlucky', a wraparound occurs to negative numbers and you have to pay to work. 
+Suppose a salary is represented by a 32 bit integer. After many generous pay rises, a salary may grow to the 31 bit threshold. At this point, the salary wraps around to a negative number; the employee must now pay to work. 
 
-This is disappointing but OK in Java; it is what the specification says should happen. It is absolutely not OK in OCL for which unbounded integers grow and grow.
+This is OK in Java; it is what the specification says should happen. It is absolutely not OK in OCL for which unbounded integers grow and grow.
 
 An OCL2Java conversion must choose a Java representation for OCL's \texttt{Integer}
 \begin{itemize}
@@ -524,7 +520,7 @@
 
 Java's Collection types were originally designed as non-template types. These were upgraded to templated classes when Java 5 added generics, but backward compatibility necessitated a concept of type erasure. This means that the actual templating type is not known at run-time preventing expressions such as \verb|new T()|.
 
-OCL's collection types have a magic \verb|T| that behaves in many ways like a template parameter. Once the requirement for UML alignment is respected, the magic \verb|T| can be respecified as a regular template parameter and the rules for collection type conformance revisited to avoid the anomaly that \verb|Set{}->including(4)| is erroneous. The empty \verb|Set{}| is a \verb|Set(OclVoid)|. When the source argument is used to specialize the \verb|Set(T)::including(T)| operation to \verb|Set(OclVoid)::including(OclVoid)| the error arises because \verb|4| does not conform to \verb|OclVoid|. More declaratively, there is an alternative specialization \verb|Set(Integer)::including(Integer)| for which both source and argument are type conformant.
+OCL's collection types have a magic underspecified \verb|T| that behaves in many ways like a template parameter. Once the requirement for UML alignment is respected, the magic \verb|T| can be respecified as a regular template parameter and the rules for collection type conformance revisited to avoid the anomaly that \verb|Set{}->including(4)| is erroneous. The empty \verb|Set{}| is a \verb|Set(OclVoid)|. When the source argument is used to specialize the \verb|Set(T)::including(T)| operation to \verb|Set(OclVoid)::including(OclVoid)| the error arises because \verb|4| does not conform to \verb|OclVoid|. More declaratively, there is an alternative specialization \verb|Set(Integer)::including(Integer)| for which both source and argument are type conformant.
 
 Eclipse OCL applies this declarative philosophy to ensure that the Abstract Syntax is annotated with consistent specializations. The \verb|Operation::type| declaration has the unspecialized type. The invoking \verb|OperationCallExp::type| has the specialized type. 
 These types are propagated and checked throughout the AST. They provide the accuracy necessary to declare variables in Java and to inject the necessary casts from what the OCL analysis guarantees to what the Java declarations require.
@@ -567,7 +563,7 @@
 
 OCL's \texttt{null} is very similar to \texttt{null} in Java.
 
-Difficulties can arise if the implementation of a type such as an enumeration fails to provide for a null value,
+Difficulties can arise if the implementation of a type such as an enumeration fails to provide for a null value.
 
 \subsection{Operation}
 
@@ -604,7 +600,7 @@
 
 In Java a primary type such as \verb|MyClass<T>| is declared once. Its specialization such as \verb|MyClass<String>| may be `declared' many times with each re-`declaration' sharing  the same specialized type.
 
-OCL does not declare types at all; types are declared elsewhere in some metamodel. Usage of the collection types such as \verb|Bag(String)| behave in a very similar way to a Java specialization, perhaps confirming that the magic \verb|T| that parameterizes them should be modeled as a UML TemplateParameter.
+OCL does not declare types at all; types are declared elsewhere in some metamodel. Usage of the collection types such as \verb|Bag(String)| behave in a similar way to a Java specialization, perhaps confirming that the magic behind the underspecified \verb|T| that parameterizes them should be modeled as a UML TemplateParameter. %Although Java types are similar, it may often be necessary to insert casts to enforce the differing OCL  generics  and inheritance semantics.
 
 An OCL Tuple type has no unique declaration, rather each repetition of the same  set of \{name,type\} pairs is the same type. Java has no corresponding dynamically constructed type, so a code generator must pre-analyze the OCL to aggregate all Tuple declarations and create a conventional Java class for each distinct Tuple type.
 
@@ -625,9 +621,9 @@
 
 This is a difficult corner of the OCL specification that jfOCL may reasonably choose to skip.
 
-Eclipse OCL\cite{Eclipse-OCL} with an emphasis on execution has no execution capability for \texttt{oclIsNew()} or \texttt{@pre}. No user has ever complained.
+Eclipse OCL\cite{Eclipse-OCL} with an emphasis on execution has no execution capability for \texttt{oclIsNew()} or \texttt{@pre}. No user has reported this bug.
 
-USE\cite{USE} has an emphasis on simulation and a custom model framework that supports a `filmstrip'~\cite{Desai} of system states. This is able to support \texttt{oclIsNew()} and \texttt{@pre}.
+USE\cite{USE} has an emphasis on simulation and a custom model framework with  built-in \texttt{oclIsNew()} and \texttt{@pre}. This is able to support a `filmstrip'~\cite{Desai} of system states.
 
 In principle, the support for two system states, may require the operation entry code to have a complete copy of the system state. This can be difficult and expensive, but is only necessary when the post-condition's \texttt{@pre} access involves a cascade of collection operations that are too complex to analyze. In practice, the \texttt{@pre} accesses are often trivial making an on-entry copy simple.
 
@@ -645,9 +641,9 @@
 
 A naive helper implementation may perform a total model search for every \texttt{allInstances()} call. A better implementation may start with a metamodel analysis of the OCL to determine the typically small number of calls that can occur followed by a model analysis to determine all required \texttt{allInstances()} in one model traversal. This may be performed as part of the initial model loading or lazily when the first call occurs.
 
-\subsubsection{Implicit Opposites}\label{Implicit Opposites}
+\subsubsection{Unnavigable Opposites}\label{Implicit Opposites}
 
-OCL's opposite navigation again has no counterpart in Java and like \texttt{allInstances()} can be remedied by a helper function that traverses the whole model searching for the solutions. Again, like \texttt{allInstances()}, a naive implementation may be very costly, but a better implementation may use a metamodel analysis to discover all the \verb|X::y| unnavigable opposites actually in use so that a single traversal of the model can populate a cache of \verb|{X -> X::y}| for constant-time cost during execution. These analyses can be performed at the same time as the \texttt{allInstances()} search.
+OCL's navigation to unnavigable and sometimes implicitly named opposites again has no counterpart in Java and like \texttt{allInstances()} can be remedied by a helper function that traverses the whole model searching for the solutions. Again, like \texttt{allInstances()}, a naive implementation may be very costly, but a better implementation may use a metamodel analysis to discover all the \verb|X::y| unnavigable opposites actually in use so that a single traversal of the model can populate a cache of \verb|{X -> X::y}| for constant-time cost during execution. These analyses can be performed at the same time as the \texttt{allInstances()} search.
 
 \subsubsection{Stereotype}
 
@@ -697,7 +693,7 @@
 
 \subsection{Code Generator Model and Optimization}
 
-The Abstract Syntax Graph is a good model of the OCL semantics, but somewhat distant from the Java semantics. A Code Generator may therefore choose to transform the OCL ASG into a more Object-Oriented Code Generator Model from which generation of Java or C or ... is much easier. In the ASG, every expression term can return a value. In the CGM, every not-inlined expression term may return a Static Single Assignment variable facilitating a synthesis that can always refer to a variable. The expression terms include many extra terms to cast to known types, guard against nulls and convert between representations. The substantial support code to provide conformance tables, or implicit opposite caches can be reified in the CGM reducing the complexity of the eventual CGM to text model-to-text transformation. (For Eclipse OCL a further CGM to JavaModel to JavaText intermediate is planned.) 
+The Abstract Syntax Graph is a good model of the OCL semantics, but somewhat distant from the Java semantics. A Code Generator may therefore choose to transform the OCL ASG into a more Object-Oriented CGM (Code Generator Model) from which generation of Java or C or some other language is much easier. In the ASG, every expression term can return a value. In the CGM, every not-inlined expression term may return a Static Single Assignment variable facilitating a synthesis that can always refer to a variable. The expression terms include many extra terms to cast to known types, guard against nulls and convert between representations. The substantial support code to provide conformance tables, or implicit opposite caches can be reified in the CGM reducing the complexity of the eventual CGM to text model-to-text transformation. For Eclipse OCL a further CGM to JavaModel to JavaText intermediate is planned. 
 
 Once a sensible CGM is in use, support for optimizations such as Common Subexpression Elimination, Constant Folding and Loop Hoisting follows naturally. The Validity Analysis ~\cite{Willink2021} is a significant extension to Constant Folding that once integrated should identify many more candidates for Dead Code Elimination.
 
@@ -713,8 +709,6 @@
 	\item subtly distinct semantics from Java
 \end{itemize}
 
-Unfortunately a jfOCL only addresses some of the distinct semantics.
-
 \begin{table}
 \begin{tabular}{ c | c | c }
 Concept & Eclipse OCL & jfOCL \\
@@ -733,7 +727,7 @@
 and/or & commutative & short-circuit \\
 \hline
 allInstances() & supported & prohibited \\
-implicit opposites & supported & prohibited \\
+unnavigable opposites & supported & prohibited \\
 qualified navigation & supported & prohibited \\
 qualified associations & supported & prohibited \\
 qualified navigation & supported & prohibited \\
@@ -753,7 +747,7 @@
 
 \section{Related Work}\label{Related Work}
 
-This paper revisits Willink~\cite{Willink2012} in which "An extensible OCL Virtual Machine and Code Generator" was presented. It probably remains as the only extensible code generator for `full' OCL (and QVTc and QVTr). Ten years on, the emphasis on a VM is clearly misleading hype. A VM suggests a JVM-like byte code interpreter, which is possible, but something of a premature optimization. The XMI serialization of the OCL ASG is more appropriate. Compacting it to byte code while saving on file size would needlessly lose readability when debugging. In this paper we draw on 10 years evolution to explain why a `full' code generator is hard so that other authors tempted to develop one can fully appreciate the challenges they face.
+This paper revisits Willink~\cite{Willink2012} in which "An extensible OCL Virtual Machine and Code Generator" was presented. It probably remains as the only extensible code generator for `full' OCL (and QVTc and QVTr). Ten years on, the emphasis on a VM is clearly misleading hype. A VM suggests a JVM-like byte code interpreter, which is possible, but something of a premature optimization. The XMI serialization of the OCL ASG is more appropriate. Compacting it to byte code while saving on file size would needlessly lose readability when debugging. In this paper we draw on 10 years evolution to explain why a `full' code generator is hard so that other authors can fully appreciate the challenges they face.
 
 Many authors have provided a partial OCL code generator demonstrating good characteristics aligned with some research goal. Omission of OCL facilities such as oclIsNew(), @pre,  allInstances(), States, Messages and even Tuples and opposites is common, but in many cases this just represents a pragmatic reduction of scope to facilitate research; these omissions can be rectified by a little more work. Failure to address unbounded numerics, numeric equality, null/invalid propagation, nested Collections and oclType() is a more fundamental challenge to some of the approaches. 
 
diff --git a/ocl/docs/publications/OCL2022Library/.gitignore b/ocl/docs/publications/OCL2022Library/.gitignore
index b87275c..3bf35f8 100644
--- a/ocl/docs/publications/OCL2022Library/.gitignore
+++ b/ocl/docs/publications/OCL2022Library/.gitignore
@@ -7,3 +7,4 @@
 /OCLLibrarySupport.log
 /OCLLibrarySupport.out
 /OCLLibrarySupport.synctex.gz
+/OCL2022Library.zip
diff --git a/ocl/docs/publications/OCL2022Library/ACM-Reference-Format.bst b/ocl/docs/publications/OCL2022Library/ACM-Reference-Format.bst
new file mode 100644
index 0000000..7984639
--- /dev/null
+++ b/ocl/docs/publications/OCL2022Library/ACM-Reference-Format.bst
@@ -0,0 +1,3081 @@
+%%% -*-BibTeX-*-
+%%% ====================================================================
+%%%  @BibTeX-style-file{
+%%%     author          = "Nelson H. F. Beebe, Boris Veytsman and Gerald Murray",
+%%%     version         = "2.1",
+%%%     acmart-version  = "1.79",
+%%%     date            = "14 June 2017",
+%%%     filename        = "ACM-Reference-Format.bst",
+%%%     email           = "borisv@lk.net, boris@varphi.com",
+%%%     codetable       = "ISO/ASCII",
+%%%     keywords        = "ACM Transactions bibliography style; BibTeX",
+%%%     license         = "public domain",
+%%%     supported       = "yes",
+%%%     abstract        = "",
+%%%  }
+%%% ====================================================================
+
+%%% Revision history:  see source in git
+
+ENTRY
+  { address
+    advisor
+    archiveprefix
+    author
+    booktitle
+    chapter
+    city
+    date
+    edition
+    editor
+    eprint
+    eprinttype
+    eprintclass
+    howpublished
+    institution
+    journal
+    key
+    location
+    month
+    note
+    number
+    organization
+    pages
+    primaryclass
+    publisher
+    school
+    series
+    title
+    type
+    volume
+    year
+        % New keys recognized
+        issue         % UTAH: used in, e.g., ACM SIGSAM Bulletin and ACM Communications in Computer Algebra
+        articleno
+        eid
+        day           % UTAH: needed for newspapers, weeklies, bi-weeklies
+        doi           % UTAH
+        url           % UTAH
+        bookpages     % UTAH
+        numpages
+        lastaccessed  % UTAH: used only for @Misc{...}
+        coden         % UTAH
+        isbn          % UTAH
+        isbn-13       % UTAH
+        issn          % UTAH
+        lccn          % UTAH
+	distinctURL   % whether to print url if doi is present
+  }
+  {}
+  { label.year extra.label sort.year sort.label basic.label.year}
+
+INTEGERS { output.state before.all mid.sentence after.sentence after.block }
+
+INTEGERS { show-isbn-10-and-13 }  % initialized below in begin.bib
+
+INTEGERS { nameptr namesleft numnames }
+
+INTEGERS { multiresult }
+
+INTEGERS { len }
+
+INTEGERS { last.extra.num }
+
+STRINGS { s t t.org u }
+
+STRINGS { last.label next.extra }
+
+STRINGS { p1 p2 p3 page.count }
+
+
+FUNCTION { not }
+{
+    { #0 }
+    { #1 }
+  if$
+}
+
+FUNCTION { and }
+{
+    'skip$
+    { pop$ #0 }
+  if$
+}
+
+FUNCTION { or }
+{
+   { pop$ #1 }
+    'skip$
+  if$
+}
+
+
+FUNCTION { dump.stack.1 }
+{
+    duplicate$ "STACK[top] = [" swap$ * "]" * warning$
+}
+
+FUNCTION { dump.stack.2 }
+{
+    duplicate$ "STACK[top  ] = [" swap$ * "]" * warning$
+    swap$
+    duplicate$ "STACK[top-1] = [" swap$ * "]" * warning$
+    swap$
+}
+
+FUNCTION { empty.or.unknown }
+{
+  %% Examine the top stack entry, and push 1 if it is empty, or
+  %% consists only of whitespace, or is a string beginning with two
+  %% queries (??), and otherwise, push 0.
+  %%
+  %% This function provides a replacement for empty$, with the
+  %% convenient feature that unknown values marked by two leading
+  %% queries are treated the same as missing values, and thus, do not
+  %% appear in the output .bbl file, and yet, their presence in .bib
+  %% file(s) serves to mark values which are temporarily missing, but
+  %% are expected to be filled in eventually once more data is
+  %% obtained.  The TeX User Group and BibNet bibliography archives
+  %% make extensive use of this practice.
+  %%
+  %% An empty string cannot serve the same purpose, because just as in
+  %% statistics data processing, an unknown value is not the same as an
+  %% empty value.
+  %%
+  %% At entry: stack = ... top:[string]
+  %% At exit:  stack = ... top:[0 or 1]
+
+  duplicate$ empty$
+    { pop$ #1 }
+    { #1 #2 substring$ "??" = }
+  if$
+}
+
+FUNCTION { empty.or.zero }
+{ 
+  %% Examine the top entry and push 1 if it is empty, or is zero
+  duplicate$ empty$
+    { pop$ #1 }
+    { "0" = }
+  if$
+}
+
+
+FUNCTION { writeln }
+{
+  %% In BibTeX style files, the sequences
+  %%
+  %%     ... "one" "two" output
+  %%     ... "one" "two" output.xxx
+  %%
+  %% ship "one" to the output file, possibly following by punctuation,
+  %% leaving the stack with
+  %%
+  %%     ... "two"
+  %%
+  %% There is thus a one-string lag in output processing that must be
+  %% carefully handled to avoid duplicating a string in the output
+  %% file.  Unless otherwise noted, all output.xxx functions leave
+  %% just one new string on the stack, and that model should be born
+  %% in mind when reading or writing function code.
+  %%
+  %% BibTeX's asynchronous buffering of output from strings from the
+  %% stack is confusing because newline$ bypasses the buffer.  It
+  %% would have been so much easier for newline to be a character
+  %% rather than a state of the output-in-progress.
+  %%
+  %% The documentation in btxhak.dvi is WRONG:  it says
+  %%
+  %%    newline$ Writes onto the bbl file what's accumulated in the
+  %%             output buffer. It writes a blank line if and only
+  %%             if the output buffer is empty. Since write$ does
+  %%             reasonable line breaking, you should use this
+  %%             function only when you want a blank line or an
+  %%             explicit line break.
+  %%
+  %%    write$   Pops the top (string) literal and writes it on the
+  %%             output buffer (which will result in stuff being
+  %%             written onto the bbl file when the buffer fills
+  %%             up).
+  %%
+  %% Examination of the BibTeX source code shows that write$ does
+  %% indeed behave as claimed, but newline$ sends a newline character
+  %% directly to the output file, leaving the stack unchanged.  The
+  %% first line "Writes onto ... buffer." is therefore wrong.
+  %%
+  %% The original BibTeX style files almost always use "write$ newline$"
+  %% in that order, so it makes sense to hide that pair in a private
+  %% function like this one, named after a statement in Pascal,
+  %% the programming language embedded in the BibTeX Web program.
+
+  write$                % output top-of-stack string
+  newline$              % immediate write of newline (not via stack)
+}
+
+FUNCTION { init.state.consts }
+{
+  #0 'before.all :=
+  #1 'mid.sentence :=
+  #2 'after.sentence :=
+  #3 'after.block :=
+}
+
+FUNCTION { output.nonnull }
+{ % Stack in: ... R S T  Stack out: ... R T   File out: S<comma><space>
+  's :=
+  output.state mid.sentence =
+    {
+      ", " * write$
+    }
+    {
+      output.state after.block =
+        {
+          add.period$ writeln
+          "\newblock " write$
+        }
+        {
+          output.state before.all =
+            {
+              write$
+            }
+            {
+              add.period$ " " * write$
+            }
+          if$
+        }
+      if$
+      mid.sentence 'output.state :=
+    }
+  if$
+  s
+}
+
+FUNCTION { output.nonnull.dot.space }
+{ % Stack in: ... R S T  Stack out: ... R T   File out: S<dot><space>
+  's :=
+  output.state mid.sentence =           % { "<DEBUG output.nonnull.dot.space>. " * write$ }
+    {
+      ". " * write$
+    }
+    {
+      output.state after.block =
+        {
+          add.period$ writeln "\newblock " write$
+        }
+        {
+          output.state before.all =
+            {
+              write$
+            }
+            {
+              add.period$ " " * write$
+            }
+          if$
+        }
+      if$
+      mid.sentence 'output.state :=
+    }
+  if$
+  s
+}
+
+FUNCTION { output.nonnull.remove }
+{ % Stack in: ... R S T  Stack out: ... R T   File out: S<space>
+  's :=
+  output.state mid.sentence =
+    {
+      " " * write$
+    }
+    {
+      output.state after.block =
+        {
+          add.period$ writeln "\newblock " write$
+        }
+        {
+          output.state before.all =
+            {
+              write$
+            }
+            {
+              add.period$ " " * write$
+            }
+          if$
+        }
+      if$
+      mid.sentence 'output.state :=
+    }
+  if$
+  s
+}
+
+FUNCTION { output.nonnull.removenospace }
+{ % Stack in: ... R S T  Stack out: ... R T   File out: S
+  's :=
+  output.state mid.sentence =
+    {
+      "" * write$
+    }
+    {
+      output.state after.block =
+        {
+          add.period$ writeln "\newblock " write$
+        }
+        {
+          output.state before.all =
+            {
+              write$
+            }
+            {
+              add.period$ " " * write$
+            }
+          if$
+        }
+      if$
+      mid.sentence 'output.state :=
+    }
+  if$
+  s
+}
+
+FUNCTION { output }
+{ % discard top token if empty, else like output.nonnull
+  duplicate$ empty.or.unknown
+    'pop$
+    'output.nonnull
+  if$
+}
+
+FUNCTION { output.dot.space }
+{ % discard top token if empty, else like output.nonnull.dot.space
+  duplicate$ empty.or.unknown
+    'pop$
+    'output.nonnull.dot.space
+  if$
+}
+
+FUNCTION { output.removenospace }
+{ % discard top token if empty, else like output.nonnull.removenospace
+  duplicate$ empty.or.unknown
+    'pop$
+    'output.nonnull.removenospace
+  if$
+}
+
+FUNCTION { output.check }
+{ % like output, but warn if key name on top-of-stack is not set
+  't :=
+  duplicate$ empty.or.unknown
+    { pop$ "empty " t * " in " * cite$ * warning$ }
+    'output.nonnull
+  if$
+}
+
+FUNCTION { bibinfo.output.check }
+{ % like output.check, adding bibinfo field
+  't :=
+  duplicate$ empty.or.unknown
+    { pop$ "empty " t * " in " * cite$ * warning$ }
+    { "\bibinfo{" t "}{" * * swap$ * "}" *
+      output.nonnull }
+  if$
+}
+
+FUNCTION { output.check.dot.space }
+{ % like output.dot.space, but warn if key name on top-of-stack is not set
+  't :=
+  duplicate$ empty.or.unknown
+    { pop$ "empty " t * " in " * cite$ * warning$ }
+    'output.nonnull.dot.space
+  if$
+}
+
+FUNCTION { fin.block }
+{ % functionally, but not logically, identical to fin.entry
+   add.period$
+   writeln
+}
+
+FUNCTION { fin.entry }
+{
+   add.period$
+   writeln
+}
+
+FUNCTION { new.sentence }
+{ % update sentence state, with neither output nor stack change
+  output.state after.block =
+    'skip$
+    {
+      output.state before.all =
+        'skip$
+        { after.sentence 'output.state := }
+      if$
+    }
+  if$
+}
+
+FUNCTION { fin.sentence }
+{
+   add.period$
+   write$
+   new.sentence
+   ""
+}
+
+FUNCTION { new.block }
+{
+  output.state before.all =
+    'skip$
+    { after.block 'output.state := }
+  if$
+}
+
+FUNCTION { output.coden }       % UTAH
+{ % output non-empty CODEN as one-line sentence (stack untouched)
+  coden empty.or.unknown
+    { }
+    { "\showCODEN{" coden * "}" * writeln }
+  if$
+}
+
+%
+% Sometimes articleno starts with the word 'Article' or 'Paper.
+% (this is a bug of acmdl, sigh)
+% We strip them.  We assume eid or articleno is already on stack
+%
+
+FUNCTION { strip.articleno.or.eid }
+{
+  't :=
+  t #1 #7 substring$ "Article" = 
+    {t #8 t text.length$ substring$ 't :=}
+    { }
+  if$
+  t #1 #7 substring$ "article" = 
+    {t #8 t text.length$ substring$ 't :=}
+    { }
+  if$
+  t #1 #5 substring$ "Paper" = 
+    {t #6 t text.length$ substring$ 't :=}
+    { }
+  if$
+  t #1 #5 substring$ "paper" = 
+    {t #6 t text.length$ substring$ 't :=}
+    { }
+  if$
+  % Strip any left trailing space or ~
+  t #1 #1 substring$ " " =
+    {t #2 t text.length$ substring$ 't :=}
+    { }
+  if$ 
+  t #1 #1 substring$ "~" =
+    {t #2 t text.length$ substring$ 't :=}
+    { }
+  if$
+  t 
+}
+
+
+FUNCTION { format.articleno }
+{
+  articleno empty.or.unknown not eid empty.or.unknown not and
+     { "Both articleno and eid are defined for " cite$ * warning$ }
+     'skip$
+  if$
+  articleno empty.or.unknown eid empty.or.unknown and
+     { "" }
+     {
+        numpages empty.or.unknown
+          { "articleno or eid field, but no numpages field, in "
+            cite$ * warning$ }
+          { }
+        if$
+        eid empty.or.unknown
+          { "Article \bibinfo{articleno}{" articleno strip.articleno.or.eid * "}" * }
+          { "Article \bibinfo{articleno}{" eid strip.articleno.or.eid * "}" * }
+        if$
+     }
+  if$
+}
+
+FUNCTION { format.year }
+{ % push year string or "[n.\,d.]" onto output stack
+  %% Because year is a mandatory field, we always force SOMETHING
+  %% to be output
+  "\bibinfo{year}{"
+  year empty.or.unknown
+    { "[n.\,d.]" }
+    { year }
+  if$
+  *  "}" *
+}
+
+FUNCTION { format.day.month }
+{ % push "day month " or "month " or "" onto output stack
+  day empty.or.unknown
+    {
+      month empty.or.unknown
+        { "" }
+        { "\bibinfo{date}{" month * "} " *}
+      if$
+    }
+    {
+      month empty.or.unknown
+        { "" }
+        { "\bibinfo{date}{" day * " " * month * "} " *}
+      if$
+    }
+  if$
+}
+
+FUNCTION { format.day.month.year }     % UTAH
+{ % if month is empty, push "" else push "(MON.)" or "(DD MON.)"
+  % Needed for frequent periodicals: 2008. ... New York Times C-1, C-2, C-17 (23 Oct.)
+  % acm-*.bst addition: prefix parenthesized date string with
+  % ", Article nnn "
+  articleno empty.or.unknown eid empty.or.unknown and
+    { "" }
+    { output.state after.block =
+       {", " format.articleno * }
+       { format.articleno  }
+      if$
+    }
+  if$
+  " (" * format.day.month * format.year * ")" *
+}
+
+FUNCTION { output.day.month.year }     % UTAH
+{ % if month is empty value, do nothing; else output stack top and
+  % leave with new top string "(MON.)" or "(DD MON.)"
+  % Needed for frequent periodicals: 2008. ... New York Times C-1, C-2, C-17 (23 Oct.)
+  format.day.month.year
+  output.nonnull.remove
+}
+
+FUNCTION { strip.doi } % UTAH
+{ % Strip any Web address prefix to recover the bare DOI, leaving the
+  % result on the output stack, as recommended by CrossRef DOI
+  % documentation.
+  % For example, reduce "http://doi.acm.org/10.1145/1534530.1534545" to
+  % "10.1145/1534530.1534545".  A suitable URL is later typeset and
+  % displayed as the LAST item in the reference list entry.  Publisher Web
+  % sites wrap this with a suitable link to a real URL to resolve the DOI,
+  % and the master https://doi.org/ address is preferred, since publisher-
+  % specific URLs can disappear in response to economic events.  All
+  % journals are encouraged by the DOI authorities to use that typeset
+  % format and link procedures for uniformity across all publications that
+  % include DOIs in reference lists.
+  % The numeric prefix is guaranteed to start with "10.", so we use
+  % that as a test.
+  % 2017-02-04 Added stripping of https:// (Boris)
+  doi #1 #3 substring$ "10." =
+    { doi }
+    {
+      doi 't :=  % get modifiable copy of DOI
+
+      % Change https:// to http:// to strip both prefixes (BV)
+
+      t #1 #8 substring$ "https://" =
+        { "http://"  t #9 t text.length$ #8 - substring$ * 't := }
+        { }
+      if$
+
+      t #1 #7 substring$ "http://" =
+        {
+            t #8 t text.length$ #7 - substring$ 't :=
+
+            "INTERNAL STYLE-FILE ERROR" 's :=
+
+            % search for next "/" and assign its suffix to s
+
+            { t text.length$ }
+            {
+              t #1 #1 substring$ "/" =
+                {
+                  % save rest of string as true DOI (should be 10.xxxx/yyyy)
+                  t #2 t text.length$ #1 - substring$ 's :=
+                  "" 't :=    % empty string t terminates the loop
+                }
+                {
+                  % discard first character and continue loop: t <= substring(t,2,last)
+                  t #2 t text.length$ #1 - substring$ 't :=
+                }
+              if$
+            }
+            while$
+
+            % check for valid DOI (should be 10.xxxx/yyyy)
+            s #1 #3 substring$ "10." =
+              { }
+              { "unrecognized DOI substring " s * " in DOI value [" * doi * "]" * warning$ }
+            if$
+
+            s   % push the stripped DOI on the output stack
+
+        }
+        {
+          "unrecognized DOI value [" doi * "]" * warning$
+          doi   % push the unrecognized original DOI on the output stack
+        }
+      if$
+    }
+  if$
+}
+
+%
+% Change by BV: added standard prefix to URL
+%
+FUNCTION { output.doi } % UTAH
+{ % output non-empty DOI as one-line sentence (stack untouched)
+  doi empty.or.unknown
+    { }
+    {
+      %% Use \urldef here for the same reason it is used in output.url,
+      %% see output.url for further discussion.
+      "\urldef\tempurl%" writeln
+      "\url{https://doi.org/" strip.doi * "}" * writeln
+      "\showDOI{\tempurl}" writeln
+    }
+  if$
+}
+
+FUNCTION { output.isbn }                % UTAH
+{ % output non-empty ISBN-10 and/or ISBN-13 as one-line sentences (stack untouched)
+  show-isbn-10-and-13
+    {
+      %% show both 10- and 13-digit ISBNs
+      isbn empty.or.unknown
+        { }
+        {
+          "\showISBNx{" isbn * "}" * writeln
+        }
+      if$
+      isbn-13 empty.or.unknown
+        { }
+        {
+          "\showISBNxiii{" isbn-13 * "}" * writeln
+        }
+      if$
+    }
+    {
+      %% show 10-digit ISBNs only if 13-digit ISBNs not available
+      isbn-13 empty.or.unknown
+        {
+          isbn empty.or.unknown
+            { }
+            {
+              "\showISBNx{" isbn * "}" * writeln
+            }
+          if$
+        }
+        {
+          "\showISBNxiii{" isbn-13 * "}" * writeln
+        }
+      if$
+    }
+  if$
+}
+
+FUNCTION { output.issn } % UTAH
+{ % output non-empty ISSN as one-line sentence (stack untouched)
+  issn empty.or.unknown
+    { }
+    { "\showISSN{" issn * "}" * writeln }
+  if$
+}
+
+FUNCTION { output.issue }
+{ % output non-empty issue number as a one-line sentence (stack untouched)
+  issue empty.or.unknown
+    { }
+    { "Issue " issue * "." * writeln }
+  if$
+}
+
+FUNCTION { output.lccn } % UTAH
+{ % return with stack untouched
+  lccn empty.or.unknown
+    { }
+    { "\showLCCN{" lccn * "}" * writeln }
+  if$
+}
+
+FUNCTION { output.note } % UTAH
+{ % return with stack empty
+  note empty.or.unknown
+    { }
+    { "\shownote{" note * "}" add.period$ * writeln }
+  if$
+}
+
+FUNCTION { output.note.check } % UTAH
+{ % return with stack empty
+  note empty.or.unknown
+    { "empty note in " cite$ * warning$ }
+    { "\shownote{" note * "}" add.period$ * writeln }
+  if$
+}
+
+FUNCTION { output.eprint } %
+{ % return with stack empty
+  eprint empty.or.unknown
+    { }
+    { "\showeprint"
+         archiveprefix empty.or.unknown
+           { eprinttype empty.or.unknown
+               { }
+               { "[" eprinttype "]" * * * }
+             if$
+           }
+           { "[" archiveprefix "l" change.case$ "]" * * * }
+         if$
+	 "{" eprint "}" * * *
+         primaryclass empty.or.unknown
+           { eprintclass empty.or.unknown
+             { }
+             { "~[" eprintclass "]" * * * }
+             if$
+           }
+           { "~[" primaryclass "]" * * * }
+         if$
+         writeln
+    }
+  if$
+}
+
+
+%
+% Changes by BV 2011/04/15.  Do not output
+% url if doi is defined
+%
+%
+% Changes by BV 2021/11/26.  Output url even if doi is defined
+% if distinctURL is not zero.
+%
+FUNCTION { output.url } % UTAH
+{ % return with stack untouched
+  % output URL and associated lastaccessed fields
+  doi empty.or.unknown distinctURL empty.or.zero not or
+  {
+    url empty.or.unknown
+      { }
+      {
+          %% Use \urldef, outside \showURL, so that %nn, #, etc in URLs work
+          %% correctly.  Put the actual URL on its own line to reduce the
+          %% likelihood of BibTeX's nasty line wrapping after column 79.
+          %% \url{} can undo this, but if that doesn't work for some reason
+          %% the .bbl file would have to be repaired manually.
+          "\urldef\tempurl%" writeln
+          "\url{" url * "}" * writeln
+
+          "\showURL{%" writeln
+          lastaccessed empty.or.unknown
+            { "" }
+            { "Retrieved " lastaccessed * " from " * }
+          if$
+          "\tempurl}" * writeln
+      }
+      if$
+  }
+  { }
+  if$
+}
+
+FUNCTION { output.year.check }
+{ % warn if year empty, output top string and leave " YEAR<label>" on stack in mid-sentence
+  year empty.or.unknown
+     { "empty year in " cite$ * warning$
+       write$
+       " \bibinfo{year}{[n.\,d.]}"
+       "\natexlab{" extra.label * "}" * *
+       mid.sentence 'output.state :=
+     }
+     { write$
+       " \bibinfo{year}{" year * "}"  *
+       "\natexlab{" extra.label * "}" * *
+       mid.sentence 'output.state :=
+     }
+  if$
+}
+
+
+FUNCTION { le }
+{
+  %% test whether first number is less than or equal to second number
+  %% stack in:  n1 n2
+  %% stack out: if n1 <= n2 then 1 else 0
+
+  %% "DEBUG: le " cite$ * warning$
+  > { #0 } { #1 } if$
+}
+
+FUNCTION { ge }
+{
+  %% test whether first number is greater than or equal to second number
+  %% stack in:  n1 n2
+  %% stack out: if n1 >= n2 then 1 else 0
+
+  %% "DEBUG: ge " cite$ * warning$
+  < { #0 } { #1 } if$
+}
+
+FUNCTION { is.leading.digit }
+{
+  %% test whether first character of string is a digit
+  %% stack in:  string
+  %% stack out: if first-char-is-digit then 1 else 0
+
+  #1 #1 substring$                      % replace string by string[1:1]
+  duplicate$                            % string[1:1] string[1:1]
+  chr.to.int$
+  "0" chr.to.int$ swap$ le              % "0" <= string[1:1] --> 0-or-1
+  swap$                                 % 0-or-1 string[1:1]
+  chr.to.int$
+  "9" chr.to.int$ le                    % string[1:1} <= "9" --> 0-or-1
+  and
+}
+
+FUNCTION { skip.digits }
+{
+  %% skip over leading digits in string
+  %% stack in:  string
+  %% stack out: rest-of-string leading-digits
+
+  %% "DEBUG: enter skip.digits " cite$ * warning$
+
+  %% dump.stack.1
+
+  duplicate$
+  't :=
+  't.org :=
+  "" 'u :=
+
+  { t text.length$ }
+  {
+    %% "=================DEBUG: skip.digits   t = [" t * "]" * warning$
+    t is.leading.digit
+      { t #2 t text.length$ #1 - substring$ }
+      {
+        t 'u :=
+        ""
+      }
+    if$
+    't :=
+  }
+  while$
+
+  u                                                             % rest of string
+  t.org #1 t.org text.length$ u text.length$ - substring$       % leading digits
+
+  %% "DEBUG: t.org = [" t.org * "]" * warning$
+  %% "DEBUG: u     = [" u * "]" * warning$
+
+  %% dump.stack.2
+
+  %% "DEBUG: leave skip.digits " cite$ * warning$
+}
+
+FUNCTION { skip.nondigits }
+{
+  %% skip over leading nondigits in string
+  %% stack in:  string
+  %% stack out: rest-of-string
+
+  %% "DEBUG: enter skip.nondigits " cite$ * warning$
+
+  't :=
+  "" 'u :=
+
+  { t text.length$ }
+  {
+    %% "=================DEBUG: skip.nondigits   t = [" t * "]" * warning$
+    t is.leading.digit
+      {
+        t 'u :=
+        ""
+      }
+      { t #2 t text.length$ #1 - substring$ }
+    if$
+    't :=
+  }
+  while$
+
+  u                     % rest of string
+
+  %% dump.stack.1
+  %% "DEBUG: leave skip.nondigits " cite$ * warning$
+}
+
+FUNCTION { parse.next.number }
+{
+  %% stack in:  string
+  %% stack out: rest-of-string next-numeric-part-of-string
+  %% Example:
+  %% stack in:  "123:1--123:59"
+  %% stack out: ":1--123:59" "123"
+
+  's :=
+  s skip.nondigits 's :=
+  s skip.digits
+}
+
+FUNCTION { reduce.pages.to.page.count }
+{
+  %% Stack in:  arbitrary-and-unused
+  %% Stack out: unchanged
+  %%
+  %% For the new-style pagination with article number and numpages or
+  %% pages, we expect to have BibTeX entries containing something like
+  %%     articleno = "17",
+  %%     pages     = "1--23",
+  %% with output "Article 17, 23 pages",
+  %% or
+  %%     articleno = "17",
+  %%     numpages  = "23",
+  %% with output "Article 17, 23 pages",
+  %% or
+  %%     articleno = "17",
+  %%     pages     = "17:1--17:23",
+  %% with output "Article 17, 23 pages",
+  %%
+  %% If articleno is missing or empty, then we should output "1--23",
+  %% "23" (with a warning of a missing articleno), or "17:1--17:23",
+  %% respectively.
+
+  %% "DEBUG: enter reduce.pages.to.page.count " cite$ * warning$
+
+  %% "DEBUG: pages = [" pages * "]" * warning$
+
+  pages
+  parse.next.number 'p1 :=
+  parse.next.number 'p2 :=
+  parse.next.number 'p3 :=
+  parse.next.number 'page.count :=
+
+  duplicate$
+  empty.or.unknown
+    {  }
+    {
+      duplicate$ "unexpected trailing garbage [" swap$ *
+      "] after n:p1--n:p2 in pages = [" *
+      pages *
+      "] in " *
+      cite$ *
+      warning$
+    }
+  if$
+
+  pop$
+
+  %% "DEBUG: reduce.pages.to.page.count: "
+  %% " p1 = " p1 * *
+  %% " p2 = " p2 * *
+  %% " p3 = " p3 * *
+  %% " p4 = " page.count * *
+  %% " in " cite$ * * warning$
+
+  p1 p3 =   p2 "1" =   and   numpages empty.or.unknown   and
+    { "INFO: reduced pages = [" pages * "] to numpages = [" * page.count * "]" * warning$ }
+    {
+      numpages empty.or.unknown
+        { pages }
+        { numpages }
+      if$
+      'page.count :=
+    }
+  if$
+
+  p1 "1" =   p3 empty.or.unknown   and   numpages empty.or.unknown   and
+    {
+      p2 'page.count :=
+      "INFO: reduced pages = [" pages * "] to numpages = [" * page.count * "]" * warning$
+    }
+    {
+      numpages empty.or.unknown
+        { pages }
+        { numpages }
+      if$
+      'page.count :=
+    }
+  if$
+
+  %% "DEBUG: leave reduce.pages.to.page.count " cite$ * warning$
+}
+
+FUNCTION { new.block.checkb }
+{ % issue a new.block only if at least one of top two stack strings is not empty
+  empty.or.unknown
+  swap$ empty.or.unknown
+  and
+    'skip$
+    'new.block
+  if$
+}
+
+FUNCTION { field.or.null }
+{ % convert empty value to null string, else return value
+  duplicate$ empty.or.unknown
+    { pop$ "" }
+    'skip$
+  if$
+}
+
+
+
+FUNCTION { emphasize }
+{ % emphasize a non-empty top string on the stack
+  duplicate$ empty.or.unknown
+    { pop$ "" }
+    { "\emph{" swap$ * "}" * }
+  if$
+}
+
+FUNCTION { comma }
+{ % convert empty string to null string, or brace string and add trailing comma
+  duplicate$ empty.or.unknown
+    { pop$ "" }
+    { "{" swap$ * "}," * }
+  if$
+}
+
+FUNCTION { format.names }
+{
+  % Format bibliographical entries with the first author last name first,
+  % and subsequent authors with initials followed by last name.
+  % All names are formatted in this routine.
+
+  's :=
+  #1 'nameptr :=               % nameptr = 1;
+  s num.names$ 'numnames :=    % numnames = num.name$(s);
+  numnames 'namesleft :=
+    { namesleft #0 > }
+    { nameptr #1 =
+        %NO: BAD ORDER: {"{" s nameptr "{ff~}{ll}{, jj}{, vv}" format.name$ * "}" * 't := }
+        %NO: BAD ORDER: {"{" s nameptr "{ff~}{ll}{, jj}{, vv}" format.name$ * "}" * 't := }
+        {"\bibinfo{person}{" s nameptr "{ff }{vv }{ll}{, jj}" format.name$ * "}" * 't := }
+        {"\bibinfo{person}{" s nameptr "{ff }{vv }{ll}{, jj}" format.name$ * "}" * 't := }
+      if$
+      nameptr #1 >
+        {
+          namesleft #1 >
+            { ", " * t * }
+            {
+              numnames #2 >
+                { "," * }
+                'skip$
+              if$
+              t "\bibinfo{person}{others}" =
+                { " {et~al\mbox{.}}" * } % jrh: avoid spacing problems
+                { " {and} " * t * } % from Chicago Manual of Style
+              if$
+            }
+          if$
+        }
+        't
+      if$
+      nameptr #1 + 'nameptr :=          % nameptr += 1;
+      namesleft #1 - 'namesleft :=      % namesleft =- 1;
+    }
+  while$
+}
+
+FUNCTION { my.full.label }
+{
+  's :=
+  #1 'nameptr :=               % nameptr = 1;
+  s num.names$ 'numnames :=    % numnames = num.name$(s);
+  numnames 'namesleft :=
+    { namesleft #0 > }
+
+    { s nameptr "{vv~}{ll}" format.name$ 't :=  % get the next name
+      nameptr #1 >
+        {
+          namesleft #1 >
+            { ", " * t * }
+            {
+              numnames #2 >
+                { "," * }
+                'skip$
+              if$
+              t "others" =
+                { " et~al\mbox{.}" * } % jrh: avoid spacing problems
+                { " and " * t * } % from Chicago Manual of Style
+              if$
+            }
+          if$
+        }
+        't
+      if$
+      nameptr #1 + 'nameptr :=          % nameptr += 1;
+      namesleft #1 - 'namesleft :=      % namesleft =- 1;
+    }
+  while$
+
+}
+
+FUNCTION { format.names.fml }
+{
+  % Format names in "familiar" format, with first initial followed by
+  % last name. Like format.names, ALL names are formatted.
+  % jtb: The names are NOT put in small caps
+
+  's :=
+  #1 'nameptr :=               % nameptr = 1;
+  s num.names$ 'numnames :=    % numnames = num.name$(s);
+  numnames 'namesleft :=
+    { namesleft #0 > }
+
+    {
+      "\bibinfo{person}{" s nameptr "{ff~}{vv~}{ll}{, jj}" format.name$ * "}" * 't :=
+
+      nameptr #1 >
+        {
+          namesleft #1 >
+            { ", " * t * }
+            {
+              numnames #2 >
+                { "," * }
+                'skip$
+              if$
+              t "\bibinfo{person}{others}" =
+                { " {et~al\mbox{.}}" * }
+                { " {and} " * t * }
+              if$
+            }
+          if$
+        }
+        't
+      if$
+      nameptr #1 + 'nameptr :=          % nameptr += 1;
+      namesleft #1 - 'namesleft :=      % namesleft =- 1;
+    }
+  while$
+}
+
+FUNCTION { format.authors }
+{
+  author empty.or.unknown
+    { "" }
+    {
+      "\bibfield{author}{"
+      author format.names add.period$ * "}" *} % jtb: add period if none before
+  if$
+}
+
+FUNCTION { format.key }
+{
+  empty.or.unknown
+    { key field.or.null }
+    { "" }
+  if$
+}
+
+FUNCTION { format.no.key }
+{
+  empty.or.unknown
+    { "" }
+    { "" }
+  if$
+}
+
+FUNCTION { format.editors.fml }
+{
+  % Format editor names for use in the "in" types: inbook, incollection,
+  % inproceedings: first initial, then last names. When editors are the
+  % LABEL for an entry, then format.editor is used which lists editors
+  % by last name first.
+
+  editor empty.or.unknown
+    { "" }
+    {
+      "\bibfield{editor}{"
+      editor format.names.fml
+      *  "}" *
+      editor num.names$ #1 >
+        { " (Eds.)" * }
+        { " (Ed.)" * }
+      if$
+    }
+  if$
+}
+
+FUNCTION { format.editors }
+{ % format editor names for use in labels, last names first.
+  editor empty.or.unknown
+    { "" }
+    {
+      "\bibfield{editor}{"
+      editor format.names
+      *  "}" *
+      editor num.names$ #1 >
+        { " (Eds.)." * }
+        { " (Ed.)." * }
+      if$
+    }
+  if$
+}
+
+FUNCTION { format.articletitle }
+{
+  title empty.or.unknown
+    { "" }
+    % Use this to preserve lettercase in titles:
+    { "\showarticletitle{" title * "}" * }
+    % Use this for downcase title style:
+    % { \showarticletitle{" title "t" change.case$ * "}" * }
+  if$
+}
+
+FUNCTION { format.title }
+{
+  title empty.or.unknown
+    { "" }
+    % Use this to preserve lettercase in titles:
+    { "\bibinfo{title}{" title * "}" * }
+    % Use this for downcase title style:
+    % { title "t" change.case$ }
+  if$
+}
+
+FUNCTION { n.dashify }
+{
+  't :=
+  ""
+    { t empty.or.unknown 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.a.title.with.edition }
+{
+  "\bibinfo{booktitle}{"
+  swap$ emphasize *
+  edition empty.or.unknown
+    'skip$
+    { " (\bibinfo{edition}{" * edition "l" change.case$ *
+      "} ed.)" * } % jtb: no parens for ed.
+  if$
+  "}" *
+}
+
+FUNCTION { format.btitle }
+{ title format.a.title.with.edition }
+
+FUNCTION { format.emphasize.booktitle }
+{ booktitle format.a.title.with.edition }
+
+
+
+FUNCTION { format.city }
+{
+  % jtb: if the preceding string (the title of the conference) is non-empty,
+  % jtb: append the location, otherwise leave empty (so as to trigger the
+  % jtb: error message in output.check
+
+  duplicate$ empty.or.unknown
+    { }
+    {
+      city empty.or.unknown location empty.or.unknown and
+        {
+          date empty.or.unknown
+            { }
+            { " (" * date * ")" * }
+          if$
+        }
+        {
+          location empty.or.unknown
+            {
+              date empty.or.unknown
+                { " (" * city * ")" * }
+                { " (" * city * ", " * date * ")" * }
+              if$
+            }
+            {
+              date empty.or.unknown
+                { " (" * location * ")" * }
+                { " (" * location * ", " * date * ")" * }
+              if$
+            }
+          if$
+        }
+      if$
+    }
+  if$
+}
+
+FUNCTION { tie.or.space.connect }
+{
+  duplicate$ text.length$ #3 <
+    { "~" }
+    { " " }
+  if$
+  swap$ * *
+}
+
+FUNCTION { either.or.check }
+{
+  empty.or.unknown
+    'pop$
+    { "can't use both " swap$ * " fields in " * cite$ * warning$ }
+  if$
+}
+
+FUNCTION { format.bvolume }
+{
+  % jtb: If there is a series, this is added and the volume trails after it.
+  % jtb: Otherwise, "Vol" is Capitalized.
+
+  volume empty.or.unknown
+    { "" }
+    {
+      series empty.or.unknown
+        { "Vol.~\bibinfo{volume}{" volume "}" * *}
+        { "\bibinfo{series}{" series "}, " * *
+          "Vol.~\bibinfo{volume}{" volume "}" * * *}
+      if$
+      "volume and number" number either.or.check
+    }
+  if$
+}
+
+FUNCTION { format.bvolume.noseries }
+{
+  volume empty.or.unknown
+    { "" }
+    { "Vol.~\bibinfo{volume}{" volume "}" * *
+      "volume and number" number either.or.check
+    }
+  if$
+}
+
+FUNCTION { format.series }
+{
+  series empty.or.unknown
+    {""}
+    {" \emph{(\bibinfo{series}{" * series "}" *
+     volume empty.or.unknown
+       {
+         number empty.or.unknown
+            {")}" *}
+            {", \bibinfo{number}{" number "})}" * * *}
+          if$
+       }
+       {", Vol.~\bibinfo{volume}{" volume "})}" * * *
+        "volume and number" number either.or.check
+       }
+     if$
+    }
+  if$
+}
+
+FUNCTION { format.number.series }
+{
+  volume empty.or.unknown
+    {
+      number empty.or.unknown
+        {
+          volume empty.or.unknown
+          { "" }
+          {
+            series empty.or.unknown
+              { "" }
+              { " (\bibinfo{series}{" series * "})" * }
+            if$
+          }
+          if$
+        }                                       %    { series field.or.null }
+        {
+          output.state mid.sentence =
+            { "Number" }                        % gnp - changed to mixed case always
+            { "Number" }
+          if$
+          number tie.or.space.connect series empty.or.unknown
+            { "there's a number but no series in " cite$ * warning$ }
+            { " in \bibinfo{series}{" * series * "}" * }
+          if$
+        }
+      if$
+    }
+    {
+      ""
+    }
+  if$
+}
+
+FUNCTION { multi.page.check }
+{
+  't :=
+  #0 'multiresult :=
+    { multiresult not
+      t empty.or.unknown 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.pages }
+{
+  pages empty.or.unknown
+    { "" }
+    { "\bibinfo{pages}{"
+      pages multi.page.check
+        { pages n.dashify } % gnp - removed () % jtb: removed pp.
+        { pages }
+      if$
+      * "}" *
+    }
+  if$
+}
+
+FUNCTION { format.pages.check.without.articleno }
+{ %% format pages field only if articleno is absent
+  %% Stack out: pages-specification
+  numpages missing$ pages missing$ and
+    { "page numbers missing in both pages and numpages fields in " cite$ * warning$ }
+    { }
+  if$
+
+  articleno empty.or.unknown eid empty.or.unknown and
+    {
+      pages missing$
+        {
+	   numpages empty.or.unknown
+	     {""}
+             { "\bibinfo{numpages}{" numpages * "}~pages" * }
+	  if$
+	}
+        { format.pages }
+      if$
+    }
+    { "" }
+  if$
+}
+
+FUNCTION { format.pages.check }
+{
+  pages empty.or.unknown
+    { "page numbers missing in " cite$ * warning$ "" }
+    { pages n.dashify }
+  if$
+}
+
+FUNCTION { format.bookpages }
+{
+  bookpages empty.or.unknown
+    { "" }
+    { bookpages "book pages" tie.or.space.connect }
+  if$
+}
+
+FUNCTION { format.named.pages }
+{
+  pages empty.or.unknown
+    { "" }
+    { format.pages "pages" tie.or.space.connect }
+  if$
+}
+
+%
+% Changed by Boris Veytsman, 2011-03-13
+% Now the word "pages" is printed even if
+% there field pages is not empty.
+%
+
+FUNCTION { format.page.count }
+{
+  page.count empty.or.unknown
+    { "" }
+    { "\bibinfo{numpages}{" page.count * "}~pages" * }
+  if$
+}
+
+FUNCTION { format.articleno.numpages }
+{
+  %% There are seven possible outputs, depending on which fields are set.
+  %%
+  %% These four are handled here:
+  %%
+  %%     articleno, numpages, pages     -> "Article articleno-value, numpages-value pages"
+  %%     articleno, numpages            -> "Article articleno-value, numpages-value pages"
+  %%     articleno, pages               -> "Article articleno-value, reduced-pages-value pages"
+  %%     articleno                      -> "Article articleno-value" and warn about missing numpages
+  %%
+  %% The remaining three have already been handled by
+  %% format.pages.check.without.articleno:
+  %%
+  %%     numpages, pages                -> "pages-value"
+  %%     numpages                       -> "numpages-value"
+  %%     pages                          -> "pages-value"
+  %%
+  %% We no longer issue warninig when missing articleno, but having numpages
+
+  articleno empty.or.unknown eid empty.or.unknown and
+    {
+%%      numpages empty.or.unknown
+%%        { }
+%%        { "numpages field, but no articleno or eid field, in "
+%%          cite$ * warning$ }
+%%      if$
+      ""
+    }
+    {
+      numpages empty.or.unknown
+        {
+          pages empty.or.unknown
+            {
+              "articleno or eid, but no pages or numpages field in "
+                 cite$ * warning$
+              "" 'page.count :=
+            }
+            { reduce.pages.to.page.count }
+          if$
+        }
+        { numpages 'page.count := }
+      if$
+
+      %% The Article number is now handled in format.day.month.year because
+      %% ACM prefers the style "Digital Libraries 12, 3, Article 5 (July 2008)"
+      %% over "Digital Libraries 12, 3 (July 2008), Article 5"
+      %% format.articleno output
+      format.page.count
+    }
+  if$
+}
+
+FUNCTION {calc.format.page.count}
+{
+  numpages empty.or.unknown
+   {
+     pages empty.or.unknown
+        {
+        "" 'page.count :=
+        }
+        { reduce.pages.to.page.count }
+     if$
+   }
+   { numpages 'page.count := }
+  if$
+  format.page.count
+}
+
+
+FUNCTION { journal.canon.abbrev }
+{
+  % Returns a canonical abbreviation for 'journal', or else 'journal'
+  % unchanged.
+  journal "ACM Computing Surveys"                                                                       = { "Comput. Surveys"                                 } {
+  journal "{ACM} Computing Surveys"                                                                     = { "Comput. Surveys"                                 } {
+  journal "ACM Transactions on Mathematical Software"                                                   = { "ACM Trans. Math. Software"                       } {
+  journal "{ACM} Transactions on Mathematical Software"                                                 = { "ACM Trans. Math. Software"                       } {
+  journal "ACM SIGNUM Newsletter"                                                                       = { "ACM SIGNUM Newslett."                            } {
+  journal "ACM {SIGNUM} Newsletter"                                                                     = { "ACM SIGNUM Newslett."                            } {
+  journal "{ACM} SIGNUM Newsletter"                                                                     = { "ACM SIGNUM Newslett."                            } {
+  journal "{ACM} {SIGNUM} Newsletter"                                                                   = { "ACM SIGNUM Newslett."                            } {
+  journal "American Journal of Sociology"                                                               = { "Amer. J. Sociology"                              } {
+  journal "American Mathematical Monthly"                                                               = { "Amer. Math. Monthly"                             } {
+  journal "American Mathematical Society Translations"                                                  = { "Amer. Math. Soc. Transl."                        } {
+  journal "Applied Mathematics and Computation"                                                         = { "Appl. Math. Comput."                             } {
+  journal "British Journal of Mathematical and Statistical Psychology"                                  = { "Brit. J. Math. Statist. Psych."                  } {
+  journal "Bulletin of the American Mathematical Society"                                               = { "Bull. Amer. Math. Soc."                          } {
+  journal "Canadian Mathematical Bulletin"                                                              = { "Canad. Math. Bull."                              } {
+  journal "Communications of the ACM"                                                                   = { "Commun. ACM"                                     } {
+  journal "Communications of the {ACM}"                                                                 = { "Commun. ACM"                                     } {
+  journal "Computers and Structures"                                                                    = { "Comput. \& Structures"                           } {
+  journal "Contemporary Mathematics"                                                                    = { "Contemp. Math."                                  } {
+  journal "Crelle's Journal"                                                                            = { "Crelle's J."                                     } {
+  journal "Giornale di Mathematiche"                                                                    = { "Giorn. Mat."                                     } {
+  journal "IEEE Transactions on Aerospace and Electronic Systems"                                       = { "IEEE Trans. Aerospace Electron. Systems"         } {
+  journal "{IEEE} Transactions on Aerospace and Electronic Systems"                                     = { "IEEE Trans. Aerospace Electron. Systems"         } {
+  journal "IEEE Transactions on Automatic Control"                                                      = { "IEEE Trans. Automat. Control"                    } {
+  journal "{IEEE} Transactions on Automatic Control"                                                    = { "IEEE Trans. Automat. Control"                    } {
+  journal "IEEE Transactions on Computers"                                                              = { "IEEE Trans. Comput."                             } {
+  journal "{IEEE} Transactions on Computers"                                                            = { "IEEE Trans. Comput."                             } {
+  journal "IMA Journal of Numerical Analysis"                                                           = { "IMA J. Numer. Anal."                             } {
+  journal "{IMA} Journal of Numerical Analysis"                                                         = { "IMA J. Numer. Anal."                             } {
+  journal "Information Processing Letters"                                                              = { "Inform. Process. Lett."                          } {
+  journal "International Journal for Numerical Methods in Engineering"                                  = { "Internat. J. Numer. Methods Engrg."              } {
+  journal "International Journal of Control"                                                            = { "Internat. J. Control"                            } {
+  journal "International Journal of Supercomputing Applications"                                        = { "Internat. J. Supercomputing Applic."             } {
+  journal "Journal of Computational Physics"                                                            = { "J. Comput. Phys."                                } {
+  journal "Journal of Computational and Applied Mathematics"                                            = { "J. Comput. Appl. Math."                          } {
+  journal "Journal of Computer and System Sciences"                                                     = { "J. Comput. System Sci."                          } {
+  journal "Journal of Mathematical Analysis and Applications"                                           = { "J. Math. Anal. Appl."                            } {
+  journal "Journal of Mathematical Physics"                                                             = { "J. Math. Phys."                                  } {
+  journal "Journal of Parallel and Distributed Computing"                                               = { "J. Parallel and Distrib. Comput."                } {
+  journal "Journal of Research of the National Bureau of Standards"                                     = { "J. Res. Nat. Bur. Standards"                     } {
+  journal "Journal of VLSI and Computer Systems"                                                        = { "J. VLSI Comput. Syst."                           } {
+  journal "Journal of {VLSI} and Computer Systems"                                                      = { "J. VLSI Comput. Syst."                           } {
+  journal "Journal of the ACM"                                                                          = { "J. ACM"                                          } {
+  journal "Journal of the American Statistical Association"                                             = { "J. Amer. Statist. Assoc."                        } {
+  journal "Journal of the Institute of Mathematics and its Applications"                                = { "J. Inst. Math. Appl."                            } {
+  journal "Journal of the Society for Industrial and Applied Mathematics"                               = { "J. Soc. Indust. Appl. Math."                     } {
+  journal "Journal of the Society for Industrial and Applied Mathematics, Series B, Numerical Analysis" = { "J. Soc. Indust. Appl. Math. Ser. B Numer. Anal." } {
+  journal "Linear Algebra and its Applications"                                                         = { "Linear Algebra Appl."                            } {
+  journal "Mathematica Scandinavica"                                                                    = { "Math. Scand."                                    } {
+  journal "Mathematical Tables and Other Aids to Computation"                                           = { "Math. Tables Aids Comput."                       } {
+  journal "Mathematics of Computation"                                                                  = { "Math. Comp."                                     } {
+  journal "Mathematische Annalen"                                                                       = { "Math. Ann."                                      } {
+  journal "Numerische Mathematik"                                                                       = { "Numer. Math."                                    } {
+  journal "Pacific Journal of Mathematics"                                                              = { "Pacific J. Math."                                } {
+  journal "Parallel Computing"                                                                          = { "Parallel Comput."                                } {
+  journal "Philosophical Magazine"                                                                      = { "Philos. Mag."                                    } {
+  journal "Proceedings of the American Mathematical Society"                                            = { "Proc. Amer. Math. Soc."                          } {
+  journal "Proceedings of the IEEE"                                                                     = { "Proc. IEEE"                                      } {
+  journal "Proceedings of the {IEEE}"                                                                   = { "Proc. IEEE"                                      } {
+  journal "Proceedings of the National Academy of Sciences of the USA"                                  = { "Proc. Nat. Acad. Sci. U. S. A."                  } {
+  journal "Quarterly Journal of Mathematics, Oxford, Series (2)"                                        = { "Quart. J. Math. Oxford Ser. (2)"                 } {
+  journal "Quarterly of Applied Mathematics"                                                            = { "Quart. Appl. Math."                              } {
+  journal "Review of the International Statisical Institute"                                            = { "Rev. Inst. Internat. Statist."                   } {
+  journal "SIAM Journal on Algebraic and Discrete Methods"                                              = { "SIAM J. Algebraic Discrete Methods"              } {
+  journal "{SIAM} Journal on Algebraic and Discrete Methods"                                            = { "SIAM J. Algebraic Discrete Methods"              } {
+  journal "SIAM Journal on Applied Mathematics"                                                         = { "SIAM J. Appl. Math."                             } {
+  journal "{SIAM} Journal on Applied Mathematics"                                                       = { "SIAM J. Appl. Math."                             } {
+  journal "SIAM Journal on Computing"                                                                   = { "SIAM J. Comput."                                 } {
+  journal "{SIAM} Journal on Computing"                                                                 = { "SIAM J. Comput."                                 } {
+  journal "SIAM Journal on Matrix Analysis and Applications"                                            = { "SIAM J. Matrix Anal. Appl."                      } {
+  journal "{SIAM} Journal on Matrix Analysis and Applications"                                          = { "SIAM J. Matrix Anal. Appl."                      } {
+  journal "SIAM Journal on Numerical Analysis"                                                          = { "SIAM J. Numer. Anal."                            } {
+  journal "{SIAM} Journal on Numerical Analysis"                                                        = { "SIAM J. Numer. Anal."                            } {
+  journal "SIAM Journal on Scientific and Statistical Computing"                                        = { "SIAM J. Sci. Statist. Comput."                   } {
+  journal "{SIAM} Journal on Scientific and Statistical Computing"                                      = { "SIAM J. Sci. Statist. Comput."                   } {
+  journal "SIAM Review"                                                                                 = { "SIAM Rev."                                       } {
+  journal "{SIAM} Review"                                                                               = { "SIAM Rev."                                       } {
+  journal "Software Practice and Experience"                                                            = { "Software Prac. Experience"                       } {
+  journal "Statistical Science"                                                                         = { "Statist. Sci."                                   } {
+  journal "The Computer Journal"                                                                        = { "Comput. J."                                      } {
+  journal "Transactions of the American Mathematical Society"                                           = { "Trans. Amer. Math. Soc."                         } {
+  journal "USSR Computational Mathematics and Mathematical Physics"                                     = { "U. S. S. R. Comput. Math. and Math. Phys."       } {
+  journal "{USSR} Computational Mathematics and Mathematical Physics"                                   = { "U. S. S. R. Comput. Math. and Math. Phys."       } {
+  journal "Zeitschrift fur Angewandte Mathematik und Mechanik"                                          = { "Z. Angew. Math. Mech."                           } {
+  journal "Zeitschrift fur Angewandte Mathematik und Physik"                                            = { "Z. Angew. Math. Phys."                           } {
+  journal
+  } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$
+  } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$
+  } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$
+  } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$
+  } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$
+  } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$
+  } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$
+  } if$ } if$ } if$ } if$ } if$ } if$ } if$ } if$
+}
+
+FUNCTION { format.journal.volume.number.day.month.year }
+{
+  % By Young (and Spencer)
+  % GNP - fixed bugs with missing volume, number, and/or pages
+  %
+  % Format journal, volume, number, pages for article types.
+  %
+  journal empty.or.unknown
+    { "no journal in " cite$ * warning$ "" }
+    { "\bibinfo{journal}{"
+      journal.canon.abbrev emphasize *
+      "}" * }
+  if$
+
+  number empty.or.unknown
+    {
+      volume empty.or.unknown
+        { "no number and no volume in " cite$ * warning$ "" * }
+        { " " * " \bibinfo{volume}{" * volume * "}" * }
+      if$
+    }
+    {
+      volume empty.or.unknown
+        {
+          "unusual to have number, but no volume, for " cite$ * warning$
+          " \bibinfo{number}{" * number * "}" *
+        }
+        { " \bibinfo{volume}{" * volume  * "}, \bibinfo{number}{" *
+          number * "}" *}
+      if$
+    }
+  if$
+  after.block 'output.state :=
+
+  % Sometimes proceedings are published in journals
+  % In this case we do not want to put year, day and month here
+
+  type$ "inproceedings" =
+    { }
+    {format.day.month.year * }
+  if$
+}
+
+FUNCTION { format.chapter.pages }
+{
+  chapter empty.or.unknown
+    'format.pages
+    { type empty.or.unknown
+        { "Chapter" } % gnp - changed to mixed case
+        { type "t" change.case$ }
+      if$
+      chapter tie.or.space.connect
+      pages empty.or.unknown
+        {"page numbers missing in " cite$ * warning$} % gnp - added check
+        { ", " * format.pages * }
+      if$
+    }
+  if$
+}
+
+FUNCTION { format.in.emphasize.booktitle }
+{ % jtb: format for collections or proceedings not appearing in a journal
+  booktitle empty.or.unknown
+  { "" }
+  { "In " format.emphasize.booktitle * }
+  if$
+}
+
+FUNCTION { format.in.booktitle }
+{ % jtb: format for proceedings appearing in a journal
+  booktitle empty.or.unknown
+  { "" }
+  { "In \bibinfo{booktitle}{" booktitle * "}" * }
+  if$
+}
+
+FUNCTION { format.in.ed.booktitle }
+{
+  booktitle empty.or.unknown
+  { "" }
+  { editor empty.or.unknown
+    { "In " format.emphasize.booktitle * }
+                % jtb: swapped editor location
+    { "In " format.emphasize.booktitle * ", " * format.editors.fml * }
+    if$
+  }
+  if$
+}
+
+FUNCTION { format.thesis.type }
+{ % call with default type on stack top
+  type empty.or.unknown
+    'skip$    % use default type
+    {
+      pop$    % discard default type
+      % NO: it is silly to have to brace protect every degree type!:  type "t" change.case$
+      type
+    }
+  if$
+}
+
+FUNCTION { format.tr.number }
+{
+  "\bibinfo{type}{"
+  type empty.or.unknown
+    { "{T}echnical {R}eport" }
+    'type
+  if$
+  "}" * *
+  number empty.or.unknown
+    { "t" change.case$ }
+    %% LOOKS BAD: { "." * number tie.or.space.connect }
+    %% Prefer "Research report RJ687." to "Research report. RJ687."
+    { number tie.or.space.connect }
+  if$
+}
+
+FUNCTION { format.advisor }
+{
+  advisor empty.or.unknown
+    { "" }
+    { "Advisor(s) " advisor * }
+  if$
+}
+
+FUNCTION { format.article.crossref }
+{ "See"
+  "\citeN{" * crossref * "}" *
+}
+
+FUNCTION { format.crossref.editor }
+{
+  editor #1 "{vv~}{ll}" format.name$
+  editor num.names$ duplicate$
+  #2 >
+    { pop$ " et~al\mbox{.}" * }         % jrh: avoid spacing problems
+    { #2 <
+    'skip$
+    { editor #2 "{ff }{vv }{ll}{ jj}" format.name$ "others" =
+        { " et~al\mbox{.}" * }          % jrh: avoid spacing problems
+        { " and " * editor #2 "{vv~}{ll}" format.name$ * }
+      if$
+    }
+      if$
+    }
+  if$
+}
+
+FUNCTION { format.book.crossref }
+{
+  volume empty.or.unknown
+    { "empty volume in " cite$ * "'s crossref of " * crossref * warning$
+      "In "
+    }
+    { "Volume" volume tie.or.space.connect % gnp - changed to mixed case
+      " of " *
+    }
+  if$
+  editor empty.or.unknown
+  editor field.or.null author field.or.null =
+  or
+    { key empty.or.unknown
+    { series empty.or.unknown
+        { "need editor, key, or series for " cite$ * " to crossref " *
+          crossref * warning$
+          "" *
+        }
+        { series emphasize * }
+      if$
+    }
+    { key * }
+      if$
+    }
+    { format.crossref.editor * }
+  if$
+  " \citeN{" * crossref * "}" *
+}
+
+FUNCTION { format.incoll.inproc.crossref }
+{ "See"
+  " \citeN{" * crossref * "}" *
+}
+
+FUNCTION { format.lab.names }
+{
+  % format.lab.names:
+  %
+  % determines "short" names for the abbreviated author information.
+  % "Long" labels are created in calc.label, using the routine my.full.label
+  % to format author and editor fields.
+  %
+  % There are 4 cases for labels.   (n=3 in the example)
+  % a) one author             Foo
+  % b) one to n               Foo, Bar and Baz
+  % c) use of "and others"    Foo, Bar et al.
+  % d) more than n            Foo et al.
+
+  's :=
+  s num.names$ 'numnames :=
+  numnames #2 >    % change number to number of others allowed before
+                   % forcing "et al".
+    { s #1 "{vv~}{ll}" format.name$ " et~al\mbox{.}" * } % jrh: \mbox{} added
+    {
+      numnames #1 - 'namesleft :=
+      #2 'nameptr :=
+      s #1 "{vv~}{ll}" format.name$
+        { namesleft #0 > }
+        { nameptr numnames =
+            { s nameptr "{ff }{vv }{ll}{ jj}" format.name$ "others" =
+                { " et~al\mbox{.}" * }          % jrh: avoid spacing problems
+                { " and " * s nameptr "{vv~}{ll}" format.name$ * }
+              if$
+            }
+            { ", " * s nameptr "{vv~}{ll}" format.name$ * }
+          if$
+          nameptr #1 + 'nameptr :=
+          namesleft #1 - 'namesleft :=
+        }
+      while$
+    }
+  if$
+}
+
+FUNCTION { author.key.label }
+{
+  author empty.or.unknown
+    { key empty.or.unknown
+          { "no key, author in " cite$ * warning$
+            cite$ #1 #3 substring$ }
+         'key
+      if$
+    }
+    { author format.lab.names }
+  if$
+}
+
+FUNCTION { editor.key.organization.label }
+{ % added - gnp. Provide label formatting by organization if editor is null.
+  editor empty.or.unknown
+    { organization empty.or.unknown
+        { key empty.or.unknown
+            { "no key, editor or organization in " cite$ * warning$
+              cite$ #1 #3 substring$ }
+            'key
+          if$
+        }
+        { organization }
+      if$
+    }
+    { editor format.lab.names }
+  if$
+}
+
+FUNCTION { author.editor.key.label }
+{
+  author empty.or.unknown
+    { editor empty.or.unknown
+          { key empty.or.unknown
+               { "no key, author, or editor in " cite$ * warning$
+                 cite$ #1 #3 substring$ }
+             'key
+           if$
+         }
+          { editor format.lab.names }
+      if$
+    }
+    { author format.lab.names }
+  if$
+}
+
+FUNCTION { author.editor.key.organization.label }
+{ % added - gnp. Provide label formatting by organization if author is null.
+  author empty.or.unknown
+    { editor empty.or.unknown
+        { organization empty.or.unknown
+            { key empty.or.unknown
+               { "no key, author, editor or organization in " cite$ * warning$
+                 cite$ #1 #3 substring$ }
+               'key
+              if$
+            }
+            { organization }
+          if$
+        }
+        { editor format.lab.names }
+      if$
+    }
+    { author format.lab.names }
+  if$
+}
+
+% Calculate label and leave it on stack
+FUNCTION { calc.basic.label }
+{
+  type$ "book" =
+  type$ "inbook" =
+  or
+  type$ "article" =
+  or
+    'author.editor.key.label
+    { type$ "proceedings" =
+      type$ "periodical" =
+      or
+        'editor.key.organization.label
+        { type$ "manual" =
+            'author.editor.key.organization.label
+            'author.key.label
+          if$
+        }
+      if$
+    }
+  if$
+  duplicate$
+  year empty.or.unknown
+    { "[n.\,d.]" }
+    { year field.or.null purify$ #-1 #4 substring$}
+  if$
+  *
+  'basic.label.year :=
+}
+
+FUNCTION { calc.label }
+{
+  % Changed - GNP. See also author.editor.organization.sort, editor.organization.sort
+  % Form label for BibTeX entry. The classification of which fields are used
+  % for which type of entry (book, inbook, etc.) are taken from alpha.bst.
+  % The change here from newapa is to also include organization as a
+  % citation label if author or editor is missing.
+
+  calc.basic.label
+
+  author empty.or.unknown  % generate the full label citation information.
+    {
+      editor empty.or.unknown
+        {
+          organization empty.or.unknown
+            {
+              key empty.or.unknown
+                {
+                  "no author, editor, organization, or key in " cite$ * warning$
+                  "??"
+                }
+                { key }
+              if$
+            }
+            { organization }
+          if$
+        }
+        { editor my.full.label }
+      if$
+    }
+    { author my.full.label }
+  if$
+
+  % leave label on the stack, to be popped when required.
+
+  "}{" * swap$ * "}{" *
+  %  year field.or.null purify$ #-1 #4 substring$ *
+  %
+  % save the year for sort processing afterwards (adding a, b, c, etc.)
+  %
+  year empty.or.unknown
+    { "[n.\,d.]" }
+    { year field.or.null purify$ #-1 #4 substring$}
+  if$
+  'label.year :=
+}
+
+
+FUNCTION { output.bibitem }
+{
+  newline$
+  "\bibitem[" write$
+  calc.basic.label write$
+  "(" write$
+  sort.year write$
+  ")" write$
+  "]%" writeln
+  "        {" write$
+  cite$ write$
+  "}" writeln
+  ""
+  before.all 'output.state :=
+}
+
+
+FUNCTION { output.issue.doi.coden.isxn.lccn.url.eprint }
+{ % enter and return with stack empty
+  %% We switch now from buffered output to output of complete lines, so
+  %% that the Issue .. URL data have their own lines, and are less likely
+  %% to be line-wrapped by BibTeX's short-sighted algorithm, which wraps
+  %% lines longer than 79 characters, backtracking to what it thinks is
+  %% a break point in the string.  Any such wrapping MUST be undone to
+  %% prevent percent-newline from appearing in DOIs and URLs.  The
+  %% output data are intentionally wrapped in \showxxx{} macros at
+  %% beginning of line, and that supply their own punctuation (if they
+  %% are not defined to suppress output entirely), to make it easier for
+  %% other software to recover them from .bbl files.
+  %%
+  %% It also makes it possible to later change the macro definitions
+  %% to suppress particular output values, or alter their appearance.
+  %%
+  %% Note that it is possible for theses, technical reports, and
+  %% manuals to have ISBNs, and anything that has an ISBN may also
+  %% have an ISSN.  When there are no values for these keys, there
+  %% is no output generated for them here.
+
+  "\newblock" writeln
+  after.block 'output.state :=
+
+  output.issue
+  output.isbn
+  output.coden  % CODEN is functionally like ISSN, so output them sequentially
+  output.issn
+  output.lccn
+  output.doi    % DOI is ALWAYS last according to CrossRef DOI documentation
+  output.eprint
+  output.url    % but ACM wants URL last
+}
+
+FUNCTION { output.issue.doi.coden.isxn.lccn.url.eprint.note }
+{ % enter with stack empty, return with empty string on stack
+  output.issue.doi.coden.isxn.lccn.url.eprint
+  note empty.or.unknown
+    { }
+    {
+      "\newblock" writeln
+      output.note
+    }
+  if$
+  ""
+}
+
+FUNCTION { output.issue.doi.coden.isxn.lccn.url.eprint.note.check }
+{ % enter with stack empty, return with empty string on stack
+  output.issue.doi.coden.isxn.lccn.url.eprint
+  note empty.or.unknown
+    { }
+    {
+      "\newblock" writeln
+      output.note.check
+    }
+  if$
+  ""
+}
+
+FUNCTION { article }
+{
+  output.bibitem
+
+  author empty.or.unknown
+    {
+      editor empty.or.unknown
+        { "neither author and editor supplied for " cite$ * warning$ }
+        { format.editors "editor" output.check }
+      if$
+    }
+    { format.authors "author" output.check }
+  if$
+
+  author format.no.key output       % added
+  output.year.check                 % added
+  new.block
+  format.articletitle "title" output.check
+  new.block
+  howpublished empty.or.unknown
+    { }
+    { "\bibinfo{howpublished}{" howpublished "}" * * output }
+  if$
+
+  crossref missing$
+    { format.journal.volume.number.day.month.year output}
+    {
+      "cross reference in @Article{...} is unusual" warning$
+      format.article.crossref output.nonnull
+    }
+  if$
+
+  format.pages.check.without.articleno output
+  format.articleno.numpages output
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { book }
+{
+  output.bibitem
+  author empty.or.unknown
+    { format.editors "author and editor" output.check }
+    { format.authors output.nonnull
+      crossref missing$
+        { "author and editor" editor either.or.check }
+        'skip$
+      if$
+    }
+  if$
+  output.year.check       % added
+  new.block
+  format.btitle "title" output.check
+  crossref missing$
+    { new.sentence              % jtb: start a new sentence for series/volume
+      format.bvolume output
+      new.block
+      format.number.series output
+      new.sentence
+      publisher "publisher" bibinfo.output.check
+      address "address" bibinfo.output.check    % jtb: require address
+      fin.sentence
+      pages empty.or.unknown
+        { format.bookpages }    % use bookpages when pages empty
+        { format.pages.check "pages" tie.or.space.connect }
+      if$
+      output
+    }
+    { new.block
+      format.book.crossref output.nonnull
+    }
+  if$
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { booklet }
+{
+  output.bibitem
+  format.authors output
+  author format.key output          % added
+  output.year.check                 % added
+  new.block
+  format.title "title" output.check
+  new.block
+    howpublished empty.or.unknown
+    { }
+    { "\bibinfo{howpublished}{" howpublished "}" * * output }
+  if$
+  address output
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { inbook }
+{
+  output.bibitem
+  author empty.or.unknown
+    { format.editors
+      "author and editor" output.check
+    }
+    { format.authors output.nonnull
+      crossref missing$
+    { "author and editor" editor either.or.check }
+    'skip$
+      if$
+    }
+  if$
+  output.year.check                 % added
+  new.block
+  format.btitle "title" output.check
+  crossref missing$
+    { new.sentence              % jtb: start a new sentence for series/volume
+      format.bvolume output
+      new.block
+      format.number.series output
+      new.sentence
+      publisher "publisher" bibinfo.output.check
+      address "address" bibinfo.output.check    % jtb: require address
+      format.bookpages output
+      format.chapter.pages
+      "chapter and pages" output.check  % jtb: moved from before publisher
+    }
+    {
+      format.bookpages output
+      format.chapter.pages "chapter and pages" output.check
+      new.block
+      format.book.crossref output.nonnull
+    }
+  if$
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { incollection }
+{
+  output.bibitem
+  format.authors "author" output.check
+  author format.key output       % added
+  output.year.check              % added
+  new.block
+  format.articletitle "title" output.check
+  new.block
+  crossref missing$
+    { format.in.ed.booktitle "booktitle" output.check
+      new.sentence                % jtb: start a new sentence for series/volume
+      format.bvolume output
+      format.number.series output
+      new.sentence
+      publisher "publisher" bibinfo.output.check
+      address "address" bibinfo.output.check      % jtb: require address
+      format.bookpages output
+      format.chapter.pages output % gnp - was special.output.nonnull
+                                  % left out comma before page numbers
+                                  % jtb: moved from before publisher
+    }
+    {
+      format.incoll.inproc.crossref output.nonnull
+      format.chapter.pages output
+    }
+  if$
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { inproceedings }
+{
+  output.bibitem
+  format.authors "author" output.check
+  author format.key output            % added
+  output.year.check                   % added
+  new.block
+  format.articletitle "title" output.check
+  howpublished empty.or.unknown
+    { }
+    { "\bibinfo{howpublished}{" howpublished "}" * * output.dot.space }
+  if$
+  crossref missing$
+    {
+      journal missing$          % jtb: proceedings appearing in journals
+        { format.in.emphasize.booktitle format.city "booktitle"  output.check.dot.space
+          format.series output.removenospace
+          format.editors.fml output % BV 2011/09/27 Moved dot to comma
+          series empty.or.unknown
+              { format.bvolume.noseries output }
+              {}
+          if$
+          new.sentence
+          organization output
+          publisher "publisher" bibinfo.output.check % jtb: require publisher (?)
+          address "address" bibinfo.output.check  % jtb: require address
+          format.bookpages output
+        }
+        {
+           format.in.booktitle format.city "booktitle" output.check
+           format.editors.fml output
+           new.sentence
+           format.journal.volume.number.day.month.year output
+        }
+      if$
+      format.articleno output
+      format.pages.check.without.articleno output
+    }
+    {
+      format.incoll.inproc.crossref output.nonnull
+      format.articleno output
+      format.pages.check.without.articleno output
+    }
+  if$
+  format.articleno.numpages output
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { conference } { inproceedings }
+
+FUNCTION { manual }
+{
+  output.bibitem
+  author empty.or.unknown
+    { editor empty.or.unknown
+      { organization "organization" output.check
+        organization format.key output }  % if all else fails, use key
+      { format.editors "author and editor" output.check }
+      if$
+    }
+    { format.authors output.nonnull }
+    if$
+  output.year.check                 % added
+  new.block
+  format.btitle "title" output.check
+  organization address new.block.checkb
+  % jtb: back to normal style: organization, address
+  organization "organization" output.check
+  address output
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { mastersthesis }
+{
+  output.bibitem
+  format.authors "author" output.check
+  author format.key output          % added
+  output.year.check                 % added
+  new.block
+  format.title emphasize "title" output.check  % NB: ACM style requires emphasized thesis title
+  new.block
+  "\bibinfo{thesistype}{Master's\ thesis}" format.thesis.type output
+  new.sentence
+  school "school" bibinfo.output.check
+  address empty.or.unknown
+     { }
+     { "\bibinfo{address}{" address * "}" * output }
+  if$
+  new.block
+  format.advisor output
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { misc }
+{
+  output.bibitem
+  format.authors "author" output.check
+  author format.key output            % added
+  output.year.check                   % added
+  title howpublished new.block.checkb
+  format.title output
+  new.block
+  howpublished empty.or.unknown
+    { }
+    { "\bibinfo{howpublished}{" howpublished "}" * * output }
+  if$
+  "" output.nonnull.dot.space
+  calc.format.page.count output
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { online } { manual }
+
+FUNCTION { game } { manual }
+
+FUNCTION { artifactsoftware } { manual }
+
+FUNCTION { artifactdataset } { manual }
+
+FUNCTION { software } { manual }
+
+FUNCTION { dataset } { manual }
+
+FUNCTION { phdthesis }
+{
+  output.bibitem
+  format.authors "author" output.check
+  author format.key output          % added
+  output.year.check                 % added
+  new.block
+  format.title emphasize "title" output.check  % NB: ACM style requires emphasized thesis title
+  new.block
+  "\bibinfo{thesistype}{Ph.\,D. Dissertation}" format.thesis.type output
+  new.sentence
+  school "school" bibinfo.output.check
+  address empty.or.unknown
+     { }
+     { "\bibinfo{address}{" address * "}" * output }
+  if$
+  new.block
+  format.advisor output
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION {format.date}
+{ year empty.or.unknown
+    { month empty.or.unknown
+        {
+          ""                    % output empty date if year/month both empty
+          day empty.or.unknown
+            {  }
+            { "there's a day but no month or year in " cite$ * warning$ }
+          if$
+        }
+        { "there's a month but no year in " cite$ * warning$
+          month
+          day empty.or.unknown
+            { }
+            { " " * day * }
+          if$
+        }
+      if$
+    }
+    { month empty.or.unknown
+        {
+          year                  % output only year if month empty
+          day empty.or.unknown
+            {  }
+            { "there's a day and year but no month in " cite$ * warning$ }
+          if$
+        }
+        {
+          month " " *
+          day empty.or.unknown
+            { }
+            { day * ", " * }
+          if$
+          year *
+        }
+      if$
+    }
+  if$
+}
+
+FUNCTION {new.block.checka}
+{
+  empty.or.unknown
+    'skip$
+    'new.block
+  if$
+}
+
+FUNCTION { periodical }
+{
+  output.bibitem
+  editor empty.or.unknown
+    { organization output }
+    { format.editors output.nonnull }
+  if$
+  new.block
+  output.year.check
+  new.sentence
+  format.articletitle "title" output.check
+  format.journal.volume.number.day.month.year output
+  calc.format.page.count output
+  fin.entry
+}
+
+FUNCTION { proceedings }
+{
+  output.bibitem
+  editor empty.or.unknown
+    { organization output
+      organization format.key output }  % gnp - changed from author format.key
+    { format.editors output.nonnull }
+  if$
+  % author format.key output             % gnp - removed (should be either
+  %                                        editor or organization
+  output.year.check                    % added (newapa)
+  new.block
+  format.btitle format.city "title" output.check        % jtb: added city
+  new.sentence
+  format.bvolume output
+  format.number.series output
+  new.sentence
+  organization output
+  % jtb: normal order: publisher, address
+  publisher empty.or.unknown
+     { }
+     { "\bibinfo{publisher}{" publisher * "}" * output }
+  if$
+  address empty.or.unknown
+     { }
+     { "\bibinfo{address}{" address * "}" * output }
+  if$
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { collection } { proceedings }
+
+FUNCTION { techreport }
+{
+  output.bibitem
+  format.authors "author" output.check
+  author format.key output             % added
+  output.year.check                    % added
+  new.block
+  format.btitle "title" output.check
+  new.block
+%   format.tr.number output               % jtb: moved month ...
+  format.tr.number output new.sentence    % Gerry  - need dot 2011/09/28
+  institution "institution" bibinfo.output.check
+  address empty.or.unknown
+    { }
+    { "\bibinfo{address}{" address "}" * * output }
+  if$
+  new.sentence
+  format.named.pages output
+  % ACM omits year at end in transactions style
+  % format.day.month.year output.nonnull.dot.space  % jtb: ... to here (no parens)
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note
+  fin.entry
+}
+
+FUNCTION { unpublished }
+{
+  output.bibitem
+  format.authors
+  "author" output.check
+  author format.key output              % added
+  output.year.check                     % added
+  new.block
+  format.title "title" output.check
+  fin.sentence
+  output.day.month.year                 % UTAH
+  calc.format.page.count output
+  fin.block
+  output.issue.doi.coden.isxn.lccn.url.eprint.note.check
+  fin.entry
+}
+
+FUNCTION { default.type } { misc }
+
+%%% ACM journal-style month definitions: full name if 1--5 letters, else
+%%% abbreviation of 3 or 4 characters and a dot
+
+MACRO {jan}             {"Jan."}
+
+MACRO {feb}             {"Feb."}
+
+MACRO {mar}             {"March"}
+
+MACRO {apr}             {"April"}
+
+MACRO {may}             {"May"}
+
+MACRO {jun}             {"June"}
+
+MACRO {jul}             {"July"}
+
+MACRO {aug}             {"Aug."}
+
+MACRO {sep}             {"Sept."}
+
+MACRO {oct}             {"Oct."}
+
+MACRO {nov}             {"Nov."}
+
+MACRO {dec}             {"Dec."}
+
+%%% ACM journal names
+
+MACRO {cie}  {"ACM Computers in Entertainment"}
+MACRO {csur}  {"ACM Computing Surveys"}
+MACRO {dgov}  {"Digital Government: Research and Practice"}
+MACRO {dtrap}  {"Digital Threats: Research and Practice"}
+MACRO {health}  {"ACM Transactions on Computing for Healthcare"}
+MACRO {imwut}  {"PACM on Interactive, Mobile, Wearable and Ubiquitous Technologies"}
+MACRO {jacm}  {"Journal of the ACM"}
+MACRO {jdiq}  {"ACM Journal of Data and Information Quality"}
+MACRO {jea}  {"ACM Journal of Experimental Algorithmics"}
+MACRO {jeric}  {"ACM Journal of Educational Resources in Computing"}
+MACRO {jetc}  {"ACM Journal on Emerging Technologies in Computing Systems"}
+MACRO {jocch}  {"ACM Journal on Computing and Cultural Heritage"}
+MACRO {pacmcgit}  {"Proceedings of the ACM on Computer Graphics and Interactive Techniques"}
+MACRO {pacmhci}  {"PACM on Human-Computer Interaction"}
+MACRO {pacmpl}  {"PACM on Programming Languages"}
+MACRO {pomacs}  {"PACM on Measurement and Analysis of Computing Systems"}
+MACRO {taas}  {"ACM Transactions on Autonomous and Adaptive Systems"}
+MACRO {taccess}  {"ACM Transactions on Accessible Computing"}
+MACRO {taco}  {"ACM Transactions on Architecture and Code Optimization"}
+MACRO {talg}  {"ACM Transactions on Algorithms"}
+MACRO {tallip}  {"ACM Transactions on Asian and Low-Resource Language Information Processing"}
+MACRO {tap}  {"ACM Transactions on Applied Perception"}
+MACRO {tcps}  {"ACM Transactions on Cyber-Physical Systems"}
+MACRO {tds}  {"ACM/IMS Transactions on Data Science"}
+MACRO {teac}  {"ACM Transactions on Economics and Computation"}
+MACRO {tecs}  {"ACM Transactions on Embedded Computing Systems"}
+MACRO {telo}  {"ACM Transactions on Evolutionary Learning"}
+MACRO {thri}  {"ACM Transactions on Human-Robot Interaction"}
+MACRO {tiis}  {"ACM Transactions on Interactive Intelligent Systems"}
+MACRO {tiot}  {"ACM Transactions on Internet of Things"}
+MACRO {tissec}  {"ACM Transactions on Information and System Security"}
+MACRO {tist}  {"ACM Transactions on Intelligent Systems and Technology"}
+MACRO {tkdd}  {"ACM Transactions on Knowledge Discovery from Data"}
+MACRO {tmis}  {"ACM Transactions on Management Information Systems"}
+MACRO {toce}  {"ACM Transactions on Computing Education"}
+MACRO {tochi}  {"ACM Transactions on Computer-Human Interaction"}
+MACRO {tocl}  {"ACM Transactions on Computational Logic"}
+MACRO {tocs}  {"ACM Transactions on Computer Systems"}
+MACRO {toct}  {"ACM Transactions on Computation Theory"}
+MACRO {todaes}  {"ACM Transactions on Design Automation of Electronic Systems"}
+MACRO {tods}  {"ACM Transactions on Database Systems"}
+MACRO {tog}  {"ACM Transactions on Graphics"}
+MACRO {tois}  {"ACM Transactions on Information Systems"}
+MACRO {toit}  {"ACM Transactions on Internet Technology"}
+MACRO {tomacs}  {"ACM Transactions on Modeling and Computer Simulation"}
+MACRO {tomm}   {"ACM Transactions on Multimedia Computing, Communications and Applications"}
+MACRO {tompecs}  {"ACM Transactions on Modeling and Performance Evaluation of Computing Systems"}
+MACRO {toms}  {"ACM Transactions on Mathematical Software"}
+MACRO {topc}  {"ACM Transactions on Parallel Computing"}
+MACRO {toplas}  {"ACM Transactions on Programming Languages and Systems"}
+MACRO {tops}  {"ACM Transactions on Privacy and Security"}
+MACRO {tos}  {"ACM Transactions on Storage"}
+MACRO {tosem}  {"ACM Transactions on Software Engineering and Methodology"}
+MACRO {tosn}  {"ACM Transactions on Sensor Networks"}
+MACRO {tqc}  {"ACM Transactions on Quantum Computing"}
+MACRO {trets}  {"ACM Transactions on Reconfigurable Technology and Systems"}
+MACRO {tsas}  {"ACM Transactions on Spatial Algorithms and Systems"}
+MACRO {tsc}  {"ACM Transactions on Social Computing"}
+MACRO {tslp}  {"ACM Transactions on Speech and Language Processing"}
+MACRO {tweb}  {"ACM Transactions on the Web"}
+
+%%% Some traditional macros
+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 {jcss} {"Journal of Computer and System Sciences"}
+
+MACRO {scp} {"Science of Computer Programming"}
+
+MACRO {sicomp} {"SIAM Journal on Computing"}
+
+MACRO {toois} {"ACM Transactions on Office Information Systems"}
+
+MACRO {tcs} {"Theoretical Computer Science"}
+
+
+
+READ
+
+FUNCTION { sortify }
+{
+  purify$
+  "l" change.case$
+}
+
+FUNCTION { chop.word }
+{
+  's :=
+  'len :=
+  s #1 len substring$ =
+    { s len #1 + global.max$ substring$ }
+    's
+  if$
+}
+
+FUNCTION { sort.format.names }
+{
+  's :=
+  #1 'nameptr :=
+  ""
+  s num.names$ 'numnames :=
+  numnames 'namesleft :=
+    { namesleft #0 > }
+    { nameptr #1 >
+          { "   " * }
+         'skip$
+      if$
+      s nameptr "{vv{ } }{ll{ }}{  f{ }}{  jj{ }}" format.name$ 't :=
+      nameptr numnames = t "others" = and
+          { " et~al" * }
+          { t sortify * }
+      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.or.unknown
+    { key empty.or.unknown
+         { "to sort, need author or key in " cite$ * warning$
+           "" }
+         { key sortify }
+      if$
+    }
+    { author sort.format.names }
+  if$
+}
+
+FUNCTION { author.editor.sort }
+{
+  author empty.or.unknown
+    {
+      editor empty.or.unknown
+         {
+           key empty.or.unknown
+             { "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.organization.sort }
+{
+  % added - GNP. Stack editor or organization for sorting (from alpha.bst).
+  % Unlike alpha.bst, we need entire names, not abbreviations
+
+  editor empty.or.unknown
+    { organization empty.or.unknown
+        { key empty.or.unknown
+            { "to sort, need editor, organization, or key in " cite$ * warning$
+              ""
+            }
+            { key sortify }
+          if$
+        }
+        { organization sortify }
+      if$
+    }
+    { editor sort.format.names }
+  if$
+}
+
+FUNCTION { author.editor.organization.sort }
+{
+  % added - GNP. Stack author or organization for sorting (from alpha.bst).
+  % Unlike alpha.bst, we need entire names, not abbreviations
+
+  author empty.or.unknown
+    {
+      editor empty.or.unknown
+        { organization empty.or.unknown
+            { key empty.or.unknown
+                { "to sort, need author, editor, or key in " cite$ * warning$
+                ""
+                }
+                { key sortify }
+              if$
+            }
+            { organization sortify }
+          if$
+        }
+        { editor sort.format.names }
+      if$
+    }
+    { author sort.format.names }
+  if$
+}
+
+FUNCTION { presort }
+{
+  % Presort creates the bibentry's label via a call to calc.label, and then
+  % sorts the entries based on entry type. Chicago.bst adds support for
+  % including organizations as the sort key; the following is stolen from
+  % alpha.bst.
+
+  calc.label
+  basic.label.year
+  swap$
+  "    "
+  swap$
+  * *
+  "    "
+  *
+  sortify
+  year field.or.null purify$ #-1 #4 substring$ * % add year
+  "    "
+  *
+  type$ "book" =
+  type$ "inbook" =
+  or
+  type$ "article" =
+  or
+    'author.editor.sort
+    { type$ "proceedings" =
+      type$ "periodical" =
+      or
+        'editor.organization.sort
+        { type$ "manual" =
+            'author.editor.organization.sort
+            'author.sort
+          if$
+        }
+      if$
+    }
+  if$
+  #1 entry.max$ substring$        % added for newapa
+  'sort.label :=                  % added for newapa
+  sort.label                      % added for newapa
+  *
+  "    "
+  *
+  title field.or.null
+  sort.format.title
+  *
+  #1 entry.max$ substring$
+  'sort.key$ :=
+}
+
+
+
+ITERATE { presort }
+
+SORT             % by label, year, author/editor, title
+
+% From plainnat.bst
+STRINGS { longest.label }
+
+INTEGERS { longest.label.width number.label }
+
+FUNCTION {initialize.longest.label}
+{ "" 'longest.label :=
+  #0 int.to.chr$ 'last.label :=
+  "" 'next.extra :=
+  #0 'longest.label.width :=
+  #0 'last.extra.num :=
+  #0 'number.label :=
+}
+
+
+
+FUNCTION { initialize.extra.label.stuff }
+{ #0 int.to.chr$ 'last.label :=
+  "" 'next.extra :=
+  #0 'last.extra.num :=
+}
+
+FUNCTION { forward.pass }
+{
+  % Pass through all entries, comparing current entry to last one.
+  % Need to concatenate year to the stack (done by calc.label) to determine
+  % if two entries are the same (see presort)
+
+  last.label
+  calc.basic.label year field.or.null purify$ #-1 #4 substring$ * % add year
+  #1 entry.max$ substring$ =     % are they equal?
+     { last.extra.num #1 + 'last.extra.num :=
+       last.extra.num int.to.chr$ 'extra.label :=
+     }
+     { "a" chr.to.int$ 'last.extra.num :=
+       "" 'extra.label :=
+       calc.basic.label year field.or.null purify$ #-1 #4 substring$ * % add year
+       #1 entry.max$ substring$ 'last.label := % assign to last.label
+     }
+  if$
+  number.label #1 + 'number.label :=
+}
+
+FUNCTION { reverse.pass }
+{
+  next.extra "b" =
+    { "a" 'extra.label := }
+     'skip$
+  if$
+  label.year extra.label * 'sort.year :=
+  extra.label 'next.extra :=
+}
+
+EXECUTE {initialize.extra.label.stuff}
+EXECUTE {initialize.longest.label}
+
+
+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             % by sort.label, year, title --- giving final bib. order.
+
+FUNCTION { begin.bib }
+{
+  %% Set to #0 show 13-digit ISBN in preference to 10-digit ISBN.
+  %% Set to #1 to show both 10-digit and 13-digit ISBNs.
+  #1 'show-isbn-10-and-13 :=
+
+  "%%% -*-BibTeX-*-" writeln
+  "%%% Do NOT edit. File created by BibTeX with style" writeln
+  "%%% ACM-Reference-Format-Journals [18-Jan-2012]." writeln
+  "" writeln
+
+  preamble$ empty.or.unknown
+    'skip$
+    { preamble$ writeln }
+  if$
+  "\begin{thebibliography}{" number.label int.to.str$ * "}" * writeln
+  ""                                                                         writeln
+  "%%% ====================================================================" writeln
+  "%%% NOTE TO THE USER: you can override these defaults by providing"       writeln
+  "%%% customized versions of any of these macros before the \bibliography"  writeln
+  "%%% command.  Each of them MUST provide its own final punctuation,"       writeln
+  "%%% except for \shownote{}, \showDOI{}, and \showURL{}.  The latter two"  writeln
+  "%%% do not use final punctuation, in order to avoid confusing it with"    writeln
+  "%%% the Web address."                                                     writeln
+  "%%%"                                                                      writeln
+  "%%% To suppress output of a particular field, define its macro to expand" writeln
+  "%%% to an empty string, or better, \unskip, like this:"                   writeln
+  "%%%"                                                                      writeln
+  "%%% \newcommand{\showDOI}[1]{\unskip}   % LaTeX syntax"                   writeln
+  "%%%"                                                                      writeln
+  "%%% \def \showDOI #1{\unskip}           % plain TeX syntax"               writeln
+  "%%%"                                                                      writeln
+  "%%% ====================================================================" writeln
+  ""                                                                         writeln
+
+  %% ACM publications do not use CODEN, ISSN, and LCCN data, so their default
+  %% macro wrappers expand to \unskip, discarding their values and unwanted
+  %% space.
+  %%
+  %% For other publications, prior definitions like these may be useful:
+  %%
+  %%     Plain TeX:
+  %%         \def \showCODEN     #1{CODEN #1.}
+  %%         \def \showISSN      #1{ISSN #1.}
+  %%         \def \showLCCN      #1{LCCN #1.}
+  %%
+  %%     LaTeX:
+  %%         \newcommand{\showCODEN}[1]{CODEN #1.}
+  %%         \newcommand{\showISSN}[1]#1{ISSN #1.}
+  %%         \newcommand{\showLCCN}[1]{LCCN #1.}
+
+  "\ifx \showCODEN    \undefined \def \showCODEN     #1{\unskip}     \fi" writeln
+  "\ifx \showDOI      \undefined \def \showDOI       #1{#1}\fi" writeln
+  % ACM styles omit ISBNs, but they can be included by suitable definitions of
+  % \showISBNx and \showISBNxiii before the .bbl file is read
+  "\ifx \showISBNx    \undefined \def \showISBNx     #1{\unskip}     \fi" writeln
+  "\ifx \showISBNxiii \undefined \def \showISBNxiii  #1{\unskip}     \fi" writeln
+  "\ifx \showISSN     \undefined \def \showISSN      #1{\unskip}     \fi" writeln
+  "\ifx \showLCCN     \undefined \def \showLCCN      #1{\unskip}     \fi" writeln
+  "\ifx \shownote     \undefined \def \shownote      #1{#1}          \fi" writeln % NB: final period supplied by add.period$ above
+  "\ifx \showarticletitle \undefined \def \showarticletitle #1{#1}   \fi" writeln
+  "\ifx \showURL      \undefined \def \showURL       {\relax}        \fi" writeln
+  "% The following commands are used for tagged output and should be " writeln
+  "% invisible to TeX" writeln
+  "\providecommand\bibfield[2]{#2}" writeln
+  "\providecommand\bibinfo[2]{#2}" writeln
+  "\providecommand\natexlab[1]{#1}" writeln
+  "\providecommand\showeprint[2][]{arXiv:#2}" writeln
+}
+
+EXECUTE {begin.bib}
+
+EXECUTE {init.state.consts}
+
+ITERATE {call.type$}
+
+FUNCTION { end.bib }
+{
+  newline$
+  "\end{thebibliography}"
+  writeln
+}
+
+EXECUTE {end.bib}
diff --git a/ocl/docs/publications/OCL2022Library/OCLLibrarySupport.bib b/ocl/docs/publications/OCL2022Library/OCLLibrarySupport.bib
index fd3eef8..b9456b1 100644
--- a/ocl/docs/publications/OCL2022Library/OCLLibrarySupport.bib
+++ b/ocl/docs/publications/OCL2022Library/OCLLibrarySupport.bib
@@ -92,6 +92,15 @@
 doi = {10.1007/978-3-642-30982-3\_3}
 }
 
+@inproceedings{Lano2022,
+	author = {Lano, Kevin and Rahimi, Shekoufeh Kolahdouz},
+	title = {{OCL libraries for software specification and representation}},
+	booktitle = {22nd International Workshop on OCL and Textual Modeling (OCL 2022)},
+	address = {Montreal},
+	month = {October},
+	year = {2022},
+}
+
 @inproceedings{Mandel1999,
 author = {Mandel, Luis and Cengarle, María},
 year = {1999},
@@ -141,3 +150,12 @@
 	year = {2019},
 	note = {http://www.eclipse.org/modeling/mdt/ocl/docs/publications/\allowbreak OCL2019MapType/OCLMapType.pdf}
 }
+
+@inproceedings{Willink-Shadow,
+	author = {Edward Willink},
+	title = {{Shadow Objects}},
+	booktitle = {18th International Workshop on OCL and Textual Modeling (OCL 2016)},
+	address = {Copenhagen},
+	month = {October},
+	year = {2018},
+}
diff --git a/ocl/docs/publications/OCL2022Library/OCLLibrarySupport.pdf b/ocl/docs/publications/OCL2022Library/OCLLibrarySupport.pdf
index ec8b30f..192712b 100644
--- a/ocl/docs/publications/OCL2022Library/OCLLibrarySupport.pdf
+++ b/ocl/docs/publications/OCL2022Library/OCLLibrarySupport.pdf
Binary files differ
diff --git a/ocl/docs/publications/OCL2022Library/OCLLibrarySupport.tex b/ocl/docs/publications/OCL2022Library/OCLLibrarySupport.tex
index 2638cd6..4a04ac5 100644
--- a/ocl/docs/publications/OCL2022Library/OCLLibrarySupport.tex
+++ b/ocl/docs/publications/OCL2022Library/OCLLibrarySupport.tex
@@ -11,20 +11,13 @@
 %% values in them; it is your responsibility as an author to replace
 %% the commands and values with those provided to you when you
 %% complete the rights form.
-\setcopyright{acmcopyright}
 \copyrightyear{2022}
 \acmYear{2022}
-\acmDOI{XXXXXXX.XXXXXXX}
-
-%% These commands are for a PROCEEDINGS abstract or paper.
-\acmConference[OCL 2022]{Make sure to enter the correct
-  conference title from your rights confirmation emai}{October 23,
-  2022}{Montreal, Canada}
+\setcopyright{acmlicensed}\acmConference[MODELS '22 Companion]{ACM/IEEE 25th International Conference on Model Driven Engineering Languages and Systems}{October 23--28, 2022}{Montreal, QC, Canada}
+\acmBooktitle{ACM/IEEE 25th International Conference on Model Driven Engineering Languages and Systems (MODELS '22 Companion), October 23--28, 2022, Montreal, QC, Canada}
 \acmPrice{15.00}
-\acmISBN{978-1-4503-XXXX-X/18/06}
-
-%%\acmSubmissionID{123-A56-BU3}
-
+\acmDOI{10.1145/3550356.3561540}
+\acmISBN{978-1-4503-9467-3/22/10}
 %%
 %% For managing citations, it is recommended to use bibliography
 %% files in BibTeX format.
@@ -86,13 +79,13 @@
 %% The abstract is a short summary of the work to be presented in the
 %% article.
 \begin{abstract}
-  Libraries provide a powerful re-use capability allowing developers of one application to exploit the developments of others. Sadly, OCL has no first class library capability and attempts to use available capabilities have not led to any re-useable libraries. Problems include lack of support for imports, foreign language calls, object creation, maps and inadequate specification of static functionality. We combine previous and new resolutions prototyped in Eclipse OCL to make libraries feasible. 
+  Libraries provide a powerful re-use capability allowing developers of one application to exploit the developments of others. Sadly, OCL has no first class library capability and attempts to use available capabilities have not led to any re-usable libraries. Problems include lack of support for imports, foreign language calls, object creation, maps and inadequate specification of static features. We combine previous and new resolutions prototyped in Eclipse OCL to make libraries feasible. 
 \end{abstract}
 
 %%
 %% Keywords. The author(s) should pick words that accurately describe
 %% the work being presented. Separate the keywords with commas.
-\keywords{OCL, Library, Native Call, Code Generation, Optimization}
+\keywords{OCL, Library, Native Call, Code Generation, Static Feature}
 
 %%
 %% This command processes the author and affiliation and title
@@ -102,7 +95,7 @@
 \section{Introduction}\label{Introduction}
 Libraries provide a powerful mechanism for providing re-use. The extreme polymorphism of Java's Object and Collection classes and the consequent ease of use demonstrates how libraries can create a virtuous adoption cycle. In contrast, C++ was overtaken as its Standard Template Library arrived over ten years late and was compromised by a need to support bare arrays as collections. In further contrast, OCL has only a built-in library and few users.
   
-The obvious utility of libraries has prompted authors \cite{Baar2011},\cite{Cabot2012} to query where the OCL math library is. There is no answer.
+The obvious utility of libraries has prompted authors \cite{Baar2011},\cite{Cabot2012} to query where the OCL math library is. There is no answer. In this paper, we review the inadequate support for libraries and then  provide the technology to support them. We will find that the non-Object Oriented style of typical mathematical operations requires the semantics of static features in OCL to be resolved.
 
 OCL 2.0~\cite{OCL-2.0} attempts to formalize the intuitive obviousness of OCL 1.x with the aid of models. Unfortunately the formalization never progressed beyond the draft stage and so whenever we look too closely at OCL 2.0 we find incompleteness and inconsistency \cite{Willink2020}. The Abstract Syntax model omits critical classes such as \verb|VariableDeclaration|. There is no model of the library, just many well-intentioned partial specifications.
 
@@ -115,15 +108,15 @@
 \label{fig:oclstdlib}
 \end{figure}
 
-Figure~\ref{fig:oclstdlib} shows part of the declaration of the \verb|MapType| with \verb|K| and \verb|V| template parameters. An operation with a \verb|V2| template parameter and an iteration are also shown. The operation demonstrates the fairly strong modeling identifying that the templated argument and return may be null. Additionally the \verb|invalidating| keyword indicates that the result may be \verb|invalid|. The iteration declares its potentially null parameter followed by its body typed as a lambda-expression\footnote{The bodies of iterations are clearly lambda expressions although the OCL specification avoids that terminology.}. The return is a non-null map of potentially null keys and values.
+Figure~\ref{fig:oclstdlib} shows part of the declaration of the \verb|MapType| with \verb|K| and \verb|V| template parameters. An iteration with a \verb|V2| template parameter and an operation are also shown. The operation demonstrates the fairly strong modeling identifying that the templated argument and return may be null. Additionally the \verb|invalidating| keyword indicates that the result may be \verb|invalid|. The iteration declares its potentially null parameter followed by its body typed as a lambda-expression\footnote{The bodies of iterations are lambda expressions in all but name.}. The return is a non-null map of potentially null keys and values.
 
 The figure also demonstrates using \verb|java.util.Map| for the native implementation of the type, and using a custom helper class for each operation and iteration. The helper classes use polymorphism to dispatch \verb|OperationCallExp::referredOperation| rapidly.
 
 Once the OCL Standard Library was modeled, it was possible to separate the OCL Language from the OCL Standard Library allowing a user to provide an alternate or extended library implementation. It was also possible to define additional libraries. A few JUnit tests demonstrated the principle within Eclipse OCL, however an attempt to write a tutorial to show users how to exploit the potential of an additional library demonstrated that the implementation was not ready for prime time\footnote{https://bugs.eclipse.org/bugs/show\_bug.cgi?id=415146}.
 
-The tutorial was stuck on my to-do list until Kevin Lano suggested collaborating on a Masters project to provide an OCL library. Despite the funding falling through, I proceeded to investigate the library problems and long overdue solutions that are reported in this paper.
+%The tutorial was stuck on my to-do list until Kevin Lano suggested collaborating on a Masters project to provide an OCL library. Despite the funding falling through, I proceeded to investigate the library problems and long overdue solutions that are reported in this paper.
 
-We first review the ergonomic issues to be addressed in Section~\ref{Library Ergonomics} then in Section~\ref{Examples} we examine a few examples that motivate exploiting static features whose semantics we examine in Section~\ref{Static Semantics}. In Section~\ref{Status} we describe the status of this work and in Section~\ref{Further Work} we take static properties further. Then in Section~\ref{Related Work}, we look at other work, before concluding in Section~\ref{Conclusion}.
+We first review the ergonomic issues to be solved in Section~\ref{Library Ergonomics} then in Section~\ref{Examples} we examine a few examples that motivate exploiting static features whose semantics we examine in Section~\ref{Static Semantics}. In Section~\ref{Status} we describe the status of this work and in Section~\ref{Further Work} we take static properties further. Then in Section~\ref{Related Work}, we look at other work, before concluding in Section~\ref{Conclusion}.
   
 \section{Library Ergonomics}\label{Library Ergonomics}
  
@@ -138,11 +131,11 @@
 
 \subsection{Import}
  
-The OCL specification~\cite{OCL-2.4} defines a language that can usefully constrain models, but does not specify where the models come from. This provides considerable flexibility but has prevented vendors from providing a general solution. Each tool has its own proprietary solution to solving the relationship between the OCL programming and the models.
+The OCL specification~\cite{OCL-2.4} defines a language that can usefully constrain models, but does not specify where the models come from. This provides considerable flexibility but has prevented vendors from providing a general solution. Each tool has its own proprietary solution to solving the relationship between the OCL programming and the models with their metamodels.
 
 Complete OCL comes closer to being complete in so far as the specification defines a self-standing document with a grammar that can complement a model. However a practical implementation must either add some form of import statement to allow the Complete OCL document to reference its complemented models, or operate in a pre-loaded context with ready to-go models.
 
-A similar import statement or pre-loading will be needed to exploit a library of declarations. This should be just a variation of a proprietary facility that we do not need to address further here.
+A similar import statement or pre-loading will be needed to exploit a library of declarations. This should be just a variation of a proprietary facility that we do not need to address further here. Eclipse OCL supports an import such as:
 
 \begin{verbatim}
 import 'https://git.eclipse.org/r/plugins/gitiles
@@ -152,33 +145,31 @@
 
 \subsection{Declare}
 
-A Complete OCL document, a UML model or Eclipse OCL's Standard Library model provide adequate mechanisms for declaring many, but perhaps not all, declarations. A minimal \verb|maths.ocl| supporting just the \verb|tan| operation could be declared as\footnote{... denotes functionality that has been omitted in order to focus on a relevant issue.}
-:
+A Complete OCL document, a UML model or Eclipse OCL's Standard Library model provide adequate mechanisms for declaring many, but perhaps not all, declarations. A minimal \verb|maths.ocl| supporting just the \verb|tan| operation could be declared as\footnote{... denotes functionality that has been omitted in order to focus on a relevant issue.}:
 
 \begin{verbatim}
-	package maths
-	context Real
-	def: tan() : Real = ...
-	endpackage
+  package maths
+  context Real
+  def: tan() : Real = ...
+  endpackage
 \end{verbatim} 
 
-
 \subsection{Implement}
 
 OCL is probably Turing complete, see Section~\ref{Turing Complete}, so it is in principle possible to implement any library functionality in OCL and embed that implementation as the body of a Complete OCL declaration.
 
 However few users will be keen to transliterate existing implementations from their favorite language in order to use them within OCL. We therefore have a vicious circle whereby the lack of any OCL libraries imposes a significant barrier to development of any OCL libraries.
 
-Even if a good algorithm for \verb|tan| is available, there may be Intellectual Property issues that prevent its re-use. The transliteration must be tested for interesting corner cases.  Transliteration alone is not sufficient.
+Even if a good algorithm for \verb|tan| is available, there may be Intellectual Property issues that prevent its re-use. The transliteration must be tested for interesting corner cases. Transliteration alone is not sufficient.
 
 OCL needs a mechanism to enable re-use of an implementation already available in a foreign language.
 
 \subsection{Invoke}\label{Call}  
 
-If the imported library declarations integrate well with other OCL declarations, the existing call capabilities should be re-useable.
+If the imported library declarations integrate well with other OCL declarations, the existing call capabilities should be re-usable.
 
 \begin{verbatim}
-	2.5e1.tan()
+  2.5e1.tan()
 \end{verbatim} 
 
 However when we come to implement the library declaration we find that we have just moved the problem sideways; we still need a mechanism to invoke a foreign language implementation.
@@ -198,7 +189,7 @@
     _'http://org.my.spec/2022#MyPackage'::MyClass)
 \end{verbatim} 
 
-We can generalize this to exploit a Java String function that the OCL String type does not support: 
+We can generalize this to exploit a Java String function that the OCL String type does not support as: 
 
 \begin{verbatim}
 thisString.
@@ -219,41 +210,41 @@
 
 \subsection{Math.pow}
 
-Most languages support a functional call of \verb|tan| as \verb|tan(2.5e1)| or \verb|tan 2.5e1| rather than the Object-Oriented \verb|2.5e1.tan()| which can be supported by declaring a regular \verb|Real::tan()| operation. This OO style strange if we require \verb|2.pow(4)| rather than \verb|pow(2, 4)|.
+Most languages support a functional call of \verb|tan| as \verb|tan(2.5e1)| or \verb|tan 2.5e1| rather than the Object-Oriented \verb|2.5e1.tan()| which can be supported by declaring a regular \verb|Real::tan()| operation. This OO style is strange if we want \verb|pow(2, 4)| rather than \verb|2.pow(4)|.
 
-This OO style is not actually necessary since OCL 2.2~\cite{OCL-2.2} added support for a \verb|static| keyword when declaring operations and properties.
+An OO style is not actually necessary since OCL 2.2~\cite{OCL-2.2} added support for a \verb|static| keyword when declaring operations and properties.
 
 We may therefore provide a minimal \verb|maths.ocl| as
 
 \begin{verbatim}
-	package maths
-	context Real
-	static def: pow(mant : Real, expt : Real) : Real
-	    = _'java:java.lang.Math.pow'(mant, expt)
-	endpackage
+  package maths
+  context Real
+  static def: pow(mant : Real, expt : Real) : Real
+    = _'java:java.lang.Math.pow'(mant, expt)
+  endpackage
 \end{verbatim} 
 
 This can support the call from regular OCL as
 
 \begin{verbatim}
-	... maths::Real::pow(2, 4) ...
+  ... maths::Real::pow(2, 4) ...
 \end{verbatim} 
 
-If the proprietary import mechanism exposes the contents of the \verb|maths| package, the \verb|maths::| qualification could be omitted giving a nearly optimal exposition for the call.
+If the proprietary import mechanism exposes the contents of the \verb|maths| package, the \verb|maths::| qualification and perhaps even the \verb|Real::| qualifications can be omitted giving a more optimal exposition for the call.
 
-While OCL 2.2 added the \verb|static| keyword to the grammar, it is hard to characterize the change as more than a me-too catchup to align with UML static features. Very little run-time semantics was provided for OCL, and there is little to infer from UML~\cite{UML-2.5.1}. Section 7.5.10 of the OCL specification provides an example that we shall see in Section~\ref{UniqueId} is not fully implementable in OCL. Whether and how \verb|static| is supported is down to the enthusiasm of the OCL tooling implementer.
+While OCL 2.2 added the \verb|static| keyword to the grammar, it is hard to characterize the change as more than a me-too catch-up to align with UML static features. Very little run-time semantics was provided for OCL, and there is little to infer from UML~\cite{UML-2.5.1}. Section 7.5.10 of the OCL specification provides an example that we shall see in Section~\ref{UniqueId} is not fully implementable in OCL\footnote{Diligent readers of the OCL specification may find a StaticValue class that is nothing to do with the static declaration of a feature. Rather it is a confusing throwback to when UML 1.x referred to the embedded DataType-typed attribute slots of an instance as its static structure.}. Whether and how \verb|static| is supported is down to the enthusiasm of the OCL tooling implementer.
 
 It may be noted that Ecore~\cite{Eclipse-EMF} has no support for static features, so that if a UML model with static feature is converted using UML2Ecore, the \verb|static| keyword is ignored.
 
-The requirement for possibly unsupported static functionality may be avoided by using the OO style:
+Using an OO style:
 
 \begin{verbatim}
     ... 2.pow(4) ...
 \end{verbatim} 
 
-but the underlying Java function is static so we will have to support foreign static calls anyway.
+may workaround the absence of support for static in the grammar, but the underlying Java function is static so internal support for foreign static calls is unavoidable.
 
-Better to ensure that OCL tooling supports static features. For static operations intuitive common sense seems ok. For static properties we need to clarify the semantics in respect of when a `new' static instance is created and initialized. See Section~\ref{Static Semantics}.
+For the semantics of static operations, intuitive common sense seems adequate. For static properties we need to clarify the semantics in respect of when a `new' static instance is created and initialized. See Section~\ref{Static Semantics}.
 
 Once we have a foreign call syntax, the user has a choice. The foreign calls can be used directly avoiding any need for a library at the expense of some clumsiness in the call expressions. Alternatively the foreign calls may be hidden within a library that provides friendly declarations that delegate to the foreign call.
 
@@ -263,23 +254,23 @@
 
 The foreign call delegation for \verb|pow| can be appropriate when the types are simple and when the implementation is too complicated to re-implement.
 
-But consider a Complex class, which strangely Java does not provide. But even if there was a Java implementation, we might choose to re-implement since Complex is rather simple. Except that we cannot, since, in general, addition of two complex numbers creates a new complex number. OCL provides no \verb|new| capability since construction of a new object creates a side effect in the memory system. This can be seen by considering how a \verb|new| capability might work
+But consider a Complex class, which strangely Java does not provide. Even if there was a Java implementation, we might choose to re-implement since Complex is rather simple. Except that we cannot, since, in general, addition of two complex numbers creates a new complex number. OCL provides no \verb|new| capability since construction of a new object creates a side effect in the memory system. This can be seen by considering how a \verb|new| capability might work:
 
 \begin{verbatim}
 new Complex{real=2,imag=3} = new Complex{real=2,imag=3}
 \end{verbatim} 
 
-Obviously two same-valued complex numbers should be equal; this is the UML DataType semantics. But complex is a Class and so each call to \verb|new| should create a new object; they should therefore be different in accordance with UML Class semantics. (Java provides alternative \verb|=| and \verb|equals| facilities that allows a free/confusing choice of DataType or Class semantics.)
+Obviously two same-valued complex numbers should be equal; this is the UML DataType semantics. But if Complex is a Class, each call to \verb|new| creates a new instance; they should therefore be different in accordance with UML Class semantics. (Java provides alternative \verb|=| and \verb|equals| facilities that allows a free and confusing choice of DataType or Class semantics.)
 
-This \verb|new| problem was discussed at the Aachen workshop~\cite{OCL-Aachen} where the helpful term `shadow' object was coined for a solution.
+The problem with \verb|new| was discussed at the Aachen workshop~\cite{OCL-Aachen} where the helpful term `shadow' object was coined for the solution~\cite{Willink-Shadow}.
 
-In principle, let all possible instances of all possible classes have a permanent shadow existence, so that whenever the Tuple syntax is used to `create' an object the appropriate shadow instance is returned avoiding the side effect. Rewriting our example
+In principle, let all possible instances of all possible classes have a permanent shadow existence, so that whenever the Tuple syntax is used to `create' an object, the appropriate shadow instance is returned avoiding the side effect. Rewriting our example:
 
 \begin{verbatim}
 Complex{real=2, imag=3} = Complex{real=2, imag=3}
 \end{verbatim} 
 
-the two creations each obtain the same shadow object and so the equality is satisfied. 
+the two creations each return the same immutable shadow object and so the equality is satisfied. 
 
 In practice, creation of all possible instances of all possible classes will run out of time and memory long before any useful computation can be performed. Each required shadow instance must therefore be created lazily. 
 
@@ -302,8 +293,8 @@
 
 Section 7.5.10 of the OCL specification provides half an example demonstrating how the static \verb|Employee::uniqueID| operation can be used to provide a unique ID for each \verb|Employee|.
 \begin{verbatim}
-context Employee::id : String
-  init: Employee::uniqueID()
+  context Employee::id : String
+    init: Employee::uniqueID()
 \end{verbatim} 
 
 \paragraph{Lazy (Java) Solution}
@@ -315,9 +306,9 @@
 }
 \end{verbatim} 
 
-\verb|Employee::uniqueID| can easily be realized in Java by defining a static counter for the IDs and incrementing the counter for each invocation.
+As shown above, \verb|Employee::uniqueID| can easily be realized in Java by defining a static counter for the IDs and incrementing the counter for each invocation.
 
-An alternative eager approach in which all IDs are allocated together is awkward since it requires access to all instances that may need IDs and since IDs cannot be eagerly allocated for instances that have yet to be created.
+An alternative eager approach in which all IDs are allocated together is awkward since it requires access to all instances that may need IDs. This includes those instances that are yet to be created.
 
 \paragraph{Eager (OCL) Solution}
 
@@ -330,17 +321,17 @@
   init: Employee::uniqueID()
 \end{verbatim} 
 
-The lazy approach cannot be written in OCL since the updates to the static counter constitute a side effect that is illegal in OCL. The eager approach is possible since \verb|allInstances()| can find the instances and since the lack of side effects guarantees that no later creation of instances can occur.
+The lazy approach cannot be written in OCL since the updates to the static counter constitute a side effect that is illegal in OCL. The eager approach above is possible since \verb|allInstances()| can find the instances and since the lack of side effects guarantees that no later creation of instances can occur.
 
 The static \verb|Employee::insts| property is initialized once with a sequence of all \verb|Employee| instances. Thereafter each access of the \verb|Employee::uniqueID()| operation is able to compute a distinctive \verb|self|-dependent value by searching for the index of \verb|self| in \verb|Employee::insts|. The derived \verb|Employee::id()| property delegates to \verb|Employee::uniqueID()| for the first access. Subsequent accesses should benefit from a cache.
 
 It seems unreasonable that the simple efficient lazy approach cannot be written in OCL. The semantics of static OCL features is unspecified, so there are opportunities for a resolution. Perhaps the initializer for a static property should be re-evaluated for each access. Alternatively the semantics could be refined so that the \verb|init| initializes on the first access and a \verb|der| updates on subsequent accesses. This would allow the count to evolve, but an unstable static property seems deeply suspect.
 
-It also seems unreasonable that further instances cannot be created after some unique IDs are allocated. But for pure OCL, this is not a problem since OCL has no ability to assign or mutate; the multi-valued counter cannot exist. Once OCL is embedded, perhaps in QVTo~\cite{QVT-1.3}, the imperative capabilities allow successive assigns and so the lazy approach can work. Alternatively when embedded in a strongly declarative context such as QVTr, all instances exist before the `atomic' transformation completes and so it is just a scheduling challenge for the tooling to assign the IDs to the output in a timely fashion that satisfies the write/read dependencies.
+It also seems unreasonable that further instances cannot be created after some unique IDs are allocated. But for pure OCL, this is not a problem since OCL has no ability to assign or mutate; the counter with its incrementing value cannot exist. Once OCL is embedded, perhaps in QVTo~\cite{QVT-1.3}, the imperative capabilities allow successive assigns and so the lazy approach can work. Alternatively when embedded in a strongly declarative context such as QVTr, all instances exist before the `atomic' transformation completes and so it is just a scheduling challenge for the tooling to assign the IDs to the output in a timely fashion that satisfies the write/read dependencies. For pragmatic OCL enriching a model, it is the modeling environment's responsibility to reset all caches before each execution of some OCL-defined functionality; \verb|allInstances()| must be `recomputed' each time the modeling environment makes a significant change to the system state. 
 
 %To complete the OCL specification example, we just need to allocate a distinct ID to each element of an \verb|allInstances()|. We cannot do this within uniqueID since there is no ability for a first call to populate the results for other calls. The `global' \verb|allInstances()| algorithm must be computed and cached `globally' and so must use a static cache populated before OCL execution starts. The individual results are readily accessed from the static \verb|instances| cache. 
 
-Unfortunately the \verb|indexOf()| in our solution contributes to a quadratic implementation cost. We can linearize by using a Map~\cite{Willink-Map}.
+Unfortunately the \verb|indexOf()| in our solution contributes to a quadratic implementation cost. We can linearize the cost by using a Map~\cite{Willink-Map}.
 
 \begin{verbatim}
 static context Employee::inst2id : Map(Employee,String)
@@ -353,9 +344,9 @@
   init: Employee::uniqueID()
 \end{verbatim} 
 
-At start up, or first access, the \verb|Employee::inst2id| initialization computes the sequence of \verb|allInstances()| to the \verb|insts| let-variable. The  \verb|collectBy()| collection-to-map iteration then populates the map result from an iteration over all the instances. The iteration declares, but does not directly use, the primary element iterator \verb|e|. It also declares the co-iterator \verb|i|,  which provides the index of the primary iterator in the ordered source collection. It provides the same value as \verb|insts->indexOf(e)| without the need to re-compute what the iteration evaluation already `knows'. Each map entry is keyed by the iteration element \verb|e| and maps to the iteration body \verb|i.toString()|.
+At start up, or first access, the \verb|Employee::inst2id| initialization computes the sequence of \verb|allInstances()| to the \verb|insts| let-variable. The  \verb|collectBy()| collection-to-map iteration then populates the map result from an iteration over all the instances. The iteration declares, but does not directly use, the primary element iterator \verb|e|. It also declares the co-iterator \verb|i|,  which provides the index of the primary iterator in the ordered source collection. The co-iterator provides the same value as \verb|insts->indexOf(e)| without the need to re-compute what the iteration evaluation already `knows'. Each map entry is keyed by the iteration element \verb|e| and maps to the iteration body \verb|i.toString()|.
 
-We can see that provision of globally coherent static facilities is much easier when each per-element property can be cached as an entry in a global Map.
+We can see that provision of globally coherent static facilities is much easier when each per-element property can be cached as an entry in a static global Map.
 
 \section{Feature Semantics}\label{Static Semantics}
 
@@ -369,15 +360,15 @@
 
 \subsection{Regular Features}
 
-Regular features are provided and maintained by the modeling environment to which the OCL contributes. When objects are created/deleted, or properties initialized/updated is nothing to do with OCL. The modeling environment may implement and refresh caches as appropriate.
+Regular features are provided and maintained by the modeling environment to which the OCL contributes. When objects are created/deleted or properties initialized/updated is nothing to do with OCL. The modeling environment may implement and must refresh caches as appropriate.
 
-The modeling environment may invoke an OCL expression when initializing a property. How an OCL expression accesses a property is unspecified. But obviously it must route the access through the modeling environment to ensure that any access protocols are observed.
+The modeling environment may invoke an OCL expression when initializing a property. How an OCL expression evaluation accesses a slot is unspecified. But obviously it must route the access through the modeling environment to ensure that any access protocols are observed.
 
-A modeling environment may similarly invoke an OCL expression when evaluating an operation. How an OCL expression may invoke an operation is also unspecified. Logically it should do so via the modeling environment, which would allow the modeling environment to implement a virtual dispatch policy that is not specified by OCL\footnote{For UML, the lack of a virtual dispatch specification is worked around by defining all the overloads as redefinitions.}. However operations are modeled using an \verb|ExpressionInOCL| to provide bindable parameters so there is a clear intent that OCL should be able to invoke at least OCL operations directly. Eclipse OCL does this and applies a Java-like virtual dispatch.
+A modeling environment may similarly invoke an OCL expression when evaluating an operation. How an OCL expression may invoke an operation is also unspecified. Logically it should do so via the modeling environment, which would allow the modeling environment to implement the virtual dispatch policy that is not specified by OCL\footnote{For UML, the lack of a virtual dispatch specification is worked around by defining all the overrides as redefinitions.}. However operations are modeled using an \verb|ExpressionInOCL| to provide bindable parameters so there is a clear intent that OCL should be able to invoke at least OCL operations directly. Eclipse OCL does this and applies a Java-like virtual dispatch.
 
 \subsection{Static Regular Features}
 
-For regular features, the \verb|static| keyword in OCL just echoes the corresponding declaration in UML to ensure that a Complete OCL complement complements the correct feature. (Ecore does not support static features.)
+For regular features, the \verb|static| keyword in OCL may just echo the corresponding declaration in UML to ensure that a Complete OCL complement complements the correct feature. (Ecore does not support static features.)
 
 With the modeling environment responsible for providing and maintaining the static features, the modeling environment is also responsible for their usage.
 
@@ -385,20 +376,20 @@
 
 \subsection{Additional Features}
 
-A Complete OCL document may complement pre-existing operations and properties by defining missing bodies and initializers. It may also extend pre-existing classes with additional operations and properties. These additions are specified to behave as regular features. (This is necessary to avoid new forms of \verb|PropertyCallExp| and \verb|OperationCallExp| in the Abstract Syntax, but with the additional features not actually part of a regular model, it is unclear where the target of a \verb|PropertyCallExp.referredProperty| may be found.)
+A Complete OCL document may complement pre-existing operations and properties by defining missing bodies and initializers. It may also extend pre-existing classes with additional operations and properties. These additions are specified to behave as regular features. This is necessary to avoid new forms of \verb|PropertyCallExp| and \verb|OperationCallExp| in the Abstract Syntax, but with the additional features not actually part of a regular model, it is unclear where the target of a \verb|PropertyCallExp.referredProperty| may be found.
 
-It is not clear that the modeling environment is aware of the additional features, so it is unclear whether additional properties are lazily or eagerly initialized. There can be no doubt that the additional operations are only invokable from OCL expressions within the transitive closure of Complete OCL documents that import the additional feature definition. Whether caches should be used is neither specified nor configurable.
+It is not clear if the modeling environment is aware of the additional features, so it is unclear whether additional properties are lazily or eagerly initialized. There is no doubt that the additional operations are only invokable from OCL expressions within the transitive closure of Complete OCL documents that import the additional feature definition. Whether caches should be used is neither specified nor configurable.
 
 \subsection{Static Additional Features}
 
-OCL provides no mechanism to update a property value, so an additional static property is almost useless. It can only be a constant since nothing is able to change it. It cannot contribute useful system state.
+OCL provides no mechanism to update a property value, so an additional static property is almost useless. It can only be a constant since nothing is able to change it. It cannot contribute useful system state. However the good practice of localizing magic constant values behind a symbolic name can be supported:
 
 \begin{verbatim}
 	context Real
 	static def PI : Real = 3.14159265359
 \end{verbatim} 
 
-A static additional operation is also rather boring. It differs from a non-static additional operation by requiring no access to a \verb|self| context, and no need to perform a virtual dispatch of overloads.
+A static additional operation is also rather boring. It differs from a non-static additional operation by requiring no access to a \verb|self| context, and no need to perform a virtual dispatch of overloads. Although boring, we have seen in Section~\ref{Examples} that static operations avoid the need for OO-style.
 
 \subsection{Summary}
 
@@ -487,7 +478,7 @@
 operation lazyAt(key: K, init: Lambda K() : V[?]) : V[?]
 \end{verbatim} 
 
-If the map already contains an entry for \verb|key|, the corresponding value is returned just like \verb|Map::at(key)|. If there is no entry, one is created using the \verb|init| lambda expression to define the value for the new key.
+If the map already contains an entry for \verb|key|, the corresponding value is returned just like \verb|Map::at(key)|. If there is no entry, one is created using the \verb|init| lambda expression to define the value for the new key. The lazy OCL solution could then be:
 
 \begin{verbatim}
 static context Employee::inst2id : Map(Employee,String)
@@ -497,13 +488,13 @@
                         inst2id->size().toString())
 \end{verbatim} 
 
-The \verb|Employee::inst2id| is initially empty, but each access to \verb|Employee::id| uses \verb|lazyAt| to provide a distinct value.
+The \verb|Employee::inst2id| is initially empty, and each access to \verb|Employee::id| uses \verb|lazyAt| to provide a distinct value.
 
-But \verb|Employee::inst2id->size()| can be accessed from anywhere, with unstable results depending upon \verb|Employee::id| access to occurrence. There is an observable side effect. Not OCL.
+\verb|Employee::inst2id->size()| can be accessed from anywhere, with unstable results depending upon \verb|Employee::id| access to occurrence. There is therefore an observable side effect. This is not OCL.
 
 \subsection{Mutable Statics}\label{Mutable Statics}
 
-Implementing the incrementing counter requires an ability to assign diverse values to a variable. This is possible in OCL, but only for the specific case of the result/accumulator of an \verb|iterate| iteration.
+Implementing the incrementing counter requires an ability to assign diverse values to a variable. This is possible in OCL, but only for the specific case of the result/accumulator of an \verb|iterate| iteration:
 
 \begin{verbatim}
 myList->iterate(e; acc = '' | acc + ' ' + e.toString())
@@ -511,9 +502,9 @@
 
 The multiple assignments to \verb|acc| do not create a side-effect since the \verb|acc| is private to the \verb|iterate| and only accessible on a per-iterator basis in the body. The prevailing state of \verb|acc| is not arbitrarily visible so the changes are not visible. \verb|acc| is not part of the observable side-effect-free system state.
 
-The example above gives a consistent result, for an ordered source, but could give diverse results for if the source is a set. This is not a side effect; it is a lack of determinism for which \cite{Willink2018} provides solutions.
+The example above gives a consistent result, for an ordered source, but could give diverse results if the source is a set. This is not a side effect; it is a lack of determinism for which \cite{Willink2018} provides solutions.
 
-If we could emulate each step of the \verb|iterate| independently so that we re-assign to our unique counter rather than \verb|acc|, we could discount the unique counter from the observable system state and similarly discount inconsistent step sequencing as a lack of determinism.
+If we could somehow generalize \verb|iterate| to make each step independent, we could re-assign to our unique counter rather than \verb|acc|, discount the unique counter from the observable system state and similarly discount inconsistent step sequencing as a lack of determinism.
 
 There are other mechanisms of assignment in OCL
 \begin{itemize}
@@ -521,9 +512,9 @@
 	\item property / part initializer
 	\item iterator initializer
 \end{itemize}
-but each is a single assignment. The assignment that occurs when for instance a new let-variable is created within a loop is not a re-assignment. Can any be the basis of a re-assignment?
+but each is a single assignment. The assignment that occurs, when for instance a new let-variable is created within a loop, is not a re-assignment. Can any of these mechanisms be the basis of a re-assignment?
 
-It was noted in Section~\ref{Static Semantics} that the semantics of statics are poorly specified, so we could be more imaginative and allow private static parts or properties to be changed by constructors.
+It was noted in Section~\ref{Static Semantics} that the semantics of statics are poorly specified, so we could be more imaginative and allow private static parts or properties to be changed by constructors as in the following lazy OCL solution:
 
 \begin{verbatim}
 static context Employee::initTuple : Tuple(id : String) 
@@ -576,15 +567,15 @@
 
 A foreign feature call was introduced in Section~\ref{Call} enabling OCL expressions to exploit functionality already available in foreign languages. In practice re-use of Java operations is very desirable. However evaluation of an OCL expression must be side-effect free and so any invocation of a Java operation such as \verb|List.add()| has a side-effect that may invalidate the use of OCL.
 
-Introduction of a foreign call is therefore a dangerous compromise between utility and validity. Can the danger be mitigated?
+Introduction of a foreign language call is therefore a dangerous compromise between utility and validity. Can the danger be mitigated?
 
-Compile-time analysis of the invoked functionality will not generally be possible since Java has too many side-effecting mechanisms.
+Compile-time analysis of the invoked functionality will not generally be possible since Java has too many side-effecting mechanisms and too many deep overload alternatives.
 
-At run-time, comparison of the total system state before and after a suspect foreign call is technically possible, but could be unrealistically expensive. Comparison of a hash of the total system state avoids a memory cost expense but remains unrealistic in terms of execution time.
+At run-time, comparison of the total system state before and after a suspect foreign call is technically possible, but could be unrealistically expensive. Less expensive in memory, but not time, could be a comparison of a hash of the total system state.
 
 A less ambitious comparison of shallow rather than transitive state could be feasible to catch obviously unsuitable operations such as \verb|List.add()|. A database of known bad operations could be gradually built-up, but progress would be slow since new entries only appear after a programming violation.
 
-Realistically, observing the no-side-effect rule must be the programmer's responsibility. This is of course already a programmer responsibility when configuring the \verb|Operation::isQuery| property in a UML model.
+Realistically, observing the no-side-effect rule must be the programmer's responsibility. Configuring the \verb|Operation::isQuery| property in a UML model is of course already a programmer responsibility.
 
 \section{Related Work}\label{Related Work}
 
@@ -594,6 +585,8 @@
 
 Cabot and Gogolla~\cite{Cabot2012} observe that the specified OCL Standard Library is too large for new users, but inadequate for more experienced users. They identify the provision of OCL libraries as a Research Agenda item. 
 
+Lano~\cite{Lano2022} enumerates at least eight different OCL libraries many of which require an imperative extension to OCL.
+
 Willink~\cite{Willink2011} introduces a model, grammar and editor for the OCL Standard Library, but as noted in Section~\ref{Introduction} this has not matured sufficiently to support custom libraries. 
 
 At the 2016 OCL workshop, a lightning talk by Cabot and Gogolla called for a repository of OCL benchmarks, which could no doubt also accommodate OCL libraries.
@@ -605,18 +598,18 @@
 An unbreakable iteration that computes some function \verb|f(e, acc)| at each step:
 
 \begin{verbatim}
-	...iterate(e; acc : Acc = ... | f(e, acc)) 
+  ...iterate(e; acc : Acc = ... | f(e, acc)) 
 \end{verbatim} 
 
-may be rewritten with a Tuple to be breakable.
+may be rewritten with a Tuple to be breakable:
 
 \begin{verbatim}
-...iterate(e; acc2 = Tuple{
-                       break : Boolean = false,
-                       acc : Acc = ...
-                     }
-    | if break then acc2
-      else Tuple{
+  ...iterate(e; acc2 = Tuple{
+                           break : Boolean = false,
+                           acc : Acc = ...
+                       }
+      | if break then acc2
+        else Tuple{
              break = ... ,
              acc = f(e, acc)
            }
@@ -624,19 +617,19 @@
     ) 
 \end{verbatim} 
 
-The data flow associated with the \verb|break| part is very simple; initially false, unchanging once true, never reset to false. Tooling can easily recognize this to terminate promptly.
+The data flow associated with the \verb|break| part is very simple; initially false, unchanging once true, never reset to false. Tooling can easily recognize this to terminate promptly. Perhaps OCL should have a \verb|break| value that may be returned during an ordered iteration to abandon the current and all future steps.
 
-A forever loop is awkward in OCL 2.0, but it can be achieved by a function \verb|f()| that recurses to collect the value of \verb|g()| for each loop element. 
+A forever loop is awkward in OCL 2.0, but it can be achieved by a function \verb|f()| that recurses to collect the value of \verb|g()| for each loop element: 
 
 \begin{verbatim}
-def: f(x : Integer, r : Set(Result)) : Set(Result)
-= f(x+1, r->including(g(x)))
+  def: f(x : Integer, r : Set(Result)) : Set(Result)
+  = f(x+1, r->including(g(x)))
 \end{verbatim} 
 
 This will obviously run out of stack in a naive implementation. As of OCL 2.3~\cite{OCL-2.3} there is a \verb|closure| iteration with which we can write a infinite loop.  
 
 \begin{verbatim}
-	1->closure(e | e+1)
+  1->closure(e | e+1)
 \end{verbatim} 
 
 The closure can be broken after computing something useful by:
@@ -650,12 +643,12 @@
 
 \section{Conclusion}\label{Conclusion}
 
-We have identified the inadequacy of the OCL specification as the primary impediment to provision of OCL libraries. Once we resolve the problems, we find that many facilities not clearly available in OCL 2.4 are necessary to make a library implementation possible.
+We have identified the inadequacy of the OCL specification as the primary impediment to provision of OCL libraries. In resolving the problems, we find that many facilities not clearly available in OCL 2.4 are necessary to make a library implementation possible.
 
 \begin{itemize}
 	\item An import capability loads the library declarations.
 	\item Static features facilitate typical non-OO usage such pow(2,4).
-	\item Foreign operation calls allow direct re-use of Java.
+	\item Foreign operation calls allow direct re-use of e.g. Java.
 	\item Shadow objects allow operations to return `new' objects.
 	\item Maps facilitate coherent all-instances functionality.
 	\item Co-iterators eliminate gratuitous re-calculation.
@@ -665,6 +658,8 @@
 	\item Mutable static parts support a typical counter idiom.
 \end{itemize}
 
+The introduction of foreign feature calls and the consideration of static features is new to this paper. Other facilities have been presented before, but their integration to make a custom library feasible is again new to this paper.
+
 %%
 %% The next two lines define the bibliography style to be used, and
 %% the bibliography file.