Modul:mkomtbllin

Dari Wiktionary bahasa Indonesia, kamus bebas
Loncat ke navigasi Loncat ke pencarian

Dokumentasi untuk modul ini dapat dibuat di Modul:mkomtbllin/doc

--[===[

MODULE "MKOMTBLLIN" (kompleta tabelo kun lingvoj)

"eo.wiktionary.org/wiki/Modulo:mkomtbllin" <!--2019-May-21-->
"id.wiktionary.org/wiki/Modul:mkomtbllin"

Purpose: brews a (huge) complete table with all supported languages

Utilo: generas (egan) kompletan tabelon kun cxiuj subtenataj lingvoj

Manfaat: membuat tabel lengkap (dan sangat besar) dengan semua
         bahasa yang didukung

Syfte: skapar en (gigantisk) tabell med alla spraak som stoeds

Used by templates / Uzata far sxablonoj /
Digunakan oleh templat / Anvaent av mallar:
- "montablng" (EO) / "mpltabbah" (ID) (called with param "komp", in
  turn only used this way by pagxo "Aldono:Listo kun lingvoj" /
  halaman "Lampiran:Daftar bahasa")

Required submodules / Bezonataj submoduloj / Submodul yang diperlukan:
- "mtmplloaddata" in turn requiring template "tbllingvoj" (EO)
  or "tblbahasa" (ID)
- "mpiksubstrind"

Incoming: - 1...3 parameters
            - anonymous obligatory parameter
              - string with 4 char:s
                - "d01" show appendix page ("0" do not show | "1" show)
                - "d06" kapkat ("0" hide co | "1" show nochk | "2" show check)
                - "d07" vorkat ("0" hide co | "1" show nochk | "2" show check)
                - "d08" index  ("0" hide co | "1" show nochk | "2" show check)
            - anonymous optional parameter
              - brew and show summary on success (binary digit "0" or "1")
            - anonymous optional parameter
              - string with 2 decimal digits "02"..."98" reducing probability
                to call expensive parser functions, default is 1 ie 100%

Returned: - one huge string

This module is unbreakable (when called with correct module name
and function name). Every imaginable input from the caller and
from the imported module "mtmplloaddata" will output either a useful
result or at least the string "Grava eraro".

Cxi tiu modulo estas nerompebla (kiam vokita kun gxustaj nomo de modulo
kaj nomo de funkcio). Cxiu imagebla enigo de la vokanto kaj
de la importata modulo "mtmplloaddata" eldonos aux utilan
rezulton aux almenaux signocxenon "Grava eraro".

Column numbering in the source table:
- numbering starts from ZERO
- "cy" does not count (it has theoretically index "-1")
- note that there is no comma between "cy" and "c0"
- "mpiktbllki" with special input value "+" returns the complete table line
  including the y-index word "cy", this means that unless the "cy" part is
  trimmed off, index ZERO fed into "mpiksubstrind" will return both "cy"
  and "c0", thus the indexes used by "mpiksubstrind" will NOT be OFF-by-ONE

Structure of a row in the source table with 1+10 columns:
- cy : y-index word (2 or 3 digits)
- c0 : name of the language in the site language
       - EO: usually AJ lowercase, alternatively SB uppercase begin
       - ID: without "bahasa " and begins with uppercase letter
- c1 : name of the language in the language itself (may be rl-enclosed)
- c2 : constructed and antique status (digit "0"..."3")
- c3 : ISO 639-1:2002 2-letter code
- c4 : ISO 639-3:2007 3-letter code
- c5 : wiki access code (usually same as "cy" but may be different
       and longer, for example "zh-min-nan", up to 10 char:s)
- c6 : wiki availability code (2 digits "0"..."2" ie "00"..."22")
- c7 : name of ipedia article, base principle usually
       followed (there are some exceptions):
       - EO: core word usually AJ uppercase begin
             followed by " lingvo", no "la" article
       - ID: prefixed by "Bahasa " and core word begins with uppercase letter
- c8 : category with our site language ("eo" or "id") in other tionary
       (with category prefix, but without language prefix,
       without "]]" or other nonsense, may be rl-enclosed)
- c9 : amount of pages in that category, apo:s ("16'384") are
       tolerable (this cannot be peeked automatically)
Note that "cy" and "c0" are ultimately obligatory, the remaining
ones are only desirable.

Overall structure of the generated page:
- top either fatal warning block or tiny block, both with purge link
- huge destination table (not if fatal error)
- summary block (without purge link) (may be omitted in some cases)
- bottom either fatal warning block or tiny block, both with purge link

Structure of a row in the desination table with 13 columns:
- d00 : - index (in brackets, not bold)
        - space
        - language access code (bold) (literally peeked from "cy"
          y-index word in the source table)
        # adjust background for "eo" only
- d01 : - name of the language in the site language with link to the
          lemma page (name literally peeked from "c0" in the source table,
          must be available and valid, link augmented according to
          control string "constrd01lem")
        - EOL (if link to appendix page below shown)
        - link to the appendix page (constructed from constant string
          "constrapxp" (appendix namespace prefix with ":") and "c0"
          augmented by "lfpresufkap" according to control string
          "constrd01d08") named via "constrd01qal" as translation of
          the term "(appendix page)" controlled by "booaldsow"
- d02 : - name of the language in the language itself
          (literally peeked from "c1" in the source table)
- d03 : - constructed and antique status (expanded from digit "0"..."3"
          peeked from "c2" in the source table)
        # adjust background to greenish or grey if applicable
- d04 : - "ISO 639-1:2002" 2-letter language code
          (literally peeked from "c3" in the source table)
- d05 : - "ISO 639-3:2007" 3-letter language code
          (literally peeked from "c4" in the source table)
- d06 : - link to the "kap" category in own tionary with all words in
          the language (constructed from constant string "constrkatp"
          (category namespace prefix with ":") and "c0" augmented by
          "lfpresufkap" according to control string "constrd06km")
        - EOL (if complaint below exists)
        - complaint about not existing if applicable
        - EOL (in any case)
        - amount of pages (queried) or "??" if querying does not work
        # adjust background to redish if the category does not exist
        ! depends from variables "bookapsow" and "bookapexp" and
          includes expensive querying (2), column can be completely hidden
- d07 : - link to the "vor" category in own tionary with all dictionaries in
          the language (constructed from constant string "constrkatp"
          (category namespace prefix with ":") and "c0" augmented by
          "lfpresufkap" according to control string "constrd07vm")
        - EOL (if complaint below exists)
        - complaint about not existing if applicable
        - EOL (in any case)
        - amount of pages (queried) or "??" if querying does not work
        # adjust background to redish if the category does not exist
        ! depends from variables "boovorsow" and "boovorexp" and
          includes expensive querying (2), column can be completely hidden
- d08 : - link to the index page in own tionary with
          the language (constructed from constant string "constrindp"
          (index namespace prefix with ":") and "c0" augmented by
          "lfpresufkap" according to control string "constrd01d08")
        # adjust background to redish if index page does not exist
        ! depends from variables "booidxsow" and "booidxexp" and
          includes expensive querying (1), column can be completely hidden
- d09 : - quasi-external link to wikipedia in the language concerned
          (constructed from "c5" and "c6", irrespective availability)
        - EOL (if note below exists)
        - note about bad availability if applicable
        # adjust background to grey according to bad availability
        ! no expensive querying here
- d10 : - quasi-external link to tionary in the language concerned
          (constructed from "c5" and "c6", irrespective availability, but
          special rule for own site language)
        - EOL (if note below exists)
        - note about bad availability if applicable
        # adjust background to grey according to bad availability
        ! no expensive querying here
- d11 : - quasi-external link to the article in own ipedia about the language
          (article name constructed from "c7", or alternatively if "c7" is
          not available then it is guessed from "c0" and "constrd11wm"
          and " (??)" is added)
        # adjust background to redish if "c7" is not available
        ! no expensive querying here
- d12 : - quasi-external link to EO or ID category in the tionary in the
          language concerned (peeked from "c8" in the source table)
        - EOL (if amount of articles below exists)
        - amount of articles (peeked from "c9" in the source table)
        # adjust background to redish if "c8" or "c9" is not available
        ! no expensive querying here

Expensive querying:
There are only 5 expensive queries (2 times 'PAGESINCATEGORY' and
3 times '#ifexist:') per language and thus table row. This is a big
problem here in "mkomtbllin" but in "msngtbllin" it is no problem at
all. The hard limit set by wiki software is 500. The totally fired
amount of calls can be reduced via parameters "bookapexp" "boovorexp"
"booidxexp" "numproba".

Error handling:
- "booerr" set to true if we fail to import the source table, or
  the argument supplied from the caller is bad, output is minimal with
  huge error " # # Grava eraro # # " then, no huge table and no
  summary, fatal warning YES, "numtblper" is NOT valid
- "booearsyn" set to true if early syntax check fails (line ZERO with
  "[[eo]]" or "[[id]]" not found or not valid), output is minimal with
  huge error " # # Grava eraro # # " then, no huge table and no summary,
  fatal warning YES, "numtblper" is valid (can be ZERO or equal "numtblend")
- "boomxwerr" is a "maxwidth" violation error or line without EOL,
  checked before and after row, abort immediately, huge error
  via "constrmxwe", summary YES, fatal warning YES
- "boosinerr" set to true in a table row, the row is completed (risk
  for "-"), loop exited and table closed, huge error via "constrsexe"
  AKA " # # Sintaksa eraro # # " is outside the table,
  summary YES, fatal warning YES
- "boosorerr" temporarily set to true and "numsorerr" incremented for
  every sorting error (not possible in line ZERO), lagom error "Sortiga
  eraro" is in the table element at column 0, do not exit
  the loop, fatal warning YES
- "numerrtru" (no bool) incremented for every truncated line in source table
  having "cy" and "c0", minimal error "Nekompleta linio" is in the table
  element at column 0, do not exit the loop, fatal warning NO
- "numerrtlo" (no bool) incremented for every too long line in source table,
  lagom error "Tro longa (ele) linio" is in the table
  element at column 0, do not exit the loop, fatal warning YES
- "numerrkec" (no bool) incremented for every minor
  error (possible in line ZERO), do not exit the loop, fatal warning NO
- "numerrkap" (no bool) incremented for every missing "kapvorto" category
  error (possible in line ZERO), do not exit the loop, fatal warning NO
- "numerrvor" (no bool) incremented for every missing "vortaro" category
  error (possible in line ZERO), do not exit the loop, fatal warning NO
- "numerrind" (no bool) incremented for every missing index page
  error (possible in line ZERO), do not exit the loop, fatal warning NO
- if "mw.title.getCurrentTitle().prefixedText" does not reveal our
  pagename (needed for purge link) then we don't whine but use a bad
  default "Special:Recent changes" instead

]===]

local komtbllin = {}

---- CONSTANTS ----

  -- surrogate transcoding table (only needed for EO)

  local contabtransiltable = {}
  contabtransiltable[ 67] = 0xC488 -- CX
  contabtransiltable[ 99] = 0xC489 -- cx
  contabtransiltable[ 71] = 0xC49C -- GX
  contabtransiltable[103] = 0xC49D -- gx
  contabtransiltable[ 74] = 0xC4B4 -- JX
  contabtransiltable[106] = 0xC4B5 -- jx
  contabtransiltable[ 83] = 0xC59C -- SX
  contabtransiltable[115] = 0xC59D -- sx
  contabtransiltable[ 85] = 0xC5AC -- UX breve
  contabtransiltable[117] = 0xC5AD -- ux breve

  -- constant strings (generic & misc)

  local constrfrco = '2020E0'                                      -- table frame color (blue)
  local constrbkco = 'FFFFD0'                                      -- default cell background color (light yellow)
  local constrbord = 'border:0.25em solid #' .. constrfrco .. ';'  -- to be used inside "style" element
  local constrtdbg = '<td style="' .. constrbord .. 'text-align:center;padding:0.4em;">'              -- colspan NO color NO
  local constrtddf = '<td style="' .. constrbord .. 'text-align:center;padding:0.4em;background:#'    -- colspan NO color YES
  local constrtdfd = ';">'                              -- part of HTML table code after HEX color
  local constrtden = '</td>'
  local constrkros = '&nbsp;#&nbsp;#&nbsp;'             -- lagom -> huge circumfix
  local constremibg = '<span class="error">'            -- minimal whining begin
  local constremien = '</span>'                         -- minimal whining end
  local constrelabg = '<span class="error"><b>'         -- lagom whining begin
  local constrelaen = '</b></span>'                     -- lagom whining end
  local constrehubg = constrkros .. constrelabg         -- huge whining begin
  local constrehuen = constrelaen .. constrkros         -- huge whining end
  local constrexcla = '&nbsp;' .. constremibg .. '!!!' .. constremien  -- just " !!!" with some style (komp YES sng NO)

  -- constant strings EO vs ID (depends from above "generic & misc" section)

  -- local constrpriv = "eo"                    -- EO (privileged site language)
  local constrpriv = "id"                    -- ID (privileged site language)
  -- local construsmo = "Modulo:mtmplloaddata"  -- EO (komp YES sng NO)
  local construsmo = "Modul:mtmplloaddata"   -- ID (komp YES sng NO)
  -- local constrpiks = "Modulo:mpiksubstrind"  -- EO
  local constrpiks = "Modul:mpiksubstrind"   -- ID
  -- local constrkatp = "Kategorio:"            -- EO
  local constrkatp = "Kategori:"             -- ID
  -- local constrindp = "Indekso:"              -- EO
  local constrindp = "Indeks:"               -- ID
  -- local constrapxp = "Aldono:"               -- EO
  local constrapxp = "Lampiran:"             -- ID

  -- local constrneko = constremibg .. 'Nekompleta (ele) linio' .. constremien       -- EO (minimal)
  local constrneko = constremibg .. 'Garis tidak lengkap (ele)' .. constremien    -- ID (minimal)
  -- local constrtrol = constrelabg .. 'Tro longa (ele) linio' .. constrelaen        -- EO (lagom)
  local constrtrol = constrelabg .. 'Garis terlalu panjang (ele)' .. constrelaen  -- ID (lagom)
  -- local constrsore = constrelabg .. 'Sortiga eraro' .. constrelaen                -- EO
  local constrsore = constrelabg .. 'Kesalahan sort' .. constrelaen               -- ID

  -- local constrsexe = constrehubg .. 'Sintaksa eraro' .. constrehuen                                      -- EO
  local constrsexe = constrehubg .. 'Kesalahan sintaks' .. constrehuen                                   -- ID
  -- local constrmxwe = constrehubg .. 'Linio estas tro longa (sgn, maxwid) aux sen EOL' .. constrehuen     -- EO
  local constrmxwe = constrehubg .. 'Garis terlalu panjang (kar, maxwid) atau tanpa EOL' .. constrehuen  -- ID
  -- local constrfate = constrehubg .. 'Grava eraro' .. constrehuen                                         -- EO
  local constrfate = constrehubg .. 'Kesalahan jahat' .. constrehuen                                     -- ID

  local contabdestcol = {}
  -- contabdestcol[00] = 'Alira lingva kodo'                                             -- EO
  contabdestcol[00] = 'Kode akses bahasa'                                             -- ID
  -- contabdestcol[01] = 'Nomo de la lingvo en EO kaj kapvorta pagxo</b><br>kaj aldono'  -- EO (Appendix can be hidden)
  contabdestcol[01] = 'Nama bahasa dalam ID dan halaman lema</b><br>dan lampiran'     -- ID (Appendix can be hidden)
  -- contabdestcol[02] = 'Nomo en la lingvo mem'                                         -- EO
  contabdestcol[02] = 'Nama bahasa dalam bahasa itu'                                  -- ID
  -- contabdestcol[03] = 'Planlingva kaj antikva statuso'                                -- EO
  contabdestcol[03] = 'Status buatan dan kuno'                                        -- ID
  -- contabdestcol[04] = 'ISO 639-1:2002 2-litera kodo'      -- EO
  contabdestcol[04] = 'ISO 639-1:2002 kode 2 huruf'       -- ID
  -- contabdestcol[05] = 'ISO 639-3:2007 3-litera kodo'      -- EO
  contabdestcol[05] = 'ISO 639-3:2007 kode 3 huruf'       -- ID
  -- contabdestcol[06] = 'Kapvorta kategorio</b><br>kaj nombro da pagxoj'                            -- EO ("<b>" missing) (colu can be hidden)
  contabdestcol[06] = 'Kategori kata</b><br>dan jumlah halaman'                                   -- ID ("<b>" missing) (colu can be hidden)
  -- contabdestcol[07] = 'Vortara kategorio</b><br>kaj nombro da pagxoj'                             -- EO ("<b>" missing) (colu can be hidden)
  contabdestcol[07] = 'Kategori kamus</b><br>dan jumlah halaman'                                  -- ID ("<b>" missing) (colu can be hidden)
  -- contabdestcol[08] = 'Indekso kun la lingvo'                                                     -- EO (colu can be hidden)
  contabdestcol[08] = 'Indeks bahasa itu'                                                         -- ID (colu can be hidden)
  -- contabdestcol[09] = 'Vikipedio en la lingvo'                                                    -- EO
  contabdestcol[09] = 'Wikipedia dalam bahasa itu'                                                -- ID
  -- contabdestcol[10] = 'Vikivortaro en la lingvo'                                                        -- EO
  contabdestcol[10] = 'Wikikamus dalam bahasa itu'                                                      -- ID
  -- contabdestcol[11] = 'Artikolo pri la lingvo en EO vikipedio'                                          -- EO
  contabdestcol[11] = 'Artikel tentang bahasa itu dalam wikipedia ID'                                   -- ID
  -- contabdestcol[12] = 'Kategorio pri EO en vikivortaro en la lingvo</b><br>kaj nombro da pagxoj'        -- EO ("<b>" missing)
  contabdestcol[12] = 'Kategori tentang ID dalam vikikamus dalam bahasa itu</b><br>dan jumlah halaman'  -- ID ("<b>" missing)

  -- local constrbual = "ne ekzistas"  -- EO (status of category pages)
  local constrbual = "tidak ada"    -- ID (status of category pages)

  local contabevilitem = {}
  -- contabevilitem = {'erara kodo','erara lingvonomo','erara titolo','erara kategorio','erara kvanto'}  -- EO (index 1...5, no l&t spaces)
  contabevilitem = {'kode salah','nama bahasa salah','judul salah','kategori salah','jumlah salah'}   -- ID (index 1...5, no l&t spaces)
  -- contabevilitem[0] = ' en kolumno'                                                                   -- EO (index 0, leading space needed)
  contabevilitem[0] = ' dalam kolom'                                                                  -- ID (index 0, leading space needed)

  -- local constrd01d08 = "!|"            -- EO (wall "|" required, fixes may be empty, use space here, not "_")
  local constrd01d08 = "Bahasa |"      -- ID (wall "|" required, fixes may be empty, use space here, not "_")

  -- local constrd01lem = "|"             -- EO (wall "|" required, fixes may be empty, use space here, not "_")
  local constrd01lem = "bahasa |"      -- ID (wall "|" required, fixes may be empty, use space here, not "_")

  -- local constrd01qal = '(aldona pagxo)'      -- EO
  local constrd01qal = '(halaman lampiran)'  -- ID

  local contabd03 = {}
  -- contabd03 = {'ne planita','parte planita','planita','antikva'}  -- EO (index 1...4, no spaces)
  contabd03 = {'tidak buatan','agak buatan','buatan','kuno'}      -- ID (index 1...4, no spaces)

  -- local constrd06km = "!|"             -- EO (wall "|" required, fixes may be empty, use space here, not "_")
  local constrd06km = "Kata bahasa |"  -- ID (wall "|" required, fixes may be empty, use space here, not "_")

  -- local constrd07vm = "Vortaro (|)"    -- EO (wall "|" required, fixes may be empty, use space here, not "_")
  local constrd07vm = "Kamus (|)"      -- ID (wall "|" required, fixes may be empty, use space here, not "_")

  local contabd09d10 = {}
  -- contabd09d10 = {'fermita aux malplena','nedisponebla'}  -- EO
  contabd09d10 = {'tertutup atau kosong','tidak ada'}     -- ID

  -- local constrd11wm = "!| lingvo"      -- EO (wall "|" required, fixes may be empty, use space here, not "_")
  local constrd11wm = "Bahasa |"       -- ID (wall "|" required, fixes may be empty, use space here, not "_")

  -- local constrlnkpu = 'Klaku cxi tie (kaj sekve konsentu al "malplenigi kasxmemoron") por regeneri la tabelon.'            -- EO (dot "." needed here)
  local constrlnkpu = 'Kliklah di sini (dan kemudian setujulah dengan "hapus singgahan") untuk menghasilkan ulang tabel.'  -- ID (dot "." needed here)
  -- local constrsumbr = "[[%C5%9Cablono:tbllingvoj|la fontan tabelon]]"                                                      -- EO (no dot "." here)
  local constrsumbr = "[[Templat:tblbahasa|tabel sumber]]"                                                                 -- ID (no dot "." here)

  local contabfata = {}
  -- contabfata[0] = "Gravaj eraroj trovigxas en la tabelo"                              -- EO (no dot "." here)
  contabfata[0] = "Ada kesalahan jahat dalam tabel"                                   -- ID (no dot "." here)
  -- contabfata[1] = "Se la eraroj persistas tiam vi redaktu"                            -- EO (no dot "." here)
  contabfata[1] = "Kalau kesalahan masih ada jadi Anda harus menyunting"              -- ID (no dot "." here)
  -- contabfata[2] = "kaj sekve revenu cxi tien por reinspekti rezulton"                 -- EO (no dot "." here)
  contabfata[2] = "dan kemudian datang ke sini sekali lagi untuk memeriksa hasilnya"  -- ID (no dot "." here)
  -- contabfata[3] = "Gxustigu kaj reprovu gxis ke cxi tiu mesagxo malaperas"            -- EO (no dot "." here)
  contabfata[3] = "Silakan memperbaiki dan mencoba ulang sampai pesan ini hilang"     -- ID (no dot "." here)

  -- local constrtinyb = 'Vi povas redakti'      -- EO (no dot "." here) (komp YES sng NO)
  local constrtinyb = 'Anda bisa menyunting'  -- ID (no dot "." here) (komp YES sng NO)

  local contabsum = {}
  -- contabsum[0] = "Eniga kontrolparametro, probablo: "             -- EO
  contabsum[0] = "Parameter pengontrol masuk, probabilitas: "     -- ID
  -- contabsum[1] = "Amplekso de la fonta tabelo (bitokoj): "        -- EO
  contabsum[1] = "Ukuran tabel sumber (oktet): "                  -- ID
  -- contabsum[2] = "Nombro da lingvoj: "                            -- EO
  contabsum[2] = "Jumlah bahasa: "                                -- ID
  -- contabsum[3] = "Nombro da (gravaj) sortigaj eraroj: "           -- EO
  contabsum[3] = "Jumlah kesalahan sort (jahat): "                -- ID
  -- contabsum[4] = "Nombro da nekompletaj (ele) linioj: "           -- EO
  contabsum[4] = "Jumlah garis tidak lengkap (ele): "             -- ID
  -- contabsum[5] = "Nombro da tro longaj (ele) linioj: "            -- EO
  contabsum[5] = "Jumlah garis terlalu panjang (ele): "           -- ID

  -- integers "num"

  -- two limits for width of table row in the source table
  -- !!! these values are CRUCIAL !!!
  -- !!! these values must be SAME here in "Module:mkomtbllin" and in
  --     other "Module:mpiktbllki" !!! ("Module:msngtbllin" does NOT use them)
  -- !!! DO NOT CHANGE these values unless you understand how they work !!!

  local conminwidth = 11   -- safe values 8 ... 1/2 * "maxwidth"
  local conmaxwidth = 216  -- safe values 40 ... 40'000 and lower is better

  -- some limits for single items

  local connummaxc0c1nlen = 36   -- safe values 16 ... 96
  local connummaxc8catlen = 100  -- safe values 64 ... 256

---- IMPORTS ----

local piksubstrind = require(constrpiks) -- can crash here

---- SEIZE THE HUGE SOURCE TABLE (OUTSIDE OF MAIN FUNCTION) ----

local tbllingvoj = mw.loadData(construsmo) -- can crash here (komp YES sng NO)
local constrtbl = "" -- hu sr table (320 (2 * "maxwidth") ... 1'000'000 chars)
if (tbllingvoj~=nil) then -- seems to be always true
  constrtbl = tbllingvoj [1] -- convert table -> string (with a small risk)
end--if

------------------------------------------------------------------------

---- ORDINARY LOCAL LOW LEVEL FUNCTIONS ----

------------------------------------------------------------------------

-- Local function LFPREPROEQMI

-- Preprocess "=" to "-"

local function lfpreproeqmi (strinnandout)
  if (strinnandout=="=") then
    strinnandout = "-" -- preprocess "=" to "-"
  end--if
  return strinnandout
end--function lfpreproeqmi

------------------------------------------------------------------------

-- Local function LFDEC1DIGLM

-- Convert 1 digit decimal to UINT8 with inclusive upper limit

local function lfdec1diglm (num1dygyt,num1lim)
  num1dygyt = num1dygyt - 48 -- may become invalid
  if ((num1dygyt<0) or (num1dygyt>num1lim)) then
    num1dygyt = 255
  end--if
  return num1dygyt
end--function lfdec1diglm

------------------------------------------------------------------------

-- Local function LFTESTLC

-- Test whether char is a lowercase letter, return bool

local function lftestlc (numcode)
  local boolowerc = true
  if ((numcode<97) or (numcode>122)) then
    boolowerc = false
  end--if
  return boolowerc
end--function lftestlc

------------------------------------------------------------------------

-- Local function LFXCASEBEG

-- Case beginning letter of a word or group of words to upper or lower,
-- limited unicode support

-- Input  : - strucinut : word or group of words (may be empty)
--          - booucas : "true" for uppercase and "false" for lowercase

local function lfxcasebeg (strucinut,booucas)
  local numlein = 0
  local numchaer = 0
  local numchaes = 0
  local numcut = 1 -- becomes 2 for unicode char:s
  local booc3blok = false
  local booc4c5bl = false
  local booisuppr = false
  local booislowr = false
  numlein = string.len(strucinut)
  if (numlein~=0) then
    numchaer = string.byte(strucinut,1,1)
    if ((numchaer>127) and (numlein>=2)) then
      numchaes = string.byte(strucinut,2,2)
      numcut = 2
    end--if
    if (numcut==1) then
      booisuppr = ((numchaer>64) and (numchaer< 91))
      booislowr = ((numchaer>96) and (numchaer<123))
      if (booisuppr and (booucas==false)) then
        numchaer = numchaer+32 -- ASCII UPPER->lower
      end--if
      if (booislowr and booucas) then
        numchaer = numchaer-32 -- ASCII lower->UPPER
      end--if
    else
      booc3blok = (numchaer==195) -- case delta is 32
      booc4c5bl = ((numchaer==196) or (numchaer==197)) -- case delta is 1
      if (booc3blok) then
        if ((numchaes>=128) and (numchaes<160)) then
          booisuppr = true -- C3,80...C3,9F
        end--if
        if ((numchaes>=160) and (numchaes<192)) then
          booislowr = true -- C3,A0...C3,BF
        end--if
      end--if
      if (booc4c5bl) then
        if ((numchaes%2)==0) then
          booisuppr = true
        else
          booislowr = true
        end--if
      end--if
      if (booc3blok and booisuppr and (booucas==false)) then
        numchaes = numchaes+32 -- UC UPPER->lower -- holds f AA AE EE NN OE UE
      end--if
      if (booc3blok and booislowr and booucas) then
        numchaes = numchaes-32 -- UC lower->UPPER -- holds f aa ae ee nn oe ue
      end--if
      if (booc4c5bl and booisuppr and (booucas==false)) then
        numchaes = numchaes+1 -- UC UPPER->lower -- holds for JX SX ...
      end--if
      if (booc4c5bl and booislowr and booucas) then
        numchaes = numchaes-1 -- UC lower->UPPER -- holds for jx sx ...
      end--if
    end--if (numcut==1) else
    if (numlein>numcut) then
      strucinut = string.sub(strucinut,(numcut+1),numlein) -- remaining part
    else
      strucinut = "" -- we had just 1 char
    end--if
    if (numcut==1) then
      strucinut = string.char(numchaer) .. strucinut
    else
      strucinut = string.char(numchaer) .. string.char(numchaes) .. strucinut
    end--if
  end--if
  return strucinut
end--function lfxcasebeg

------------------------------------------------------------------------

-- add digit bunching to raw decimal number string

local function lfbunch (strnomorin)
  local strnomorut = ""
  local numlenn = 0
  local numindeex = 0 -- ZERO-based counts up
  local numcaar = 0 -- char of string
  numlenn = string.len(strnomorin)
  while (true) do
    if (numindeex==numlenn) then
      break
    end--if
    numcaar = string.byte(strnomorin,(numlenn-numindeex),(numlenn-numindeex))
    if (((numindeex%3)==0) and (numindeex~=0)) then
      strnomorut = "'" .. strnomorut -- apo
    end--if
    strnomorut = string.char(numcaar) .. strnomorut
    numindeex = numindeex + 1
  end--while
  return strnomorut
end--function lfbunch

------------------------------------------------------------------------

local function lfspctound (strinin) -- replaces spaces by underscores
  local strutut = ""
  local numleenn = 0
  local numineex = 0 -- ZERO-based counts up
  local numcaarr = 0 -- char of string
  numleenn = string.len(strinin)
  while (true) do
    if (numineex==numleenn) then
      break
    end--if
    numcaarr = string.byte(strinin,(numineex+1),(numineex+1))
    if (numcaarr==32) then
      numcaarr = 95 -- space to underscore
    end--if
    strutut = strutut .. string.char(numcaarr)
    numineex = numineex + 1
  end--while
  return strutut
end--function lfspctound

------------------------------------------------------------------------

local function lfclamp (strclin,numlenlim) -- clamps string length, tripledot
  local strrezulto = ''
  local numinnlen = 0
  local numlenlihaf = 0
  numinnlen = string.len(strclin)
  if (numlenlim<8) then
    numlenlim=8
  end--if
  numlenlihaf = math.floor((numlenlim-3)/2) -- at least 2
  if (numinnlen<=numlenlim) then
    strrezulto = strclin -- copy as-is, do NOT add quotes
  else
    strrezulto = '"' .. string.sub(strclin,1,numlenlihaf) .. '"..."' .. string.sub(strclin,(numinnlen-numlenlihaf+1),numinnlen) .. '"'
  end--if
  return strrezulto
end--function lfclamp

------------------------------------------------------------------------

-- convert integer to decimal string with digit bunching and warn if non-ZERO

local function lftostwa (numcrap)
  local strhasil = ''
  strhasil = lfbunch(tostring(numcrap))
  if (numcrap~=0) then
    strhasil = strhasil .. constrexcla -- just " !!!" with some style
  end--if
  return strhasil
end--function lftostwa

------------------------------------------------------------------------

local function lfkodeosg (strsurr) -- EO transcode surrogates to cxapeloj strg
  local varpeek = 0
  local strcxapeloj = ''
  local numinputl = 0
  local numininx = 0
  local numknark = 0 -- current char (ZERO is NOT valid)
  local numknarp = 0 -- previous char (ZERO is NOT valid)
  local numlow = 0
  local numhaj = 0
  numinputl = string.len(strsurr)
  while (true) do
    if (numininx==numinputl) then
      break
    end--if
    numknark = string.byte(strsurr,(numininx+1),(numininx+1))
    numininx = numininx + 1
    numhaj = 0 -- pre-assume no translation
    if ((numknarp~=0) and ((numknark==88) or (numknark==120))) then -- got "x"
      varpeek = contabtransiltable[numknarp] -- UINT16 or nil
      if (varpeek~=nil) then
        numlow = varpeek % 256 -- MOD operator -- bitwise AND operator lacks
        numhaj = math.floor (varpeek / 256) -- DIV operator lacks in LUA :-(
      end--if
    end--if
    if (numhaj~=0) then
      strcxapeloj = strcxapeloj .. string.char(numhaj) .. string.char(numlow)
      numknark = 0 -- invalidade current char
    else
      if (numknarp~=0) then -- add previous char only if valid
        strcxapeloj = strcxapeloj .. string.char(numknarp) -- add it
      end--if
    end--if
    numknarp = numknark -- copy to previous even if invalid
  end--while
  if (numknarp~=0) then -- add previous and last char only if valid
    strcxapeloj = strcxapeloj .. string.char(numknarp) -- add it
  end--if
  return strcxapeloj
end--function lfkodeosg

local function lfkodeotb (tabsurr) -- EO transcode surrogates to cxapeloj tabl
  local varitem = 0 -- variable without type
  local tabcxapeloj = {}
  local numtblindex = 0 -- ZERO-based
  while (true) do
    varitem = tabsurr[numtblindex] -- expected type "string" or "nil"
    if (varitem==nil) then
      if (numtblindex~=0) then
        break -- index ZERO is valid (just proceed to index 1 in such a case)
      end--if
    else
      tabcxapeloj[numtblindex] = lfkodeosg(varitem)
    end--if
    numtblindex = numtblindex + 1
  end--while
  return tabcxapeloj
end--function lfkodeotb

local function lfcountchr (strqq,numascii) -- count occurrences of char in str
  local numrezalt = 0
  local numciar = 0
  local numukuran = 0
  local numindxe = 0 -- ZERO-based
  numukuran = string.len(strqq)
  while (true) do
    if (numindxe==numukuran) then
      break
    end--if
    numciar = string.byte(strqq,(numindxe+1),(numindxe+1))
    if (numciar==numascii) then
      numrezalt = numrezalt + 1
    end--if
    numindxe = numindxe + 1
  end--while
  return numrezalt
end--function lfcountchr

------------------------------------------------------------------------

-- Local function LFCOUNTNDG

-- Count occurrences of non-digits in string

-- Tolerable char:s that do not count are:
-- - digits "0"..."9"
-- - space
-- - apo

local function lfcountndg (strzzz)
  local numjrezalt = 0
  local numcair = 0
  local numjukuran = 0
  local numjindxe = 0 -- ZERO-based
  numjukuran = string.len(strzzz)
  while (true) do
    if (numjindxe==numjukuran) then
      break
    end--if
    numcair = string.byte(strzzz,(numjindxe+1),(numjindxe+1))
    if (((numcair<48) or (numcair>57)) and (numcair~=32) and (numcair~=39)) then
      numjrezalt = numjrezalt + 1
    end--if
    numjindxe = numjindxe + 1
  end--while
  return numjrezalt
end--function lfcountndg

------------------------------------------------------------------------

-- Local function LFREMOVENONDI

-- Remove non-digits from a string, return "0" if no digits available

local function lfremovenondi (strmess)
  local strnumautnum = ''
  local numcchhrr = 0
  local numwukur = 0
  local numwindxe = 0 -- ZERO-based
  numwukur = string.len(strmess)
  while (true) do
    if (numwindxe==numwukur) then
      break
    end--if
    numcchhrr = string.byte(strmess,(numwindxe+1),(numwindxe+1))
    if ((numcchhrr>47) and (numcchhrr<58)) then
      strnumautnum = strnumautnum .. string.char(numcchhrr) -- cpy digits only
    end--if
    numwindxe = numwindxe + 1
  end--while
  if (strnumautnum=='') then
    strnumautnum = '0' -- result CANNOT be empty, always a valid number
  end--if
  return strnumautnum
end--function lfremovenondi

------------------------------------------------------------------------

-- Local function LFPRESUFKAP

-- Augment string adding prefix and suffix (any of them may be empty)
-- and optionally uppercase beginning letter of the result

-- Input  : - strctl : control string (syntax see below)
--          - strinp : data string to be augmented

-- Syntax of "strctl" :
-- - prefix (may be empty, or "!" for uppercasing)
-- - wall "|"
-- - suffix (may be empty)
-- Examples: "|" is no change and "!|" is uppercasing without augmentation

-- We need "lfxcasebeg"

local function lfpresufkap (strctl,strinp)
  local varctlmur = 0 -- wall position ONE-based (but can be "nil")
  local numctllen = 0
  local strpre = ''
  local strsuf = ''
  local strhazil = ''
  numctllen = string.len (strctl)
  if (numctllen~=0) then -- empty is NOT valid
    varctlmur = string.find (strctl, '|', 1, true) -- plain text search
    if (varctlmur~=nil) then -- "not found" is NOT valid
      if (varctlmur>1) then
        strpre = string.sub(strctl,1,(varctlmur-1)) -- isolate prefix
      end--if
      if (varctlmur<numctllen) then
        strsuf = string.sub(strctl,(varctlmur+1),numctllen) -- isolate suffix
      end--if
      if (strpre=='!') then
        strhazil = lfxcasebeg (strinp,true) .. strsuf -- no prefix here
      else
        strhazil = strpre .. strinp .. strsuf
      end--if
    end--if (varctlmur~=nil) then
  end--if
  return strhazil
end--function lfpresufkap

------------------------------------------------------------------------

-- Local function LFVALIDATESTR

-- Validate string according to a huge bunch of criteria

-- Input  : - stryn : string
--          - varalt : alternative valid string (for example "??" or "-")
--                     that can "jump over" all other checks, note that empty
--                     string can be used here, use type "nil" if none
--          - nummyn : minimal length
--          - nummex : maximal length
--          - numapo : apo rules
--                     0 : no restrictions
--                     1 : leading and trailing and multiple apo:s prohibited
--                         (no-wiki-bolding-policy)
--                     2 : apo:s totally prohibited
--          - numpoz : positive list of tolerable char:s
--                     0 : none
--                     1 : only ASCII digits and maybe
--                         apo:s (see also "numapo" above)
--                     2 : only ASCII uppercase letters
--                     3 : only ASCII lowercase letters

-- Output : - booisvalid : true if string is valid

local function lfvalidatestr (stryn,varalt,nummyn,nummex,numapo,numpoz)
  local booisvalid = true -- for the caller
  local numlencx = 0
  local numynx = 0
  local numcxar = 0
  local numcxur = 0
  local vartnp = 0
  while (true) do -- fake loop
    if (type(varalt)=="string") then
      if (stryn==varalt) then
        break -- to join mark -- string is valid
      end--if
    end--if
    numlencx = string.len(stryn)
    if ((numlencx<nummyn) or (numlencx>nummex)) then
      booisvalid = false
      break -- to join mark -- string is faulty
    end--if
    if (numlencx==0) then
      break -- to join mark -- string is empty but valid
    end--if
    if (numapo==1) then
      numcxar = string.byte(stryn,1,1)
      numcxur = string.byte(stryn,numlencx,numlencx)
      vartnp = string.find(stryn, "''", 1, true) -- plain text search for apo
      if ((numcxar==39) or (numcxur==39) or vartnp) then
        booisvalid = false
        break -- to join mark -- string is faulty
      end--if
    end--if (numapo==1) then
    if ((numpoz~=0) or (numapo==2)) then
      numynx = 0 -- ZERO-based index
      while (true) do
        if (numynx==numlencx) then
          break -- done search, all OK
        end--if
        numcxar = string.byte(stryn,(numynx+1),(numynx+1))
        if ((numapo==2) and (numcxar==39)) then
          booisvalid = false
          break -- abort search, crime detected (apo)
        end--if
        if ((numpoz==1) and (numcxar~=39)) then
          if ((numcxar<48) or (numcxar>57)) then
            booisvalid = false
            break -- abort search, crime detected (non-digit)
          end--if
        end--if
        if (numpoz==2) then
          if ((numcxar<65) or (numcxar>90)) then
            booisvalid = false
            break -- abort search, crime detected (non-uppercase)
          end--if
        end--if
        if (numpoz==3) then
          if ((numcxar<97) or (numcxar>122)) then
            booisvalid = false
            break -- abort search, crime detected (non-lowercase)
          end--if
        end--if
        numynx = numynx + 1 -- ZERO-based index
      end--while
    end--if ((numpoz~=0) or (numapo==2)) then
    break -- finally to join mark
  end--while -- fake loop -- join mark
  return booisvalid
end--function lfvalidatestr

------------------------------------------------------------------------

---- ORDINARY LOCAL HIGH LEVEL FUNCTIONS ----

------------------------------------------------------------------------

-- Local function LFRLSTRIP

-- Strip "rl .. lr" if present and string length is at least 8 octet:s

local function lfrlstrip (strrlinut)
  local numsoct = 0
  local numsodt = 0
  local numsoet = 0
  local numsoft = 0
  local numsogt = 0
  local numsoht = 0
  local numlaengd = 0
  numlaengd = string.len(strrlinut)
  if (numlaengd>=8) then -- at least 2 Octet:s length "rl .. lr" after strip
    numsoct = string.byte(strrlinut,1,1)
    numsodt = string.byte(strrlinut,2,2)
    numsoet = string.byte(strrlinut,3,3)
    numsoft = string.byte(strrlinut,(numlaengd-2),(numlaengd-2))
    numsogt = string.byte(strrlinut,(numlaengd-1),(numlaengd-1))
    numsoht = string.byte(strrlinut,(numlaengd  ),(numlaengd  ))
    if ((numsoct==114) and (numsodt==108) and (numsoet==32) and (numsoft==32) and (numsogt==108) and (numsoht==114)) then
      strrlinut = string.sub(strrlinut,4,(numlaengd-3)) -- stri off 3+3 char:s
    end--if
  end--if
  return strrlinut
end--function lfrlstrip

------------------------------------------------------------------------

local function lfamountinkat (varjumlah) -- "(16'384 pages)" or "(?? pages)"
  local strnothing = ''
  if (varjumlah==nil) then -- expected type integer or nil
    strnothing = '(??'
  else
    strnothing = '(' .. lfbunch(tostring(varjumlah)) -- ZERO is valid
  end--if
  strnothing = strnothing .. ' pages)'
  return strnothing
end--function lfamountinkat

------------------------------------------------------------------------

local function lfquer2kat (frmftnt,strkatt) -- calls 2 parser functions
  local vartoomp = 0 -- string expected but minor risk for nil
  local strkatoj = '' -- accumulate notes here
  local boomiss = false
  vartoomp = frmftnt:callParserFunction(('#ifexist:'..constrkatp..strkatt),'1','0')
  if (vartoomp~='1') then
    boomiss = true -- category does not exist (incidents counted by caller)
    strkatoj = '<br>(' .. constrbual .. ')' -- "does not exist"
  end--if
  vartoomp = frmftnt:callParserFunction('PAGESINCATEGORY',strkatt,'pages','R')
  strkatoj = strkatoj .. '<br>'
  if (type(vartoomp)=='string') then -- it is a string despite it is a number
    strkatoj = strkatoj .. lfamountinkat(tonumber(vartoomp))
  else
    strkatoj = strkatoj .. lfamountinkat(nil) -- does NOT count as error
  end--if
  return boomiss,strkatoj
end--function lfquer2kat

------------------------------------------------------------------------

local function lfavailco (numava) -- translates number 2...0 to color (Y,grey)
  local strcolor = constrbkco -- pre-assume light yellow (default color)
  if (numava==1) then
    strcolor = 'D0D0D0' -- grey
  end--if
  if (numava==0) then
    strcolor = 'B0B0B0' -- darker grey
  end--if
  return strcolor
end--function lfavailco

------------------------------------------------------------------------

-- Local function LFAVAILNT

-- Translate number 2...0 to text with "br"

-- We need table "contabd09d10" with 2 strings at indexes ONE and TWO

local function lfavailnt (numalb)
  local strnote = '' -- pre-assume no extra complaint
  if (numalb==1) then
    strnote = '<br>(' .. contabd09d10[1] .. ')' -- closed or empty
  end--if
  if (numalb==0) then
    strnote = '<br>(' .. contabd09d10[2] .. ')' -- inaccessible
  end--if
  return strnote
end--function lfavailnt

------------------------------------------------------------------------

-- Local function LFEVILITEM

-- Brew complaint about faulty item in the source table

-- Input  : - numitem : type (0:code 1:langname 2:title 3:category 4:amount)
--          - numcol : column index (maybe 0...12) or special value 56
--          - strxx : the faulty string already suitably clamped

-- Output : - 2 lines separated by "<br>"

-- We need table "contabevilitem" (1...5) with special content at index ZERO

-- We need "constrelabg" and "constrelaen" (lagom error)

local function lfevilitem (numitem,numcol,strxx)
  local strharang = ''
  local numquot = 0
  strharang = constrelabg .. contabevilitem[numitem+1] .. contabevilitem[0] .. constrelaen .. ' "c'
  if (numcol==56) then
    strharang = strharang .. '5" "c6' -- special case
  else
    strharang = strharang .. tostring(numcol)
  end--if
  strharang = strharang .. '"&nbsp;:<br>'
  numquot = string.byte(strxx,1,1)
  if (numquot==34) then
    strharang = strharang .. strxx -- truncated string like <<"sh"..."ck">>
  else
    strharang = strharang .. '"' .. strxx .. '"' -- add quotes if not yet pres
  end--if
  return strharang
end--function lfevilitem

------------------------------------------------------------------------

-- Local function LFBREWURL

-- Brew [] external link to a wiki

-- Input  : - straxk : wiki access code (2...10 char:s)
--          - bootip : type (false -> ipedia | true -> tionary)
--          - varpage : pagename string (article or category with
--                      prefix) or nil expected

-- Here we replace spaces by underscore, no further encoding is performed

-- We need "lfspctound"

local function lfbrewurl (straxk,bootip,varpage)
  local strurlkita = ''
  local strsite = ''
  if (bootip) then
    strsite = 'tionary'
  else
    strsite = 'ipedia'
  end--if
  strurlkita = '[http://' .. straxk .. '.wik' .. strsite .. '.org'
  if (varpage) then -- string (article or category with prefix) or nil
    strurlkita = strurlkita .. '/wiki/' .. lfspctound(varpage) -- repla in URL
  end--if
  strurlkita = strurlkita .. ' ' -- separation space
  strurlkita = strurlkita .. straxk .. '.' .. strsite .. '...'
  if (varpage) then -- string (article or category with prefix) or nil
    strurlkita = strurlkita .. '<br>/' .. varpage -- do NOT replace here
  end--if
  strurlkita = strurlkita .. ']' -- done
  return strurlkita
end--function lfbrewurl

------------------------------------------------------------------------

-- Local function LFBREWTITSEL

-- Brew content of title cell from index number

-- Input  : - numindxe : index number of column (ZERO-based)
--          - bootrunk : remove non-bold part after "</b><br>" if true

-- An entry in the table "contabdestcol" is NOT supposed to contain
-- "<b>" (even less "''"), nor "</b>" at end, but it may contain
-- "</b><br>" to separate a non-bold part

-- We need table "contabdestcol"

local function lfbrewtitsel (numindxe,bootrunk)
  local strdesc = ''
  local varfond = 0
  strdesc = contabdestcol[numindxe] -- may contain "</b><br>" or NOT
  strdesc = '<b>' .. strdesc -- always add "<b>" begin of bold
  varfond = string.find(strdesc, '</b><br>', 1, true) -- plain text search
  if (varfond and bootrunk) then
    strdesc = string.sub(strdesc,1,(varfond+3)) -- remove part after "</b>"
  end--if
  if (varfond==nil) then
    strdesc = strdesc .. '</b>' -- add "</b>" end o b only if it is not yet in
  end--if
  strdesc = strdesc .. '<br>(' .. tostring(numindxe) .. ')'
  return strdesc
end--function lfbrewtitsel

------------------------------------------------------------------------

---- MAIN EXPORTED FUNCTION ----

------------------------------------------------------------------------

function komtbllin.ek (mwframent)

  -- general unknown type "var"

  local vartmp = 0     -- variable without type multipurpose

  -- special type "args" AKA "arx"

  local arxourown = 0  -- metaized "args" from our own "frame" (NOT caller's)

  -- general "str"

  local strpara  = ""  -- incoming parameter with 4 digi, reported at the end
  local strtmp   = ""  -- temp, even for "searcheol"
  local strtpm   = ""  -- temp other
  local strsrcrw = ""  -- complete row from the source table
  local strret   = ""  -- huge output string with the table
  local strbkn   = ""  -- HTML HEX color (6 digits)
  local strt3d   = ""  -- HTML "td" element concatenated from 3 parts
  local strtblcy = ""  -- src y-index word (this is NOT the column "c0")
  local strtblc0 = ""  -- src column 0 (this is NOT the y-index word) (obliga)
  local strtblc1 = ""  -- src column 1 (nice to have)
  local strtblc2 = ""  -- src column 2 (nice to have) 1 digit
  local strtblc3 = ""  -- src column 3 (nice to have) 2 letters
  local strtblc4 = ""  -- src column 4 (nice to have) 3 letters
  local strtblc5 = ""
  local strtblc6 = ""
  local strtblc7 = ""  -- src column 7
  local strtblc8 = ""  -- src column 8
  local strtblc9 = ""  -- src column 9
  local strdeste = ""  -- destinat table element with both "td" HTML elements
  local strpurge = ""  -- purge quasi-external link complete with "[" and "]"
  local strsumbl = ""  -- summary block

  -- general "num"

  local numproba  = 100  -- probability from arxourown[3] (komp YES sng NO)
  local numoct    = 0    -- temp some char
  local numodt    = 0    -- temp other char
  local numtamp   = 0    -- temp
  local numtump   = 0    -- temp
  local numlong   = 0    -- temp for decimal conversion (length of parameter)
  local numinxlen = 0    -- length of previous y-index word (2 or 3)
  local numfoulen = 0    -- length of latest found y-index word (2 or 3)
  local numiwo0   = 0    -- previous
  local numiwo1   = 0    -- previous
  local numiwo2   = 0    -- previous
  local numipos   = 0    -- Octet position in "constrtbl", ZERO-based
  local numiprev  = 0    -- Octet position of previous line in "constrtbl"
  local numc6pedi = 0    -- ipedia code "0"..."2"
  local numc6tion = 0    -- tionary code "0"..."2"

  -- bunched info about the input table "num"

  local numtbllen = 0  -- length of huge source table seized via "mw.loadData"
  local numrowinx = 0  -- row index becoming amount of rows & langs at the end
  local numsorerr = 0  -- sorting errors (fatal but do not abort)
  local numerrtru = 0  -- valid truncated lines in source table (minor)
  local numerrtlo = 0  -- too long lines in source table
  local numerrkec = 0  -- minor error (not fatal)
  local numerrkap = 0  -- missing kap (not fatal)
  local numerrvor = 0  -- missing vor (not fatal)
  local numerrind = 0  -- missing index page (not fatal)
  local numtblbeg = 0  -- size of legal garbage before the table, begin of tab
  local numtblend = 0  -- begin of legal garbage after the table
  local numtblper = 0  -- position of the earliest abort syntax error
  local numminwid = 0  -- evaluated minimal width
  local nummaxwid = 0  -- evaluated maximal width
  local nummaxkal = 0  -- evaluated maximal bloat of category link
  local numamoexp = 0  -- amount of committed calls to expensive parser functi

  -- general "boo"

  local booerr     = true   -- fatal error flag
  local booearsyn  = false  -- early syntax err flag (out table NO summary NO)
  local boosinerr  = false  -- syntax error flag (abort after the row)
  local boomxwerr  = false  -- maxwidth error (checked bef&aft row, abort imm)
  local boosorerr  = false  -- sort error flag (do not abort)
  local boolocerr  = false  -- local error flag within a table element
  local boolokeer  = false  -- other local error flag within a table element
  local boogtabort = false  -- brewed from 3 vari by OR, "numtblper" is valid
  local boodofatal = false  -- brewed from 6 vari by OR, show fatal block
  local boohavtbl  = false
  local bootimp    = false  -- temp
  local bootymp    = false  -- temp
  local booc0bad   = false  -- true if len(c0) out of rang, even "-" NOT valid
  local booc1bad   = false
  local booc3bad   = false  -- 2-litera -- true if bad
  local booc4bad   = false  -- 3-litera -- true if bad
  local booc5c6bad = false  -- true if c5 or c6 is bad
  local booc7bad   = false  -- ipedia article -- true if bad
  local boorussia  = false  -- set up randomly for every row from "numproba"

  -- from arxourown "boo"

  local booaldsow  = false  -- f arxourown[1] do show appendix page in "d01"
  local bookapsow  = false  -- f arxourown[1] do show column d06 at all
  local bookapexp  = false  -- f arxourown[1] carry out expensive query in d06
  local boovorsow  = false  -- f arxourown[1] do show column d07 at all
  local boovorexp  = false  -- f arxourown[1] carry out expensive query in d07
  local booidxsow  = false  -- f arxourown[1] do show column d08 at all
  local booidxexp  = false  -- f arxourown[1] carry out expensive query in d08
  local boosummar  = false  -- f arxourown[2] do show on success

  -- only for built-in function "optconcat"

  local isubtabbunch = {}     -- bunch strings here

  -- only for built-in function "searchdblchr"

  local isubnumlim = 0        -- octets to check (2 * "amount of iterations")
  local isubnumchr = 0        -- char to search (91 for "[[" or 40 for "((")
  local isubboodwn = false    -- "true" for downward search
  local osubboofnd = false    -- "true" if the dblchar was found

  -- only for built-in function "searcheol"

  local isubnumlio = 0        -- octets to check
  local isubbootmp = false    -- "true" to fill "strtmp" with copied chars
  local osubnmline = 0        -- length of found line
  local osubboofnf = false    -- "true" if EOL was found

  -- only for built-in function "cmp2or3wordbi"

  local osubboobiger = false  -- "true" if found idx word bigger than "numiwo"

  ---- BUILT-IN GOSUB-STYLE FUNCTION "OPTCONCAT" ----

  -- PURPOSE: workaround poor memory management in LUA during string
  --          concatenations, add incoming string to "strret"

  -- IN  : parameter "varincom" either string or type "nil"

  -- CHG : isubtabbunch (table), strret (string)

  -- NOTE: the thing needs to be initialized by <<local strret = "">>
  --       and <<local isubtabbunch = {}>>

  -- NOTE: if the "strret" string has to be changed directly (concatenation
  --       or replace), then "optconcat (nil)" or "isubtabbunch = {}"
  --       must be done before !!!

  local optconcat = function (varincom)
    if (type(varincom)=="string") then
      if (#isubtabbunch>20) then
        strret = strret .. table.concat (isubtabbunch) .. varincom
        isubtabbunch = {}
      else
        table.insert (isubtabbunch, varincom) -- ONE-based numbering
      end--if
    end--if
    if ((varincom==nil) and (#isubtabbunch>0)) then
      strret = strret .. table.concat (isubtabbunch)
      isubtabbunch = {}
    end--if
  end--function optconcat

  ---- BUILT-IN GOSUB-STYLE FUNCTION "SEARCHDBLCHR" ----

  -- PURPOSE: searches for a dblchar (91 for "[[" or 40 for "((")
  --          upwards or downwards

  -- IN  : isubnumlim, isubnumchr, isubboodwn (unchanged)
  -- OUT : osubboofnd (not in)
  -- USE : constrtbl (acts as a constant in the module)
  -- CHG : numipos (in and out)

  -- NOTE: if "isubboodwn" is "false" then we run upwards and check
  --       upwards, thus with incoming position "numipos"=10 we start checking
  --       at positions 11&(12,10), with incoming "isubnumlim"=10 we will no
  --       longer check positions 23&(24,22) but will check 21&(22,20) ... we
  --       need 3 chars margin at the top of range

  -- NOTE: if "isubboodwn" is "true" then we run downwards but still check
  --       upwards, thus with incoming position "numipos"=10 we start checking
  --       at positions 11&(12,10), with incoming "isubnumlim"=10 we will no
  --       longer check positions -01&(00,-02) but will check 01&(02,00) ... we
  --       need 3 chars margin at the top of range

  -- NOTE: we are supposed to safely ignore single occurrences (ie continue
  --       searching), as opposed to the fact that triple and longer
  --       occurrences are prohibited

  local searchdblchr = function ()
    local usubnumsrch = 0 -- search position checker counting always up
    local usubnumok = 0   -- single char (giving a f**k about UTF8)
    local usubnumincr = 2 -- de facto constant "+2" or "-2"
    osubboofnd = true     -- pre-assume that we will find our dblchr
    if (isubboodwn) then
      usubnumincr = -2
    end--if
    while (true) do -- iterate through octets searching for dblchr (up or dwn)
      if (usubnumsrch>isubnumlim) then
        osubboofnd = false -- give up, table broken, "numipos" irrelevant now
        break
      end--if
      usubnumok = string.byte (constrtbl,(numipos+2),(numipos+2)) -- "+1" actu
      if (usubnumok==isubnumchr) then
        usubnumok = string.byte (constrtbl,(numipos+3),(numipos+3)) -- "+2" ab
        if (usubnumok==isubnumchr) then
          numipos = numipos + 1
          break -- found and "numipos" valid ... otherwise try to look below
        end--if
        usubnumok = string.byte (constrtbl,(numipos+1),(numipos+1)) -- "+0" bl
        if (usubnumok==isubnumchr) then
          break -- found and "numipos" valid ... otherwise continue search
        end--if
      end--if
      usubnumsrch = usubnumsrch + 2
      numipos = numipos + usubnumincr -- "+2" or "-2"
    end--while
  end--function searchdblchr

  ---- BUILT-IN GOSUB-STYLE FUNCTION "SEARCHEOL" ----

  -- PURPOSE: searches for EOL, only upwards, and maybe copies
  --          text into "strtmp"

  -- IN  : (both unchanged) : isubnumlio (limit), isubbootmp (control copying)
  -- OUT : osubboofnf (not in) and osubnmline (not in)
  -- USE : constrtbl (acts as a constant in the module)
  -- CHG : - numipos (in and out)
  --       - maybe strtmp (in and out) filled with copied text, we do
  --         not clear it on entry, the caller is responsible

  local searcheol = function ()
    local usubnumsrcz = 0 -- search position checker
    local numoqqt = 0     -- single char (giving a f**k about UTF8)
    osubboofnf = true     -- pre-assume that we will find our EOL
    while (true) do -- iterate through octets searching for EOL (only up)
      if (usubnumsrcz>=isubnumlio) then
        osubboofnf = false ; -- give up, tabl broken, "numipos" irrelevant now
        break
      end--if
      numoqqt = string.byte (constrtbl,(numipos+1),(numipos+1)) -- "+0" actual
      if ((numoqqt<32) and (numoqqt~=9)) then
        break -- found and "numipos" valid ... otherwise continue search
      end--if
      if (isubbootmp == true) then
        strtmp = strtmp .. string.char (numoqqt)
      end--if
      usubnumsrcz = usubnumsrcz + 1
      numipos = numipos + 1
    end--while
    if (osubboofnf) then
      osubnmline = usubnumsrcz
    end--if
  end--function searcheol

  ---- BUILT-IN GOSUB-STYLE FUNCTION "CMP2OR3WORDBI" ----

  -- PURPOSE: performs a comparison of 2 or 3 char:s testing for "bigger"

  -- IN  : numipos, numinxlen, numfoulen, numiwo0...numiwo2
  -- OUT : osubboobiger ("true" if found index word is bigger than "numiwo")
  -- USE : constrtbl (acts as a constant in the module)
  -- CHG : N/A

  -- NOTE: it is the caller's responsibility to ensure
  --       that "numinxlen" and "numfoulen" are 2 or 3 !!!

  -- NOTE: it is the caller's responsibility to ensure
  --       that we don't hit the limit here in

  -- NOTE: the 2 strings are expected not to be equal on entry here,
  --       but single letters may be, thus ("grc" and "grc") is impossible,
  --       but ("grc" and "gro") or ("grc" and "gr") can occur, actually,
  --       the code here itself tests for "bigger" vs "smaller or equal"

  local cmp2or3wordbi = function ()
    local usubnum1char = 0 -- single char
    osubboobiger = false -- pre-assume smaller or equal, likely abort soon
    usubnum1char = (string.byte (constrtbl,numipos+3,numipos+3))
    if (usubnum1char>numiwo0) then
      osubboobiger = true -- bigger
    else
      if (usubnum1char==numiwo0) then
        usubnum1char = (string.byte (constrtbl,numipos+4,numipos+4)) ;
        if (usubnum1char>numiwo1) then
          osubboobiger = true ; -- bigger
        else
          if ((usubnum1char==numiwo1) and ((numinxlen+numfoulen)>4)) then
            if (numfoulen>numinxlen) then
              osubboobiger = true -- (3:2 - found:previous) and bigger
            else
              if (numfoulen==3) then
                usubnum1char = (string.byte (constrtbl,numipos+5,numipos+5)) ;
              else
                usubnum1char = 0
              end--if
              if (usubnum1char > numiwo2) then
                osubboobiger = true -- bigger
              end--if
            end--if
          end--if
        end--if (usubnum1char>numiwo1) else
      end--if
    end--if
  end--function cmp2or3wordbi

  ---- CHECK THE HUGE SOURCE TABLE ----

  if (type(constrtbl)=="string") then -- important check
    numtbllen = string.len(constrtbl)
    if ((numtbllen>=(2*conmaxwidth)) and (numtbllen<=1000000)) then
      booerr = false -- was preset to true
    end--if
  end--if

  ---- SEIZE 1 ... 3 PARAMETERS ----

  -- obligatory 4 digits about 4 columns into 7 bool:s (all preset to "false")
  -- optional 1 digit into 1 bool (default "false")
  -- optional 2 digits into 1 num (default 100 ie 100% ie 1) (komp YES sng NO)

  arxourown = mwframent.args -- "args" from our own "frame"

  if ((arxourown[1]==nil) or (arxourown[4])) then
    booerr = true -- need one obligatory param, four are not appreciated
  end--if

  if (booerr==false) then
    strpara = arxourown[1] -- 4 digits: ald 01 | kap 012 | vor 012 | idx 012
    numlong = string.len(strpara)
    if (numlong==4) then
      numoct = string.byte (strpara,1,1)
      numoct = lfdec1diglm (numoct,1) -- 255 if invalid
      if (numoct==255) then
        booerr = true -- invalid input
      end--if
      if (numoct==1) then
        booaldsow = true -- show link to appendix page in "d01"
      end--if
      numoct = string.byte (strpara,2,2)
      numoct = lfdec1diglm (numoct,2) -- 255 if invalid
      if (numoct==255) then
        booerr = true -- invalid input
      end--if
      if (numoct~=0) then
        bookapsow = true -- show kapvorta katego "d06"
      end--if
      if (numoct==2) then
        bookapexp = true -- carry out expensive query kapvorta katego "d06"
      end--if
      numoct = string.byte (strpara,3,3)
      numoct = lfdec1diglm (numoct,2) -- 255 if invalid
      if (numoct==255) then
        booerr = true -- invalid input
      end--if
      if (numoct~=0) then
        boovorsow = true -- show vortara katego "d07"
      end--if
      if (numoct==2) then
        boovorexp = true -- carry out expensive query vortara katego "d07"
      end--if
      numoct = string.byte (strpara,4,4)
      numoct = lfdec1diglm (numoct,2) -- 255 if invalid
      if (numoct==255) then
        booerr = true -- invalid input
      end--if
      if (numoct~=0) then
        booidxsow = true -- show index "d08"
      end--if
      if (numoct==2) then
        booidxexp = true -- carry out expensive query index "d08"
      end--if
    else
      booerr = true -- invalid input
    end--if (numlong==4) else
  end--if

  if ((booerr==false) and (arxourown[2]~=nil)) then -- optional param
    strtamp = arxourown[2] -- 1 binary digit expected
    numlong = string.len(strtamp)
    if (numlong==1) then
      numoct = string.byte (strtamp,1,1) -- boosummar preset to false
      numoct = lfdec1diglm (numoct,1) -- 255 if invalid
      if (numoct==255) then
        booerr = true -- invalid input
      end--if
      if (numoct==1) then
        boosummar = true -- show summary
      end--if
    else
      booerr = true -- invalid input
    end--if (numlong==1) else
  end--if

  if ((booerr==false) and (arxourown[3]~=nil)) then -- optional param probabil
    strtamp = arxourown[3] -- 2 decimal digits "02"..."98" expected
    if (lfvalidatestr(strtamp,nil,2,2,2,1)) then
      numoct = string.byte (strtamp,1,1)
      numodt = string.byte (strtamp,2,2)
      numoct = lfdec1diglm (numoct,9) -- 255 if invalid
      numodt = lfdec1diglm (numodt,9) -- 255 if invalid
      numproba = numoct * 10 + numodt -- was preset to default value 100
      if ((numproba<2) or (numproba>98)) then
        booerr = true -- invalid value
      end--if
    else
      booerr = true -- invalid length of string
    end--if
  end--if

  ---- TRANSCODE EO IF NEEDED ----

  if (constrpriv=="eo") then
    constrd01qal  = lfkodeosg(constrd01qal)  -- "(aldona pagxo)"
    constrlnkpu   = lfkodeosg(constrlnkpu)   -- "Klaku cxi tie (kaj" ...
    contabd09d10  = lfkodeotb(contabd09d10)  -- 1,2 -- "fermita aux malplena"
    contabdestcol = lfkodeotb(contabdestcol) -- 0...12 -- table headings
    contabfata    = lfkodeotb(contabfata)    -- 0...3 -- texts for fatal block
  end--if

  ---- SEIZE THE PAGENAME (NEEDED FOR PURGE LINK) AND BREW THE PURGE LINK ----

  -- here we do NOT use the usual function "lfbrewurl" due to
  -- insurmountable differences in the link form

  -- we need "constrlnkpu" with complete sentence

  strtpm = "Special:Recent changes" -- bad default

  vartmp = mw.title.getCurrentTitle().prefixedText -- with namespace prefix !!
  if (type(vartmp)=="string") then
    if (string.len(vartmp)~=0) then
      strtpm = vartmp -- pagename here (otherwise "Special:Recent changes")
    end--if
  end--if

  strtpm = lfspctound(strtpm) -- replace space by underscore in URL
  strtmp = 'http://' .. constrpriv .. '.wiktionary.org/wiki/' .. strtpm .. '?action=purge'

  strpurge = '[' .. strtmp .. ' ' .. constrlnkpu .. ']' -- complete sentence

  ---- SEARCH FOR THE TABLE BEGIN AKA THE 0TH Y-INDEX WORD ----

  -- will succeed if we find "[[" within "maxwidth"

  -- note that minimum table size guaranteed from above
  -- is (2 * "maxwidth") but the table may contain much padding
  -- and shrink considerably after padding is trimmed off

  if (booerr==false) then
    numtblper = 0          -- risk of "booearsyn" error here, preventively set
    numipos = 0            -- ZERO-basd position in "constrtbl"
    isubnumlim = conmaxwidth -- do NOT subtract here
    isubnumchr = 91
    isubboodwn = false
    searchdblchr () ; -- OUT: osubboofnd | USE: constrtbl | CHG: numipos
    if (osubboofnd==false) then
      booearsyn = true ; -- give up, table is broken, "numipos" irrelevant now
    end--if
  end--if
  numtblbeg = numipos

  -- now ZERO-based "numipos" and "numtblbeg" maybe point to the found "[["

  ---- SEARCH FOR THE LAST Y-INDEX WORD ----

  -- will succeed if we find "[[" within "maxwidth"

  -- if we have only one line then found last index word will
  -- be the same as the found 0th index word

  if ((booerr==false) and (booearsyn==false)) then
    numtblper = numtbllen  -- risk of "booearsyn" error here, preventively set
    numipos = numtbllen - conminwidth      -- ZERO-based positi in "constrtbl"
    isubnumlim = 2 * conmaxwidth - conminwidth -- allow full "maxwidth" of grb
    isubnumchr = 91                            -- "["
    isubboodwn = true                          -- downwards
    searchdblchr () ; -- OUT: osubboofnd | USE: constrtbl | CHG: numipos
    if (osubboofnd==false) then
      booearsyn = true ; -- give up, table is broken, "numipos" irrelevant now
    end--if
  end--if

  -- now ZERO-based "numipos" maybe points to the found "[["

  ---- SEARCH FOR END OF THE LAST Y-INDEX WORD ----

  -- the last line too long is an error
  -- missing EOL in the last line is an error

  if ((booerr==false) and (booearsyn==false)) then
    numtblper = numipos -- risk of "booearsyn" error here, preventively set
    isubnumlio = numtbllen - numipos -- NOT "+1" do NOT chk Octet above table
    if (isubnumlio>conmaxwidth) then
      isubnumlio = conmaxwidth
    end--if
    isubbootmp = false -- do not copy
    searcheol () ; -- OUT: osubboofnf | USE: constrtbl | CHG: numipos only
    if (osubboofnf==false) then
      booearsyn = true ; -- give up
    end--if
  end--if
  numtblend = numipos

  -- now ZERO-based "numipos" and "numtblend" maybe point
  -- to the found EOL after last line

  ---- CHECK THE 0TH Y-INDEX WORD ----

  -- "[[" is already assured

  numipos  = numtblbeg -- points to "[["

  if ((booerr==false) and (booearsyn==false)) then

    numtblper = numipos -- risk of "booearsyn" error here, preventively set
    if ((numipos+6)>=numtbllen) then
      booearsyn = true
    end--if

    if (booearsyn==false) then
      numoct = string.byte (constrtbl,(numipos+3),(numipos+3)) -- "e" or "i"
      if (numoct~=string.byte(constrpriv,1,1)) then
        booearsyn = true
      end--if
      numoct = string.byte (constrtbl,(numipos+4),(numipos+4)) -- "o" or "d"
      if (numoct~=string.byte(constrpriv,2,2)) then
        booearsyn = true
      end--if
      numoct = string.byte (constrtbl,(numipos+5),(numipos+5)) -- "]"
      if (numoct~=93) then
        booearsyn = true
      end--if
      numoct = string.byte (constrtbl,(numipos+6),(numipos+6)) -- "]"
      if (numoct~=93) then
        booearsyn = true
      end--if
      numoct = string.byte (constrtbl,(numipos+7),(numipos+7)) -- space
      if (numoct~=32) then
        booearsyn = true
      end--if
    end--if

    if (booearsyn==false) then
      strtblcy = constrpriv -- "eo" or "id"
      numfoulen =  2 -- string length of "eo" or "id"
      boosorerr = false
      numminwid = conmaxwidth
      nummaxwid = 0
      nummaxkal = 0 -- evaluated maximal bloat of category link
    end--if

  end--if ((booerr==false) and (booearsyn==false)) then

  -- now ZERO-based "numipos "and "numtblbeg" maybe point to the found
  -- languange code ie "[[eo]]" or "[[id]]"

  ---- BEGIN TO GENERATE THE OUTPUT TABLE (13 COLUMNS) ----

  -- using constants "constrtdbg" and "constrtden" for "<td"...">" and "</td>"

  -- here we start using "optconcat", the thing has been initialized
  -- by <<"local strret = "">> and <<local isubtabbunch = {}>>

  -- using function "lfbrewtitsel"

  -- note that "bootymp" has inverted sence compared to "booaldsow"

  if ((booerr==false) and (booearsyn==false)) then
    boohavtbl = true
    optconcat ('<table style="' .. constrbord .. 'margin:0.5em auto 0.5em auto;border-collapse:collapse;"><tr>')
    numtamp = 0
    while (true) do -- iterate over table columns
      if (numtamp==13) then -- valid indexes 0...12
        break
      end--if
      bootimp = true -- hide column if false
      if ((numtamp==6) and (bookapsow==false)) then
        bootimp = false -- column "d06" "kap" can be hidden
      end--if
      if ((numtamp==7) and (boovorsow==false)) then
        bootimp = false -- column "d07" "vor" can be hidden
      end--if
      if ((numtamp==8) and (booidxsow==false)) then
        bootimp = false -- column "d08" "idx" can be hidden
      end--if
      bootymp = ((numtamp==1) and (booaldsow==false)) -- trunc title if true
      if (bootimp) then
        strtpm = constrtdbg .. lfbrewtitsel (numtamp,bootymp) .. constrtden
        optconcat (strtpm) -- "lfbrewtitsel" does not add "<td"...">" "</td>"
      end--if
      numtamp = numtamp + 1 -- count even hidden columns
    end--while
    optconcat ('</tr>')
  end--if

  ---- MAIN LOOP ----

  -- at entry without error ((booerr==false) and (booearsyn==false)),
  -- we have from above:
  -- * "numipos" equal "numtblbeg"
  -- * "[[eo]]" or "[[id]]" assured & "strtblcy" filled with
  --   2 char:s and "numfoulen" set to 2
  -- * "boosorerr" set to false

  -- at reiteration, we have from below:
  -- * "numipos" already bumped
  -- * y-index word assured & "strtblcy" filled with
  --   2 or 3 char:s and "numfoulen" set to 2 or 3
  -- * "boosorerr" set accordingly and possible inicident already counted

  -- in any case, we have:
  -- * "numipos" pointing to the "[[" and "numfoulen" set accordingly
  --   so we have to set "numiprev", jump over the y-index word and pick
  --   a line from the table
  -- * both "boomxwerr" and "boosinerr" false

  if ((booerr==false) and (booearsyn==false)) then

    while (true) do -- iterate over all table rows

      numiprev = numipos -- backup for check far below

      numtamp = math.random(1,100) -- playing Russian roulette with LUA
      boorussia = (numtamp<=numproba) -- limit can be 2...98 or 100

      optconcat ('<tr>')

      numipos = numipos + 5 + numfoulen -- jump over "[[" code "]]" space
      numtblper = numipos -- risk of "boomxwerr" or "boosinerr" here, preventi
      isubnumlio = numtblend - numipos + 1 -- here DO "+1" iot include EOL !!
      if (isubnumlio>conmaxwidth) then
        isubnumlio = conmaxwidth -- do NOT subtract here
      end--if
      isubbootmp = true -- do copy into "strtmp"
      strtmp = ""       -- "searcheol" will fill it, start with empty
      searcheol ()      -- OUT: osubboofnf | CHG: numipos, osubnmline, strtmp
      if (osubboofnf==false) then
        boomxwerr = true -- EOL NOT found, NOT exit loop until table row fini
      else
        strsrcrw = strtmp -- complete row from the source table (without "cy")
      end--if

      strbkn = constrbkco -- color code without "#" cross -- begin dest column 0
      if (strtblcy=="eo") then
        strbkn = '90FF90' -- green decoration
      end--if
      strdeste = '(' .. tostring (numrowinx) .. ') <b>' .. strtblcy .. '</b>'
      if (boosorerr) then -- reported only here but already counted below
        strdeste = strdeste .. '<br>' .. constrsore -- sort err (type lagom)
      end--if
      if (boomxwerr==false) then
        numtamp = 0
        strtmp = piksubstrind.ek { args = { strsrcrw, "-" } } -- count substri
        if (string.len(strtmp)==2) then
          numtamp = tonumber(strtmp)
        end--if
        if (numtamp==0) then
          boosinerr = true -- this criminal, abort table generation after row
        else
          if (numtamp<10) then
            strbkn = 'FFD8D8' -- redish
            strdeste = strdeste .. '<br>' .. constrneko -- err (type minimal)
            numerrtru = numerrtru + 1 -- this is NOT fatal (not "kec" either)
          end--if
          if (numtamp>10) then
            strbkn = 'FFB0B0' -- red -- error overrides decoration
            strdeste = strdeste .. '<br>' .. constrtrol -- err (type lagom)
            numerrtlo = numerrtlo + 1 -- this is NOT fatal (but lagom)
          end--if
          if (numtamp~=10) then
            strdeste = strdeste .. ' (' .. tostring(numtamp) .. ')'
          end--if
        end--if (numtamp==0) else
      end--if
      if (boomxwerr or boosinerr or boosorerr) then
        strbkn = 'FFB0B0' -- red -- error overrides decoration
      end--if
      strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme with color
      optconcat (strt3d .. strdeste .. constrtden) -- dn dest column 0

      if ((boomxwerr==false) and (boosinerr==false)) then

        strtblc0 = piksubstrind.ek { args = { strsrcrw, "0" } } -- bg src "c0"
        strtblc0 = lfpreproeqmi (strtblc0) -- "="->"-" but no rl-enclos possib
        booc0bad = (not lfvalidatestr(strtblc0,nil,2,connummaxc0c1nlen,0,0))
        strtblc0 = lfclamp(strtblc0,(connummaxc0c1nlen+4)) -- even "-" is bad

        strbkn = constrbkco -- color code without "#" cross -- bg dest "d01"
        if (booc0bad) then
          strbkn = 'FFB0B0' -- red
          strdeste = lfevilitem(1,0,strtblc0) -- show the evil -- bad lng name
          boosinerr = true -- this criminal, abort table generation after row
        else
          strtpm = lfpresufkap(constrd01lem,strtblc0) -- augment and maybe uc
          strdeste = '[[' .. strtpm .. '|' .. strtblc0 .. ']]' -- wl to lem pg
          if (booaldsow) then
            strtmp = lfpresufkap(constrd01d08,strtblc0) -- augme and maybe uc
            strtmp = constrapxp .. strtmp -- add the "Appendix:" prefix
            strdeste = strdeste .. '<br>[[' .. strtmp .. '|' .. constrd01qal .. ']]' -- wikili
          end--if
        end--if
        strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
        optconcat (strt3d .. strdeste .. constrtden) -- done "d01"

        strtblc1 = piksubstrind.ek { args = { strsrcrw, "1" } } -- bg src "c1"
        strtblc1 = lfpreproeqmi (strtblc1) -- "="->"-" and rl-enclos possible
        strtblc1 = lfrlstrip(strtblc1) -- nam of the lang in the lang itself
        booc1bad = (not lfvalidatestr(strtblc1,"-",2,connummaxc0c1nlen,0,0))
        strtblc1 = lfclamp(strtblc1,(connummaxc0c1nlen+4)) -- done "c1"

        strbkn = constrbkco -- color code without "#" cross -- bg dest "d02"
        if (booc1bad) then
          strbkn = 'FFB0B0' -- red
          strdeste = lfevilitem(1,1,strtblc1) -- show the evil -- bad lng name
          boosinerr = true -- this criminal, abort table generation after row
        else
          strdeste = strtblc1 -- name of the lang in the lang itself
          if (strtblc1=="-") then -- nice to have, do not abort
            strbkn = 'FFD8D8' -- redish if no "lang in the lang"
            numerrkec = numerrkec + 1
          end--if
        end--if
        strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
        optconcat (strt3d .. strdeste .. constrtden) -- done "d02"

        strtblc2 = piksubstrind.ek { args = { strsrcrw, "2" } } -- bg src "c2"
        strtblc2 = lfpreproeqmi (strtblc2) -- "="->"-" but no rl-enclos possib
        strtblc2 = lfclamp(strtblc2,10) -- constructed and antique status
        numtamp = string.len(strtblc2) -- length after clamping

        strbkn = constrbkco -- color code without "#" cross -- bg dest "d03"
        boolocerr = false
        if (strtblc2=="-") then -- nice to have, do not abort
          strbkn = 'FFD8D8' -- redish if no "constructed and antique status"
          strdeste = "-"
          numerrkec = numerrkec + 1
        else
          if (numtamp~=1) then -- length after clamping
            boolocerr = true
          else
            numoct = string.byte (strtblc2,1,1) -- must be "0" ... "3"
            if ((numoct<48) or (numoct>51)) then
              boolocerr = true -- this will become "boosinerr = true"
            else
              if (numoct==49) then
                strbkn = 'D0FFD8' -- greenish
              end--if
              if (numoct==50) then
                strbkn = 'A0FFC0' -- more greenish (but not green)
              end--if
              if (numoct==51) then
                strbkn = 'D0D0D0' -- grey
              end--if
              strdeste = contabd03[numoct-47] -- "contabd03" is ONE-based
              strdeste = strdeste .. ' (' .. string.char(numoct) .. ')'
            end--if
          end--if (numtamp~=1) else
        end--if (strtblc2=="-") else
        if (boolocerr) then
          strbkn = 'FFB0B0' -- red -- error overrides decoration
          strdeste = lfevilitem(0,2,strtblc2) -- show the evil -- "bad code"
          boosinerr = true -- this criminal, abort table generation after row
        end--if
        strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
        optconcat (strt3d .. strdeste .. constrtden) -- done "d03"

        strtblc3 = piksubstrind.ek { args = { strsrcrw, "3" } } -- bg src "c3"
        strtblc3 = lfpreproeqmi (strtblc3) -- "="->"-" but no rl-enclos possib
        strtblc3 = lfclamp(strtblc3,10) -- 2-letter code or "--" expected
        if (strtblc3=="--") then
          booc3bad = false -- 2 valid alternative values "-" and "--" exist
        else
          booc3bad = (not lfvalidatestr(strtblc3,"-",2,2,2,3))
        end--if -- nice to have -- done "c3"

        strbkn = constrbkco -- color code without "#" cross -- bg dest "d04"
        if (booc3bad) then
          strbkn = 'FFB0B0' -- red
          strdeste = lfevilitem(0,3,strtblc3) -- show the evil -- "bad code"
          boosinerr = true -- this criminal, abort table generation after row
        else
          strdeste = strtblc3
          if (strtblc3=="-") then -- nice to have
            strbkn = 'FFD8D8' -- redish if no ISO 639-1:2002 code
            numerrkec = numerrkec + 1
          end--if
        end--if
        strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
        optconcat (strt3d .. strdeste .. constrtden) -- done "d04"

        strtblc4 = piksubstrind.ek { args = { strsrcrw, "4" } } -- bg src "c4"
        strtblc4 = lfpreproeqmi (strtblc4) -- "="->"-" but no rl-enclos possib
        strtblc4 = lfclamp(strtblc4,10) -- 3-letter code or "---" expected
        if (strtblc4=="---") then
          booc4bad = false -- 2 valid alternative values "-" and "---" exist
        else
          booc4bad = (not lfvalidatestr(strtblc4,"-",3,3,2,3))
        end--if -- nice to have -- done "c4"

        strbkn = constrbkco -- color code without "#" cross -- bg dest "d05"
        if (booc4bad) then
          strbkn = 'FFB0B0' -- red
          strdeste = lfevilitem(0,4,strtblc4) -- show the evil -- "bad code"
          boosinerr = true -- this criminal, abort table generation after row
        else
          strdeste = strtblc4
          if (strtblc4=="-") then -- nice to have
            strbkn = 'FFD8D8' -- redish if no ISO 639-3:2007 code
            numerrkec = numerrkec + 1
          end--if
        end--if
        strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
        optconcat (strt3d .. strdeste .. constrtden) -- done "d05"

        if (bookapsow) then -- column "d06" can be hidden !!!
          strbkn = constrbkco -- color code without "#" cross -- begin "d06"
          if (booc0bad) then
            strbkn = 'FFB0B0' -- red
            strdeste = "??" -- kat with words (we have already seen bad "c0")
          else
            strtmp = lfpresufkap(constrd06km,strtblc0) -- augment and maybe uc
            strdeste = "[[:" .. constrkatp .. strtmp .. "|" .. constrkatp .. '<br>' .. strtmp .. "]]"
            if (bookapexp and boorussia) then
              bootimp,strtpm = lfquer2kat (mwframent,strtmp)
              strdeste = strdeste .. strtpm -- add 1 or 2 further lines
              numamoexp = numamoexp + 2 -- count expensive calls
              if (bootimp) then
                strbkn = 'FFD8D8' -- redish if "kap" kat does not exist
                numerrkap = numerrkap + 1
              end--if
            end--if (bookapexp and boorussia) then
          end--if
          strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
          optconcat (strt3d .. strdeste .. constrtden) -- done "d06"
        end--if (bookapsow) then

        if (boovorsow) then -- column "d07" can be hidden !!!
          strbkn = constrbkco -- color code without "#" cross -- beg dest co 7
          if (booc0bad) then
            strbkn = 'FFB0B0' -- red
            strdeste = "??" -- kat with dictiona (we have already seen bad c0)
          else
            strtmp = lfpresufkap(constrd07vm,strtblc0) -- augment and maybe uc
            strdeste = "[[:" .. constrkatp .. strtmp .. "|" .. constrkatp .. '<br>' .. strtmp .. "]]"
            if (boovorexp and boorussia) then
              bootimp,strtpm = lfquer2kat (mwframent,strtmp)
              strdeste = strdeste .. strtpm -- add 1 or 2 further lines
              numamoexp = numamoexp + 2 -- count expensive calls
              if (bootimp) then
                strbkn = 'FFD8D8' -- redish if "vor" kat does not exist
                numerrvor = numerrvor + 1
              end--if
            end--if (boovorexp and boorussia) then
          end--if
          strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
          optconcat (strt3d .. strdeste .. constrtden) -- dn dest column 7
        end--if (boovorsow) then

        if (booidxsow) then -- column "d08" can be hidden !!!
          strbkn = constrbkco -- color code without "#" cross -- beg dest co 8
          if (booc0bad) then
            strbkn = 'FFB0B0' -- red
            strdeste = "??" -- index page (we have already seen bad c0)
            boosinerr = true -- this criminal, abort table generation aftr row
          else
            strtmp = lfpresufkap(constrd01d08,strtblc0) -- augment and maybe uc
            strtmp = constrindp .. strtmp -- add the "Index:" prefix
            strdeste = '[[' .. strtmp .. ']]' -- brew the wikilink
            if (booidxexp and boorussia) then
              vartmp = mwframent:callParserFunction(('#ifexist:'..strtmp),'1','0')
              numamoexp = numamoexp + 1 -- count expensive calls
              if (vartmp~='1') then
                strbkn = 'FFD8D8' -- redish if index page does not exist
                strdeste = strdeste .. '<br>(' .. constrbual .. ')'
                numerrind = numerrind + 1
              end--if
            end--if (booidxexp and boorussia) then
          end--if
          strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
          optconcat (strt3d .. strdeste .. constrtden) -- dn dest column 8
        end--if (booidxsow) then

        booc5c6bad = false -- common for "c5" and "c6"

        strtblc5 = piksubstrind.ek { args = { strsrcrw, "5" } } -- bg src "c5"
        strtblc5 = lfpreproeqmi (strtblc5) -- "="->"-" but no rl-enclos possib
        strtblc5 = lfclamp(strtblc5,16) -- wiki access code
        numtamp = string.len(strtblc5) -- length after clamping
        if (strtblc5~="-") then -- nice to have
          numoct = string.byte(strtblc5,1,1) -- wiki access code
          if ((numtamp<2) or (numtamp>10) or (lftestlc(numoct)==false)) then
            booc5c6bad = true -- this will become "boosinerr = true"
          end--if
        end--if -- done "c5"

        strtblc6 = piksubstrind.ek { args = { strsrcrw, "6" } } -- bg src "c6"
        strtblc6 = lfpreproeqmi (strtblc6) -- "="->"-" but no rl-enclos possib
        strtblc6 = lfclamp(strtblc6,10) -- availability 2 digits
        numtamp = string.len(strtblc6) -- length after clamping
        if (strtblc6~="-") then -- nice to have
          if (numtamp==2) then
            numc6pedi = string.byte(strtblc6,1,1) -- availability code
            numc6tion = string.byte(strtblc6,2,2) -- availability code
            numc6pedi = lfdec1diglm (numc6pedi,2) -- 0...2 or 255 if invalid
            numc6tion = lfdec1diglm (numc6tion,2) -- 0...2 or 255 if invalid
            if ((numc6pedi==255) or (numc6tion==255)) then
              booc5c6bad = true -- this will become "boosinerr = true"
            end--if
          else
            booc5c6bad = true -- this will become "boosinerr = true"
          end--if
        end--if -- done "c6"

        strbkn = constrbkco -- color code without "#" cross -- bg dest "d09"
        strdeste = '-'
        if ((booc5c6bad==false) and (strtblc5~="-")) then
          strbkn = lfavailco(numc6pedi)
          strdeste = lfbrewurl (strtblc5,false,nil) -- other ipedia main page
          strdeste = strdeste .. lfavailnt(numc6pedi) -- <br>+notice or empty
        end--if
        if (booc5c6bad) then
          strbkn = 'FFB0B0' -- red -- error overrides decoration
          strdeste = lfevilitem(0,56,strtblc5) -- show the evil -- "bad code"
          boosinerr = true -- this criminal, abort table generation after row
        end--if
        strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
        optconcat (strt3d .. strdeste .. constrtden) -- dn dest column 9

        strbkn = constrbkco -- color code without "#" cross -- bg dest "d10"
        strdeste = '-'
        if ((booc5c6bad==false) and (strtblc5~="-")) then
          if (strtblc5==constrpriv) then
            strdeste = ':-)' -- only for "d10" cell "other tionary"
          else
            strbkn = lfavailco(numc6tion)
            strdeste = lfbrewurl (strtblc5,true,nil) -- other tionary main page
            strdeste = strdeste .. lfavailnt(numc6tion) -- <br>+notice or empt
          end--if
        end--if
        if (booc5c6bad) then
          strbkn = 'FFB0B0' -- red -- error overrides decoration
          strdeste = lfevilitem(0,56,strtblc6) -- show the evil -- "bad code"
          boosinerr = true -- this criminal, abort table generation after row
        end--if
        strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
        optconcat (strt3d .. strdeste .. constrtden) -- done "d10"

        strtblc7 = piksubstrind.ek { args = { strsrcrw, "7" } } -- begin "c7"
        strtblc7 = lfpreproeqmi (strtblc7) -- "="->"-" but no rl-enclos possib
        booc7bad = (not lfvalidatestr(strtblc7,"-",2,32,0,0))
        strtblc7 = lfclamp(strtblc7,36) -- name of ipedia article -- done "c7"

        strbkn = constrbkco -- color code without "#" cross -- bg dest "d11"
        if (booc7bad) then -- "c7" is bad
          strbkn = 'FFB0B0' -- red
          strdeste = lfevilitem(2,7,strtblc7) -- show the evil -- "bad title"
          boosinerr = true -- this criminal, abort table generation after row
        else
          if ((strtblc7=="-") and booc0bad) then -- nice to have "c7"
            strbkn = 'FFB0B0' -- red if we have neither "c0" nor "c7"
            strdeste = '-'
            boosinerr = true -- this criminal, abort table generation aftr row
          else
            strtmp = strtblc7 -- name of wp article, BEWARE: may contain space
            bootimp = false
            if (strtmp=="-") then
              bootimp = true -- this is semi-evil, we have to guess
              strtmp = lfpresufkap(constrd11wm,strtblc0) -- augment and maybe uc
            end--if
            strdeste = lfbrewurl (constrpriv,false,strtmp) -- own ipedia article
            if (bootimp) then
              strbkn = 'FFD8D8' -- redish if we had to guess
              strdeste = strdeste .. ' (??)'
              numerrkec = numerrkec + 1
            end--if
          end--if
        end--if
        strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
        optconcat (strt3d .. strdeste .. constrtden) -- done "d11"

        strtblc8 = piksubstrind.ek { args = { strsrcrw, "8" } } -- bg src "c8"
        strtblc8 = lfpreproeqmi (strtblc8) -- "="->"-" and rl-enclos possible
        strtblc8 = lfrlstrip(strtblc8) -- category link
        numtamp = string.len(strtblc8) -- length after stripping before clamp
        strtblc8 = lfclamp(strtblc8,(connummaxc8catlen+4)) -- cat link "tamp"

        strtblc9 = piksubstrind.ek { args = { strsrcrw, "9" } } -- bg src "c9"
        strtblc9 = lfpreproeqmi (strtblc9) -- "="->"-" but no rl-enclos possib
        numtump = string.len(strtblc9) -- length before clamping
        strtblc9 = lfclamp(strtblc9,12) -- amount -- variable is "tump"

        strbkn = constrbkco -- color code without "#" cross -- bg dest "d12"
        boolocerr = false
        boolokeer = false
        if (strtblc8~="-") then -- do NOT evaluate evilness of "-" in "c8"
          if ((numtamp<8) or (numtamp>connummaxc8catlen)) then -- "c8" bad
            boolocerr = true -- length out of range
          else
            if (lfcountchr(strtblc8,58)~=1) then -- c8 bad
              boolocerr = true -- bad amount of colons, ONE is required
            end--if
          end--if
        end--if
        if (strtblc9~="-") then -- do NOT evaluate evilness of "-" in "c9"
          if (numtump>8) then -- c9 bad
            boolokeer = true -- length out of range (no minimum)
          else
            if (lfcountndg(strtblc9)~=0) then -- c9 bad
              boolokeer = true -- faulty char:s, a number is expected
            end--if
          end--if
        end--if
        if (boolocerr or boolokeer) then
          strbkn = 'FFB0B0' -- red if crime in "c8" or "c9"
          strdeste = '' -- preset to empty, may be needed below
          if (boolocerr) then
            strdeste = lfevilitem(3,8,strtblc8) -- show evil "bad category"
          end--if
          if (boolocerr and boolokeer) then
            strdeste = strdeste .. '<br>and<br>' -- damn: 2 crimi err in 1 row
          end--if
          if (boolokeer) then
            strdeste = strdeste .. lfevilitem(4,9,strtblc9) -- ev "bad amount"
          end--if
          boosinerr = true -- this criminal, abort table generation after row
        else
          if (strtblc8=='-') then
            strbkn = 'FFD8D8' -- redish if no category
            strdeste = '-'
            numerrkec = numerrkec + 1
          else
            if (numtamp>nummaxkal) then
              nummaxkal = numtamp -- new record established !!!
            end--if
            strdeste = lfbrewurl (strtblc5,true,strtblc8) -- other tionary cat
            strdeste = strdeste .. '<br>'
            if (strtblc9=="-") then
              strdeste = strdeste .. lfamountinkat(nil) -- NOT count as error
            else
              numtump = tonumber(lfremovenondi(strtblc9)) -- apo:s tolerable
              strdeste = strdeste .. lfamountinkat(numtump) -- apo:s added
            end--if (strtblc9=='-') else
          end--if (strtblc8=='-') else
        end--if (boolocerr or boolokeer) else
        strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
        optconcat (strt3d .. strdeste .. constrtden) -- done "d12"

      end--if ((boomxwerr==false) and (boosinerr==false)) then

      optconcat ('</tr>') -- close table row

      if (boomxwerr or boosinerr) then
        break -- something is evil, abort now that table row is finished
      end--if

      if (numipos==numtblend) then
        numrowinx = numrowinx + 1 -- otherwise "numrowinx" is off-by-one
        break -- success !!! -- done with the table
      end--if

      numtblper = numipos -- risk of "boomxwerr" error here, preventively set
      isubnumlio = numtblend - numipos -- here do NOT "+1" NOT interested EOL
      if (isubnumlio>conmaxwidth) then
        isubnumlio = conmaxwidth -- do NOT subtract here
      end--if
      isubnumchr = 91 -- search for "[["
      isubboodwn = false
      searchdblchr () -- OUT: osubboofnd | USE: constrtbl | CHG: numipos
      if (osubboofnd==false) then
        boomxwerr = true
        break -- "[[" NOT found
      end--if
      numtamp = numipos - numiprev -- evaluated width from "[[" to "[["
      if (numtamp>conmaxwidth) then
        boomxwerr = true
        break -- "maxwidth" violated
      end--if
      if (numtamp<numminwid) then
        numminwid = numtamp -- new negative record established !!!
      end--if
      if (numtamp>nummaxwid) then
        nummaxwid = numtamp -- new record established !!!
      end--if

      numtblper = numipos -- risk of "boosinerr" error here, preventively set
      if ((numipos+conminwidth)>=numtblend) then
        boosinerr = true
        break -- truncation
      end--if

      strtblcy = '' -- next access code
      numfoulen =  0 -- index 0...2 -- ZERO-based

      while (true) do -- check access code (2 or 3 letters)
        numoct = string.byte (constrtbl,(numipos+3+numfoulen),(numipos+3+numfoulen))
        if (numoct==93) then
          break -- "]" fnd -- good (numfoulen is 2 or 3) or bad (numfoulen<2)
        end--if
        if (numfoulen==3) then
          boosinerr = true
          break -- access code too long -- bad
        end--if
        if (lftestlc(numoct)==false) then
          boosinerr = true -- only lowercase letters accepted
          break
        end--if
        strtblcy = strtblcy .. string.char (numoct)
        numfoulen = numfoulen + 1 -- increment for every seized lowercase char
      end--while

      if ((numfoulen<2) or (numfoulen>3)) then
        boosinerr = true -- must be 2 or 3 letters
      end--if
      numoct = string.byte (constrtbl,(numipos+4+numfoulen),(numipos+4+numfoulen))
      if (numoct~=93) then
        boosinerr = true  -- two "]" required (the former one checked earlier)
      end--if
      numoct = string.byte (constrtbl,(numipos+5+numfoulen),(numipos+5+numfoulen))
      if (numoct~=32) then
        boosinerr = true  -- space required
      end--if

      if (boosinerr) then
        break -- coming line not valid
      end--if

      boosorerr = false -- maybe we will set it below and report it above
      if (numrowinx>0) then -- sorting NOT required after line 0
        cmp2or3wordbi () -- OUT: osubboobiger | USE: constrtbl, numiwo
        if (osubboobiger==false) then
          numsorerr = numsorerr + 1
          boosorerr = true -- sorting error, report it later
        end--if
      end--if

      numiwo0 = string.byte (strtblcy,1,1) -- bkp next code for overnext check
      numiwo1 = string.byte (strtblcy,2,2)
      if (string.len(strtblcy)==3) then
        numiwo2 = string.byte (strtblcy,3,3)
      else
        numiwo2 = 0
      end--if
      numinxlen = numfoulen -- backup next length for overnext check
      numrowinx = numrowinx + 1

    end--while

  end--if ((booerr==false) and (booearsyn==false)) then

  ---- CLOSE THE OUTPUT TABLE IF IT EXISTS AND WHINE IF NEEDED ----

  if ((booerr==false) and (booearsyn==false)) then
    if (boohavtbl) then
      optconcat ('</table>')
    end--if
    if (boomxwerr) then
      optconcat (constrmxwe) -- whine outside the table -- "maxwidth" violat
    end--if
    if (boosinerr) then
      optconcat (constrsexe) -- whine outside the table -- other error
    end--if
  else
    isubtabbunch = {} -- crucial
    strret = constrfate -- fatal error -- replace content of the string
  end--if

  ---- MERGE BAD NEWS ----

  -- * "boogtabort" is brewed from 3 var and implies that "numtblper" is valid
  -- * "boodofatal" is brewed from 6 var and activates the fatal block
  -- * we become fatal if:
  --   - booerr (no table then)
  --   - booearsyn (no table then, but "numtblper" is valid)
  --   - boosinerr or boomxwerr (table generation aborted)
  --   - (numsorerr<>0) or (numerrtlo<>0)

  boogtabort = (booearsyn or boosinerr or boomxwerr) -- "numtblper" valid
  boodofatal = (booerr or boogtabort or (numsorerr~=0) or (numerrtlo~=0))

  ---- BREW THE FATAL WARNING BLOCK OR TINY BLOCK ----

  -- * block is displayed in any case and enclosed in a "div" box in any case,
  --   but the style heavily depends of "boodofatal" fatality
  -- * font size 200% or 100% (default), text color red or black (default),
  --   align center

  if (boodofatal) then
    strtmp = '<div style="margin:0.5em auto 0.5em auto; padding:0.5em; border:0.5em solid #FF0060; text-align:center;">'
    strtmp = strtmp .. '<span style="font-size:200%; color:#FF0060">'
    strtmp = strtmp .. contabfata[0] .. '. ' .. strpurge .. ' ' .. contabfata[1]
    strtmp = strtmp .. ' ' .. constrsumbr .. ' ' .. contabfata[2] .. '. ' .. contabfata[3]
    strtmp = strtmp .. '.</span></div>'
  else
    strtmp = '<div style="margin:0.5em auto 0.5em auto; padding:0.5em; border:1px solid #000000; text-align:center;">'
    strtmp = strtmp .. strpurge .. ' ' .. constrtinyb .. ' ' .. constrsumbr .. '.</div>'
  end--if

  ---- BREW THE SUMMARY BLOCK ----

  -- * the summary block is enclosed in a single-cell table since
  --   a "div" box would fill the complete screen width
  -- * using a "ul/li" type list (note that wikicode "*" would NOT work here)
  -- * font size 80%, text color black (default), align left (default)

  if (boodofatal or boosummar) then

    strsumbl = '<table style="margin:0.5em auto 0.5em auto; padding:0.5em; border:1px solid #000000;">'
    strsumbl = strsumbl .. '<tr><td><span style="font-size:80%;"><ul>'

    strsumbl = strsumbl .. '<li>' .. contabsum[0] -- 2 parameters (one of them is optional)
    strsumbl = strsumbl .. '"' .. strpara .. '", ' .. tostring(numproba) .. '</li>'

    strsumbl = strsumbl .. '<li>' .. contabsum[1] .. lfbunch(tostring(numtbllen)) .. '</li>' -- source
    strsumbl = strsumbl .. '<li>' .. contabsum[2] .. lfbunch(tostring(numrowinx)) .. '</li>' -- lang
    strsumbl = strsumbl .. '<li>' .. contabsum[3] .. lftostwa(numsorerr) .. '</li>' -- sort
    strsumbl = strsumbl .. '<li>' .. contabsum[4] .. lfbunch(tostring(numerrtru)) .. '</li>' -- trunc (ele)
    strsumbl = strsumbl .. '<li>' .. contabsum[5] .. lftostwa(numerrtlo) .. '</li>' -- too long (ele)
    strsumbl = strsumbl .. '<li>' .. 'errkec : ' .. lfbunch(tostring(numerrkec)) .. '</li>' -- minor
    strsumbl = strsumbl .. '<li>' .. 'errkap : ' .. lfbunch(tostring(numerrkap)) .. '</li>' -- kap
    strsumbl = strsumbl .. '<li>' .. 'errvor : ' .. lfbunch(tostring(numerrvor)) .. '</li>' -- vor
    strsumbl = strsumbl .. '<li>' .. 'errind : ' .. lfbunch(tostring(numerrind)) .. '</li>' -- missing index page
    strsumbl = strsumbl .. '<li>' .. 'tblbeg : ' .. lfbunch(tostring(numtblbeg)) .. '</li>' -- bloat
    strsumbl = strsumbl .. '<li>' .. 'tblend : ' .. lfbunch(tostring(numtblend)) .. '</li>' -- bloat

    strsumbl = strsumbl .. '<li>' .. 'tblper : ' -- earliest abort syntax err
    if (boogtabort) then
      strsumbl = strsumbl .. lfbunch(tostring(numtblper)) .. constrexcla -- just " !!!" with some style
    else
      strsumbl = strsumbl .. 'N/A'
    end--if
    strsumbl = strsumbl .. '</li>'

    strsumbl = strsumbl .. '<li>' .. 'eval minwid, const minwid : ' -- minwidth
    strsumbl = strsumbl .. tostring(numminwid) .. ', ' .. tostring(conminwidth) .. '</li>'
    strsumbl = strsumbl .. '<li>' .. 'eval maxwid, const maxwid : ' -- maxwidth
    strsumbl = strsumbl .. tostring(nummaxwid) .. ', ' .. tostring(conmaxwidth) .. '</li>'
    strsumbl = strsumbl .. '<li>' .. 'eval maxkatlink, const maxkatlink : '
    strsumbl = strsumbl .. tostring(nummaxkal) .. ', ' .. tostring(connummaxc8catlen) .. '</li>'

    strsumbl = strsumbl .. '<li>' .. 'amoexp : ' -- expensive calls
    strsumbl = strsumbl .. lfbunch(tostring(numamoexp))
    if (numamoexp>500) then
      strsumbl = strsumbl .. constrexcla -- just " !!!" with some style
    end--if
    strsumbl = strsumbl .. '</li>'

    strsumbl = strsumbl .. '</ul></span></td></tr></table>'

  end--if

  ---- BREW THE FINAL HUGE STRING ----

  optconcat (nil) -- crucial, finalizes "strret"
  if (boodofatal or boosummar) then
    strret = strret .. strsumbl -- add summary block
  end--if
  strret = strtmp .. strret .. strtmp -- add fatal warn or tiny block 2 times

  ---- RETURN THE JUNK STRING ----

  return strret

end--function

  ---- RETURN THE JUNK LUA TABLE ----

return komtbllin