Modulo:mkomtbllin

El Vikivortaro
Salti al navigilo Salti al serĉilo
--[===[

MODULE "MKOMTBLLIN" (kompleta tabelo kun lingvoj)

"eo.wiktionary.org/wiki/Modulo:mkomtbllin" <!--2022-Sep-25-->
"id.wiktionary.org/wiki/Modul:mkomtbllin"d

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 / Behoevda submoduler:
- "mtbllingvoj" in turn requiring template "tbllingvoj" (EO)
- "mtblbahasa" in turn requiring template "tblbahasa" (ID)
- "mpiksubstrind"

Incoming: * optional anonymous
            - brew and show technical summary block on success (binary
              digit "0" or "1", default "0" ie false)
          * optional anonymous
            - string with 2 decimal digits "02"..."98" reducing probability
              to call expensive parser functions, default is 1 ie 100%
          * named obligatory parameter
            * "infsel=" column control -- string with 6 char:s (tristate
                        options: "0" do not show | "1" show no query |
                        "2" show and query)
              * "d07" "tln" top lng cat (0 or 1 only, no query)
              * "d07" "kap" cat
              * "d08" "vor" cat (0 or 1 only, no query)
              * "d08" "mal" cat
              * "d09" "apx" appendix (0 or 1 only, no query)
              * "d09" "ind" index
          * named optional parameter
            * "detrc=true" to create trace debug report

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 "mtbllingvoj" 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 "mtbllingvoj" eldonos aux utilan
rezulton aux almenaux signocxenon "Grava eraro".

The function of this module is governed by
the "Specification of the 2-dimensional table picking system".
- y-index markers are obligatory and
  lowercase (numbers and "-" not yet allowed) !!!FIXME!!!
- x-index markers are disallowed

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 marker "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+11 columns:
- cy : y-index marker (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 : QID (for example "Q5432") "Q" + 2...8 digits, earliest digit
       "1"..."9", further digits "0"..."9"
- c2 : name of the language in the language itself
       ("propralingve") (may be rl-enclosed)
- c3 : constructed and antique status (digit "0"..."3")
- c4 : ISO 639-1:2002 2-letter code (only lowercase)
- c5 : ISO 639-3:2007 3-letter code (only lowercase)
- c6 : wiki access code, itself usually same as "cy", but may be different
       and longer up to 10 char:s, for example "zh-min-nan", leave it "-"
       here if code is same or unknown, use "??" if code belongs to
       other language ("als.pedia.org")
- c7 : wiki availability code (2 digits "0"..."2" ie "00"..."22"),
       "-" causes reddish background and no info about availability
- c8 : name of ipedia article, base principle usually
       followed (there are some exceptions):
       - EO: core word usually AJ name with uppercased begin
             followed by " lingvo", no "la" article
       - ID: prefixed by "Bahasa " and core word begins with uppercase letter
- c9 : category with our site language ("eo" or "id") in other tionary
       (with category NS prefix, but without language prefix, without "]]"
       or other nonsense, may be rl-enclosed, can be absurdly long
       "Rummad:Wikeriadur:Distagaduriou' a vank en indonezeg" has 52
       octet:s and even worse 2 apo:s)
- c10 : number 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 highly 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)
- technical 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 destination table with 14 columns:
- d00 : - index (in brackets, not bold)
        - space
        - language access code (bold) (literally peeked from "cy"
          y-index marker 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 by "lfinsertultim"
          according to control string "contabpages[0]")
- d02 : - QID (for example "Q5432") !!!FIXME!!! not yet used
- d03 : - name of the language in the language itself
          (literally peeked from "c1" in the source table)
- d04 : - constructed and antique status (expanded from digit "0"..."3"
          peeked from "c2" in the source table)
        # adjust background to greenish or grey if applicable
- d05 : - "ISO 639-1:2002" 2-letter language code
          (literally peeked from "c3" in the source table)
- d06 : - "ISO 639-3:2007" 3-letter language code
          (literally peeked from "c4" in the source table)
- d07 : - ? link to the "tln" top lng category in own tionary if
            desired, no page count here
        - ? EOL (only if both cat:s are desired)
        - ? link to the "kap" category in own tionary with all words in
            the language (constructed from constant string "constrkatq"
            (category namespace prefix without ":") and "c0" augmented by
            "lfinsertultim" according to control string "contabpages[6]")
          - ? EOL (if complaint below exists)
          - ? complaint about not existing if applicable
          - ? EOL (if the "parent" link to the "kap" category is present)
          - ? number of pages (queried) or "??" if querying does not work
        # adjust background to reddish if the category (one of two)
          does not exist
        ! depends on variables "bootlnsow" and "bootlnexp" and "bookapsow"
          and "bookapexp" and includes expensive querying (2), column
          can be completely hidden by "bood07"
- d08 : - ? link to the "vor" category in own tionary with all dictionaries in
            the language (constructed from constant string "constrkatq"
            (category namespace prefix without ":") and "c0" augmented by
            "lfinsertultim" according to control string "contabpages[3]"), no
            page count here
        - ? EOL (only if both cat:s are desired)
        - ? link to the "mal" template cat
          - ? EOL (if complaint below exists)
          - ? complaint about not existing if applicable
          - ? EOL (if the "parent" link to the "mal" template cat is present)
          - ? number of pages (queried) or "??" if querying does not work
        # adjust background to reddish if the category (one of two)
          does not exist
        ! depends on variables "boovorsow" and "boovorexp" and "boomalsow"
          and "boomalexp" and includes expensive querying (2), column
          can be completely hidden by "bood08"
- d09 : - link to the appendix page (constructed from constant string
          "constrapxq" (appendix namespace prefix without ":") and "c0"
          augmented by "lfinsertultim" according to control string
          "contabpages[1]") controlled by "booapxsow"
        - EOL (only if both pages are desired)
        - link to the index page in own tionary with
          the language (constructed from constant string "constrindq"
          (index namespace prefix without ":") and "c0" augmented by
          "lfinsertultim" according to control string "contabpages[2]")
        # adjust background to reddish if at least one of them does not exist
        ! depends on variables "booapxsow" and "booapxexp" and "booindsow"
          and "booindexp" and includes expensive querying (1), column
          can be completely hidden by "bood09"
- d10 : - quasi-external link to wikipedia in the language concerned
          (constructed from "c5" and "c6" and "cy", irrespective availability)
        - EOL (if note below exists)
        - note about bad availability of the wiki if applicable
        # adjust background to grey according to bad availability
        ! no expensive querying here
- d11 : - quasi-external link to tionary in the language concerned
          (constructed from "c5" and "c6" and "cy", irrespective availability)
        - EOL (if note below exists)
        - note about bad availability of the wiki if applicable
        # adjust background to grey according to bad availability
        ! no expensive querying here
        & special rule ie blocking for own site language
- d12 : - 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 using "lfinsertultim" from "c0"
          and "contabpages[7]" and " (??)" is added)
        # adjust background to reddish if "c7" is not available
        ! no expensive querying here
- d13 : - quasi-external link to EO or ID category in the tionary in the
          language concerned (peeked from "c8" in the source table)
        - EOL (if number of articles below exists)
        - number of articles (peeked from "c9" in the source table)
        # adjust background to reddish if "c8" or "c9" is not available
        ! no expensive querying here
        & special rule ie blocking for own site language

Expensive querying:
There are up to 6 expensive queries (2 cat:s plus appendix plus index, one
cat costs 2 bucks ("ifexist" and "pagesincategory") per page, appendix and
index cost one buck per page) per language and thus table row. This is a big
problem in "mkomtbllin" but in "msngtbllin" it is no problem at all. The hard
limit set by wiki software is 500. The totally fired number of calls can be
reduced via parameters "bootlnexp" "bookapexp" "boovorexp" "boomalexp"
"booapxexp" "booindexp" and "numproba". We even have a fraud implemented.

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 "#E01 Grava eraro" then, no huge table and no
  technical summary block, fatal warning YES, position_err 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 "#E01 Grava eraro" then, no huge table and no summary,
  fatal warning YES, position_err 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
  "#E15 Linio estas tro longa", 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
  "#E16 Sintaksa eraro" is outside the table, summary YES, fatal warning YES
- "sort_error" temporarily set to true and "sort_error" 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 !!!FIXME!!! not used anymore
- "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
- "numerrmal" (no bool) incremented
- "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 exporttable = {}

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

---- CONSTANTS [O] ----

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

  -- uncommentable EO vs ID constant strings (core site-related features)

  local constrpriv = "eo"                    -- EO (privileged site language)
  -- local constrpriv = "id"                    -- ID (privileged site language)
  local construsmo = "Modulo:mtbllingvoj"    -- EO (komp YES sng NO)
  -- local construsmo = "Modul:mtblbahasa"      -- ID (komp YES sng NO)
  local constrpiks = "Modulo:mpiksubstrind"  -- EO
  -- local constrpiks = "Modul:mpiksubstrind"   -- ID
  local constrkatq = "Kategorio"             -- EO (used only via "lfykattlaenk")
  -- local constrkatq = "Kategori"              -- ID
  local constrindq = "Indekso"               -- EO
  -- local constrindq = "Indeks"                -- ID
  local constrapxq = "Aldono"                -- EO (used only via "lfyapxindlaenk")
  -- local constrapxq = "Lampiran"              -- ID

  -- constant table translating x-indexes for "lfyseizesubstring"
  -- valid indexes 0...10 covering totally 11 columns "c0"..."c10"

  local contabrxi = {[0]=0,1,2,3,4,5,6,7,8,9,10}

  -- constant table (ban list) !!!FIXME!!! unused

  -- add only obviously invalid access codes (2-letter or 3-letter)

  -- length of the list is NOT stored anywhere, the processing stops
  -- when type "nil" is encountered

  -- "en.wiktionary.org/wiki/Wiktionary:Language_treatment" excluded languages
  -- "en.wikipedia.org/wiki/Spurious_languages"
  -- "iso639-3.sil.org/code/art" only valid in ISO 639-2
  -- "iso639-3.sil.org/code/zxx" "No linguistic content"

  local contabisbanned = {}
  contabisbanned = {'by','dc','ll','jp','art','cmn','deu','eng','epo','fra','gem','ger','ido','lat','por','rus','spa','swe','tup','zxx'} -- 1...20

  -- 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 (HTML)

  local constrfrco = '2020E0'                                      -- table frame color (blue) (use only here in this block)
  local constrbord = 'border:0.25em solid #' .. constrfrco .. ';'  -- part of "style" element (use only here in this block)

  local constrbkco = 'FFFFD0'                                      -- default cell background color (light yellow) (used in main)
  local constrhutabegin = '<table style="' .. constrbord .. 'margin:0.5em auto 0.5em auto;border-collapse:collapse;text-align:center;"><tr>'
  local constrtdbgtit = '<td style="' .. constrbord .. 'padding:0.4em;">'         -- colspan NO color NO (title line)
  local constrtddf = '<td style="' .. constrbord .. 'padding:0.4em;background:#'  -- colspan NO color YES (content)
  local constrtdfd = ';">'                                                        -- part of HTML table code after HEX color
  local constrtden = '</td>'

  -- constant strings (error circumfixes)

  local constremibg = '<span class="error">'     -- mini whining begin
  local constremien = '</span>'                  -- mini whining end
  local constrelabg = '<span class="error"><b>'  -- lagom whining begin
  local constrelaen = '</b></span>'              -- lagom whining end
  local constrlaxhu = '&nbsp;&#91;&#93;&nbsp;'   -- lagom -> huge circumfix " [] "
  local constrexcla = '&nbsp;' .. constremibg .. '!!!' .. constremien  -- just " !!!" with some style (komp YES sng NO)

  -- uncommentable EO vs ID constant table (error messages)

  -- #E01...#E17, note that #E00 is NOT supposed to be included here
  -- #E02...#E13 come from submodule

  local contaberaroj = {}
  contaberaroj[01] = 'Grava eraro'                                     -- EO (huge) fate #E01
  -- contaberaroj[01] = 'Galat jahat'                                     -- ID (huge)
  contaberaroj[02] = 'Sxablono "tbllingvoj" ne trovita'                -- EO #E02
  -- contaberaroj[02] = 'Templat "tblbahasa" tidak ditemukan'             -- ID #E02
  contaberaroj[03] = 'Sxablono "tbllingvoj" havas malbonan grandecon'  -- EO #E03
  -- contaberaroj[03] = 'Ukuran templat "tblbahasa" salah'                -- ID #E03
  contaberaroj[04] = 'Du areoj'
  -- contaberaroj[04] = 'Dua lingkup'
  contaberaroj[05] = 'Longo de linio'
  -- contaberaroj[05] = 'Panjang baris'
  contaberaroj[06] = 'Malsukcesis eltiri elementojn'
  -- contaberaroj[06] = 'Ekstraksi elemen gagal'
  contaberaroj[07] = 'Ordiga eraro'
  -- contaberaroj[07] = 'Galat urutan'
  contaberaroj[08] = 'Duoblajxo en "cy"'
  -- contaberaroj[08] = 'Duplikat dalam "cy"'
  contaberaroj[09] = 'Duoblajxo en "c0"'
  -- contaberaroj[09] = 'Duplikat dalam "c0"'
  contaberaroj[10] = 'Duoblajxo en "c1"'
  -- contaberaroj[10] = 'Duplikat dalam "c1"'
  contaberaroj[11] = 'Nevalida lingvokodo'                                 -- EO #E11
  -- contaberaroj[11] = 'Kode bahasa tidak valid'                             -- ID #E11
  contaberaroj[12] = 'Nekompleta (ele) linio'                              -- EO (mini) neko #E12 !!!FIXME!!! collision dual meaning
  -- contaberaroj[12] = 'Garis tidak lengkap (ele)'                           -- ID (mini)
  contaberaroj[13] = 'Kvanto da linioj'                                    -- EO #E13
  -- contaberaroj[13] = 'Jumlah baris'                                        -- ID #E13
  contaberaroj[15] = 'Tro longa (ele) linio'                               -- EO (lagom) trol #E15
  -- contaberaroj[15] = 'Garis terlalu panjang (ele)'                         -- ID (lagom)
  contaberaroj[16] = 'Sintaksa eraro'                                      -- EO (huge) sexe #E16
  -- contaberaroj[16] = 'Kesalahan sintaks'                                   -- ID (huge)
  contaberaroj[17] = 'Linio estas tro longa (sgn, maxwid) aux sen EOL'     -- EO (huge) mxwe #E17 !!!FIXME!!! NOT used
  -- contaberaroj[17] = 'Garis terlalu panjang (kar, maxwid) atau tanpa EOL'  -- ID (huge)

  -- uncommentable EO vs ID constant table (titles for the table)

  -- * see "lfbrewtitsel" and note that contabmisc[0] is needed too
  -- * note that we can have 2 items in one cell but the non-bold title part
  --   "kvanto" cannot be doubled and must be shared if needed

  local contabdestit = {}
  contabdestit[00] = 'Alira lingva kodo'                                             -- EO
  -- contabdestit[00] = 'Kode akses bahasa'                                             -- ID
  contabdestit[01] = 'Nomo de la lingvo en EO kaj kapvorta pagxo'                    -- EO (all bold)
  -- contabdestit[01] = 'Nama bahasa dalam ID dan halaman lema'                         -- ID (all bold)
  contabdestit[02] = 'Vikidatumeja pagxo'                                            -- EO
  -- contabdestit[02] = 'Halaman wikidata'                                              -- ID
  contabdestit[03] = 'Lingvonomo propralingve'                                       -- EO
  -- contabdestit[03] = 'Nama bahasa dalam bahasa itu'                                  -- ID
  contabdestit[04] = 'Planlingva kaj antikva statuso'                                -- EO
  -- contabdestit[04] = 'Status buatan dan kuno'                                        -- ID
  contabdestit[05] = 'ISO 639-1:2002 2-litera kodo'            -- EO
  -- contabdestit[05] = 'ISO 639-1:2002 kode 2 huruf'             -- ID
  contabdestit[06] = 'ISO 639-3:2007 3-litera kodo'            -- EO
  -- contabdestit[06] = 'ISO 639-3:2007 kode 3 huruf'             -- ID
  contabdestit[07] = 'Cxefa kategorio%Kapvorta kategorio#kvanto da pagxoj'           -- EO  (colu can be hidden)
  -- contabdestit[07] = 'Kategori utama%Kategori lema#jumlah halaman'                   -- ID  (colu can be hidden)
  contabdestit[08] = 'Vortara kategorio%Sxablona kategorio#kvanto da pagxoj'         -- EO  (colu can be hidden)
  -- contabdestit[08] = 'Kategori kamus%Kategori templat#jumlah halaman'                -- ID  (colu can be hidden)
  contabdestit[09] = 'Aldono%Indekso'                                                -- EO  (colu can be hidden)
  -- contabdestit[09] = 'Lampiran%Indeks'                                               -- ID  (colu can be hidden)
  contabdestit[10] = 'Vikipedio en la lingvo'                                               -- EO
  -- contabdestit[10] = 'Wikipedia dalam bahasa itu'                                           -- ID
  contabdestit[11] = 'Vikivortaro en la lingvo'                                             -- EO
  -- contabdestit[11] = 'Wikikamus dalam bahasa itu'                                           -- ID
  contabdestit[12] = 'Artikolo pri la lingvo en EO vikipedio'                               -- EO
  -- contabdestit[12] = 'Artikel tentang bahasa itu dalam wikipedia ID'                        -- ID
  contabdestit[13] = 'Kategorio pri EO en vikivortaro en la lingvo#kvanto da pagxoj'        -- EO
  -- contabdestit[13] = 'Kategori tentang ID dalam wikikamus dalam bahasa itu#jumlah halaman'  -- ID

  -- uncommentable EO vs ID constant strings and tables (misc)

  local contabmisc = {}
  contabmisc[0] = "kaj"          -- EO coordinator "&"
  -- contabmisc[0] = "dan"          -- ID coordinator "&"
  contabmisc[1] = "ne ekzistas"  -- EO status of category pages lng kap vor
  -- contabmisc[1] = "tidak ada"    -- ID status of category pages lng kap vor

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

  -- uncommentable EO vs ID constant table (pagenames to be constructed)

  -- syntax of the insertion and discarding magic string:
  -- "@" followed by 2 uppercase letters and 2 hex numbers
  -- otherwise the hit is not expanded, but copied as-is instead
  -- 2 letters select the insertable item from table supplied by the caller
  -- 2 hex numbers control discarding left and right (0...15 char:s)

  -- insertable items defined:
  -- * LK lng code (for example "da" or "io" or "grc")
  -- * LN lng name native (for example "dana" or "Ido")
  -- * LU lng name uppercased (for example "Dana" or "Ido")

  -- see "lfinsertultim" and "tabstuff" use space here and avoid "_"

  local contabpages = {}
  contabpages[0] = "@LN00"                  -- EO lemma page in NS ZERO
  -- contabpages[0] = "bahasa @LN00"           -- ID lemma page in NS ZERO
  contabpages[1] = "@LU00"                  -- EO appendix-NS page
  -- contabpages[1] = "Bahasa @LN00"           -- ID appendix-NS page
  contabpages[2] = "@LU00"                  -- EO index-NS page
  -- contabpages[2] = "Bahasa @LN00"           -- ID index-NS page
  contabpages[3] = "Vortaro (@LN00)"        -- EO "vor" dict cat
  -- contabpages[3] = "Kamus bahasa @LN00"     -- ID "vor" dict cat
  contabpages[4] = "Sxablonaro -@LK00-"     -- EO "mal" template cat "Kategorio:Sxablonaro -ja-"
  -- contabpages[4] = "Templat bahasa @LN00"   -- ID "mal" template cat "Kategori:Templat bahasa Jepang"
  contabpages[5] = "@LU00"                  -- EO "tln" top lng cat
  -- contabpages[5] = "Bahasa @LN00"           -- ID "tln" top lng cat
  contabpages[6] = "Kapvorto (@LN00)"       -- EO "kap" lemma cat
  -- contabpages[6] = "Kata bahasa @LN00"      -- ID "kap" lemma cat
  contabpages[7] = "@LU00 lingvo"           -- EO ipedia page guessing
  -- contabpages[7] = "Bahasa @LN00"           -- ID ipedia page guessing

  -- uncommentable EO vs ID constant strings and tables (misc)

  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 contabd10d11w = {}
  contabd10d11w = {'fermita aux malplena','nedisponebla'}  -- EO
  -- contabd10d11w = {'tertutup atau kosong','tidak ada'}     -- ID

  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 contabbigtiny = {}
  contabbigtiny[0] = "Gravaj eraroj trovigxas en la tabelo"                              -- EO (no dot "." here) ERR
  -- contabbigtiny[0] = "Ada kesalahan jahat dalam tabel"                                   -- ID (no dot "." here) ERR
  contabbigtiny[1] = "Se la eraroj persistas tiam vi redaktu"                            -- EO (no dot "." here) ERR
  -- contabbigtiny[1] = "Kalau kesalahan masih ada jadi Anda harus menyunting"              -- ID (no dot "." here) ERR
  contabbigtiny[2] = "kaj sekve revenu cxi tien por reinspekti rezulton"                 -- EO (no dot "." here) ERR
  -- contabbigtiny[2] = "dan kemudian datang ke sini sekali lagi untuk memeriksa hasilnya"  -- ID (no dot "." here) ERR
  contabbigtiny[3] = "Gxustigu kaj reprovu gxis ke cxi tiu mesagxo malaperas"            -- EO (no dot "." here) ERR
  -- contabbigtiny[3] = "Silakan memperbaiki dan mencoba ulang sampai pesan ini hilang"     -- ID (no dot "." here) ERR
  contabbigtiny[4] = 'Vi povas redakti'                                                  -- EO (no dot "." here) OK (komp YES sng NO)
  -- contabbigtiny[4] = 'Anda bisa menyunting'                                              -- ID (no dot "." here) OK (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] = "Kvanto da lingvoj: "                            -- EO
  -- contabsum[2] = "Jumlah bahasa: "                                -- ID
  contabsum[3] = "Kvanto da (gravaj) sortigaj eraroj: "           -- EO
  -- contabsum[3] = "Jumlah kesalahan sort (jahat): "                -- ID
  contabsum[4] = "Kvanto da nekompletaj (ele) linioj: "           -- EO
  -- contabsum[4] = "Jumlah garis tidak lengkap (ele): "             -- ID
  contabsum[5] = "Kvanto da tro longaj (ele) linioj: "            -- EO
  -- contabsum[5] = "Jumlah garis terlalu panjang (ele): "           -- ID

  -- integers "num"

  -- limits for single items

  local connummaaxc0nlen = 44   -- safe values 16 ... 96  -- eval "nummaxc0n"
  local connummaaxc2nlen = 68   -- safe values 16 ... 96  -- eval "nummaxc2n" ("ae" "lad" are very long)
  local connummaxc8catlen = 100 -- safe values 64 ... 256 -- eval "nummaxkal"

  -- further tuning

  local conboofree = true -- cost for "lfwifexist", into qtcostquery[1]
  local connumcatstyle = 1 -- category style: 0 raw | 1 "Ka:" | 2 <br>

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

---- SPECIAL STUFF OUTSIDE MAIN [B] ----

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

---- SPECIAL VAR:S ----

local qpiksubstri = {}   -- type "table" with type "function" inside
local qtbllingbaha = {}  -- from submodule with up to 11 elements
local qtcostquery = {}   -- for IfExists and PagesInCategory with 5 elements
local qtbunch = {}       -- bunch strings here for "lfhoptconcat"
local qbooguard = false  -- only for the guard test, pass to other var ASAP
local qboodetrc = true   -- from "detrc=true" but default is "true" !!!
local qstrtrace = '<br>' -- for main & sub:s, debug report request by "detrc="
local qstrret = ''       -- "lfhoptconcat" used huge output string with table

---- GUARD AGAINST INTERNAL ERROR & ONE IMPORT VIA REQUIRE ----

if ((type(constrpriv)~="string") or (type(construsmo)~="string") or (type(constrpiks)~="string") or (type(constrkatq)~="string")) then
  qbooguard = true -- "true" on error
else
  qpiksubstri = require(constrpiks) -- can crash here despite guarding ??
  if (type(qpiksubstri)~="table") then
    qbooguard = true -- "true" on error
  end--if
end--if

---- SEIZE THE HUGE SOURCE TABLE VIA LOADDATA ----

if (not qbooguard) then
  qtbllingbaha = mw.loadData(construsmo) -- can crash here despite guarding ??
  if (type(qtbllingbaha)~="table") then -- seems to be always false
    qbooguard = true
  end--if
end--if

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

---- DEBUG FUNCTIONS [D] ----

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

-- Local function LFTRACEMSG

-- Enhance upvalue "qstrtrace".

-- for variables the other sub "lfshowvar" is preferable but in exceptional
-- cases it can be justified to send text with values of variables to this sub

-- no size limit, use this one also to import detrc text from submodule

-- upvalue "qstrtrace" must NOT be type "nil" on entry (is inited to "<br>")

-- uses upvalue "qboodetrc"

local function lftracemsg (strshortlineorbigtext)
  local strseparator = ''
  if (qboodetrc and (type(strshortlineorbigtext)=='string')) then
    if (string.find(strshortlineorbigtext,'<br>',1,true)) then
      strseparator = '<br>&nbsp;######################<br>'
      qstrtrace = qstrtrace .. strseparator .. strshortlineorbigtext .. strseparator .. '<br>'
    else
      qstrtrace = qstrtrace .. strshortlineorbigtext .. '.<br>' -- dot added !!!
    end--if
  end--if
end--function lftracemsg

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

---- MATH FUNCTIONS [E] ----

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

local function mathmax (xmaxaa, xmaxbb)
  local resultmax = 0 -- max operator lacks in LUA :-(
  resultmax = xmaxaa
  if (resultmax<xmaxbb) then
    resultmax = xmaxbb
  end--if
  return resultmax
end--function mathmax

local function mathmin (xmindd, xminee)
  local resultmin = 0 -- min operator lacks in LUA :-(
  resultmin = xmindd
  if (resultmin>xminee) then
    resultmin = xminee
  end--if
  return resultmin
end--function mathmin

local function mathdiv (xdividens, xdivisero)
  local resultdiv = 0 -- DIV operator lacks in LUA :-(
  resultdiv = math.floor (xdividens / xdivisero)
  return resultdiv
end--function mathdiv

local function mathmod (xdividendo, xdivisoro)
  local resultmod = 0 -- MOD operator is "%" and bitwise AND operator lack too
  resultmod = xdividendo % xdivisoro
  return resultmod
end--function mathmod

local function mathbitwrit (numinkoming, numbityndex, boowrite)
  local numpatched = 0
  local numcountup = 0
  local numweight = 1 -- single bit value 1 -> 2 -> 4 -> 8 ...
  local boosinglebit = false
  while true do
    if ((numinkoming==0) and (numcountup>numbityndex)) then
      break -- we have run out of bits on BOTH possible sources
    end--if
    if (numcountup==numbityndex) then
      boosinglebit = boowrite -- overwrite bit
    else
      boosinglebit = (mathmod(numinkoming,2)==1) -- pick bit
    end--if
    numinkoming = mathdiv(numinkoming,2) -- shift right
    if (boosinglebit) then
      numpatched = numpatched + numweight -- add one bit rtl only if true
    end--if
    numcountup = numcountup + 1 -- count up here until we run out of bits
    numweight = numweight * 2
  end--while
  return numpatched
end--function mathbitwrit

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

---- SOME FUNCTIONS [?] ----

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

-- Local function LFPREPROEQMI

-- Preprocess "=" to "-"

-- A table element may not be equal to the string "=" per spec

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

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

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 = mathdiv((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

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

-- Local function LFISPACUNDR

-- Spaces to underscores or vice-versa.

-- Incoming boolean "true" for output underscores and "false" for spaces.

local function lfispacundr (strxxin, boounderlig)
  local numleang = 0
  local numandex = 0 -- ZERO-based
  local numcxarr = 0
  local strkatrol = ''
  numleang = string.len (strxxin)
  while true do -- genuine loop
    if (numandex==numleang) then
      break
    end--if
    numcxarr = string.byte (strxxin,(numandex+1),(numandex+1))
    if ((numcxarr==32) or (numcxarr==95)) then
      if (boounderlig) then
        numcxarr = 95
      else
        numcxarr = 32
      end--if
    end--if
    strkatrol = strkatrol .. string.char (numcxarr)
    numandex = numandex + 1
  end--while
  return strkatrol
end--function lfispacundr

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

-- Local function LFIKATALDIGU !!!FIXME!!! NOT used

-- Brew cat include (no extra colon ":") or appendix link from 3 elements.

local function lfikataldigu (strprefixx, strkataldnomo, strhintvisi)
  local strrbkma = ''
  if (type(strhintvisi)=="string") then
    strrbkma = '[[' .. strprefixx .. ':' .. strkataldnomo .. '|' .. strhintvisi .. ']]'
  else
    strrbkma = '[[' .. strprefixx .. ':' .. strkataldnomo .. ']]'
  end--if
  return strrbkma
end--function lfikataldigu

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

-- Local function LFCOUNTCHR

-- Count occurrences of a char (given by ASCII code) in a string.

-- Input  : * strqq -- string (empty is useless but can't cause major harm)
--          * numascii -- code of char to be counted

-- Output : * numrezalt -- number of hits

local function lfcountchr (strqq, numascii)
  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 -- done -- ZERO iterations possible
    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 (from a customizable set) in a string

-- Tolerable char:s that do not count are:
-- * digits "0"..."9"
-- * maybe apo for (trictl=1) or (trictl=2)
-- * maybe space for (trictl=2)

local function lfcountndg (strzzz,trictl)
  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==39) and (trictl~=0)) then
        numcair=48 -- apo OK
      end--if
      if ((numcair==32) and (trictl==2)) then
        numcair=48 -- space OK
      end--if
    if ((numcair<48) or (numcair>57)) 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

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

---- NUMBER CONVERSION FUNCTIONS [N] ----

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

-- 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 LFDEC1DIGIT

-- Convert 1 decimal ASCII digit to integer 0...9 (255 if invalid).

local function lfdec1digit (num1digit)
  num1digit = num1digit - 48 -- may become invalid
  if ((num1digit<0) or (num1digit>9)) then
    num1digit = 255
  end--if
  return num1digit
end--function lfdec1digit

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

-- Local function LFNUMTO2DIGIT

-- Convert integer 0...99 to 2-digit decimal string "00"..."99".

-- Depends on functions :
-- [E] mathmin mathdiv mathmod

local function lfnumto2digit (numzerotoninetynine)
  local strtwodig = '' -- always 2 digits
  numzerotoninetynine = math.floor (numzerotoninetynine) -- no transcendental
  numzerotoninetynine = mathmin (numzerotoninetynine,99) -- no trillions
  strtwodig = tostring(mathdiv(numzerotoninetynine,10)) .. tostring(mathmod(numzerotoninetynine,10))
  return strtwodig
end--function lfnumto2digit

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

-- Local function LFNUMTODECBUN

-- Convert non-negative integer to decimal string with bunching.

-- Depends on functions :
-- [E] mathdiv mathmod

local function lfnumtodecbun (numnomoriin)
  local strnomorut = ''
  local numindeex = 0
  local numcaar = 0
  numnomoriin = math.floor (numnomoriin) -- transcendental numbers suck
  if (numnomoriin<0) then
    numnomoriin = 0 -- negative numbers suck
  end--if
  while true do
    numcaar = mathmod(numnomoriin,10) + 48 -- get digit moving right to left
    numnomoriin = mathdiv(numnomoriin,10)
    if (numindeex==3) then
      strnomorut = "'" .. strnomorut -- ueglstr apo
      numindeex = 0
    end--if
    strnomorut = string.char(numcaar) .. strnomorut -- ueglstr digit
    numindeex = numindeex + 1
    if (numnomoriin==0) then
      break
    end--if
  end--while
  return strnomorut
end--function lfnumtodecbun

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

-- Local function LFONEHEXTOINT

-- Convert single quasi-digit (ASCII HEX "0"..."9" "A"..."F") to
-- integer (0...15, 255 invalid).

-- Only uppercase accepted

local function lfonehextoint (numdigit)
  local numresult = 255
  if ((numdigit>47) and (numdigit<58)) then
    numresult = numdigit-48
  end--if
  if ((numdigit>64) and (numdigit<71)) then
    numresult = numdigit-55
  end--if
  return numresult
end--function lfonehextoint

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

-- [??]

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

-- convert integer to deciml string with digit bunching & warn unconditionally

-- need constant string "constrexcla" ie just " !!!" with some style

local function lftostwauc (numccrap)
  local strhaasil = ''
  strhaasil = lfnumtodecbun(numccrap) .. constrexcla
  return strhaasil
end--function lftostwauc

-- convert integer to deciml string with digit bunching & warn if non-ZERO

-- need constant string "constrexcla" ie just " !!!" with some style

local function lftostwaz (numcrap)
  local strhasil = ''
  strhasil = lfnumtodecbun(numcrap)
  if (numcrap~=0) then
    strhasil = strhasil .. constrexcla
  end--if
  return strhasil
end--function lftostwaz

-- convert integer to deciml string with digit bunching & warn if over limit

-- need constant string "constrexcla" ie just " !!!" with some style

local function lftostw2p (numcreap, numinklimit)
  local strhasiil = ''
  strhasiil = lfnumtodecbun(numcreap)
  if (numcreap>numinklimit) then
    strhasiil = strhasiil .. constrexcla
  end--if
  return strhasiil
end--function lftostw2p

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

---- LOW LEVEL STRING FUNCTIONS [G] ----

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

local function lftestnum (numkaad)
  local boodigit = false
  boodigit = ((numkaad>=48) and (numkaad<=57))
  return boodigit
end--function lftestnum

local function lftestuc (numkode)
  local booupperc = false
  booupperc = ((numkode>=65) and (numkode<=90))
  return booupperc
end--function lftestuc

local function lftestlc (numcode)
  local boolowerc = false
  boolowerc = ((numcode>=97) and (numcode<=122))
  return boolowerc
end--function lftestlc

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

---- UTF8 FUNCTIONS [U] ----

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

-- Local function LFULNUTF8CHAR

-- Evaluate length of a single UTF8 char in octet:s.

-- Input  : * numbgoctet  -- beginning octet of a UTF8 char

-- Output : * numlen1234x -- number 1...4 or ZERO if invalid

-- Does NOT thoroughly check the validity, looks at 1 octet only.

local function lfulnutf8char (numbgoctet)
  local numlen1234x = 0
    if (numbgoctet<128) then
      numlen1234x = 1 -- $00...$7F -- ANSI/ASCII
    end--if
    if ((numbgoctet>=194) and (numbgoctet<=223)) then
      numlen1234x = 2 -- $C2 to $DF
    end--if
    if ((numbgoctet>=224) and (numbgoctet<=239)) then
      numlen1234x = 3 -- $E0 to $EF
    end--if
    if ((numbgoctet>=240) and (numbgoctet<=244)) then
      numlen1234x = 4 -- $F0 to $F4
    end--if
  return numlen1234x
end--function lfulnutf8char

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

-- Local function LFCASEREST

-- Adjust case of a single letter (restricted), only ASCII
-- plus a very limited set of 2-octet UTF8 letters. (this is REST)

-- Input  : * strucinrsut : single unicode letter (1 or 2 octet:s)
--          * booupcas    : for desired uppercase "true" and for
--                          lowercase "false"
--          * numselset   : 0 ASCII -- 2 eo -- 5 sv (value 255 NOT here)

-- Output : * strucinrsut : (same var, "ZZ" on failure)

-- Depends on functions : (this is REST)
-- [U] lfulnutf8char
-- [G] lftestuc lftestlc
-- [E] mathdiv mathmod mathbitwrit

-- Unknown non-ASCII input strictly returns "ZZ"

-- Defined sets:
-- 2: 2 x 6 uppercase and lowercase -eo- (CX GX HX JX SX UX cx gx hx jx sx ux)
--    upper CX $0108 GX $011C HX $0124 JX $0134 SX $015C UX $016C lower +1
-- 5: 2 x 4 uppercase and lowercase -sv- (AA AE OE EE aa ae oe ee)
--    upper AE $00C4 AA $00C5 EE $00C9 OE $00D6 lower +$20

local function lfcaserest (strucinrsut, booupcas, numselset)

  local numlaengdn = 0 -- length from "string.len"
  local numchaerr = 0 -- UINT8 beginning char
  local numchaess = 0 -- UINT8 later char (BIG ENDIAN, lower value here up)
  local numchareel = 0 -- UINT8 code relative to beginning of block $00...$FF
  local numdeta = 0 -- SINT8 +32 or -32 or +1 or -1 or ZERO
  local numtheemp = 0

  local boowantlowr = false
  local booiisuppr = false
  local booiislowr = false
  local boovalid = false -- preASSume guilt

  booupcas = not (not booupcas)
  boowantlowr = (not booupcas)

  while true do -- upper fake loop (this is REST)

    numlaengdn = string.len (strucinrsut)
    if ((numlaengdn<1) or (numlaengdn>2)) then -- only 1 or 2 accepted
      break -- bad string length
    end--if
    numchaerr = string.byte (strucinrsut,1,1)
    if ((lfulnutf8char(numchaerr))~=numlaengdn) then
      break -- mismatch with length
    end--if

    if (numlaengdn==1) then
      booiisuppr = lftestuc(numchaerr)
      booiislowr = lftestlc(numchaerr)
      if (booiisuppr and boowantlowr) then
        numdeta = 32 -- ASCII UPPER->lower
      end--if
      if (booiislowr and booupcas) then
        numdeta = -32 -- ASCII lower->UPPER
      end--if
      boovalid = true
      break -- success with ASCII, almost done
    end--if

    numchaess = string.byte (strucinrsut,2,2) -- only $80 to $BF
    numchareel = (mathmod(numchaerr,4)*64) + (numchaess-128) -- 4 times 64

    if ((numselset==2) and ((numchaerr==196) or (numchaerr==197))) then -- eo
      numtheemp = mathbitwrit (numchareel,0,false) -- bad way to do AND $FE
      if ((numtheemp==8) or (numtheemp==28) or (numtheemp==36) or (numtheemp==52) or (numtheemp==92) or (numtheemp==108)) then
        booiisuppr = (numtheemp==numchareel) -- UC below and even (ordinary)
        booiislowr = not booiisuppr
        if (booiisuppr and boowantlowr) then
          numdeta = 1 -- UPPER->lower
        end--if
        if (booiislowr and booupcas) then
          numdeta = -1 -- lower->UPPER
        end--if
        boovalid = true
        break -- success with -eo-, almost done
      end--if
    end--if ((numselset==2) and ...

    if ((numselset==5) and (numchaerr==195)) then -- sv
      numtheemp = mathbitwrit (numchareel,5,false) -- bad way to do AND $DF
      if ((numtheemp==196) or (numtheemp==197) or (numtheemp==201) or (numtheemp==214)) then
        booiisuppr = (numtheemp==numchareel) -- UC below and bit is ZERO
        booiislowr = not booiisuppr
        if (booiisuppr and boowantlowr) then
          numdeta = 32 -- UPPER->lower
        end--if
        if (booiislowr and booupcas) then
          numdeta = -32 -- lower->UPPER
        end--if
        boovalid = true
        break -- success with -sv-, almost done
      end--if
    end--if ((numselset==5) and ...

    break -- finally to join mark -- unknown non-ASCII char is a fact :-(
  end--while -- upper fake loop -- join mark (this is REST)

  while true do -- lower fake loop (this is REST)

    if (not boovalid) then
      strucinrsut = "ZZ" -- unknown non-ASCII char
      break -- helvete
    end--if

    if (numdeta==0) then
      break -- nothing to do
    end--if

    if (numlaengdn==1) then
      strucinrsut = string.char (numchaerr + numdeta) -- no risk of carry here
      break -- done
    end--if

    strucinrsut = string.char (numchaerr) .. string.char (numchaess + numdeta)

    break -- finally to join mark
  end--while -- lower fake loop -- join mark (this is REST)

  return strucinrsut -- same var for input and output !!!

end--function lfcaserest

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

-- Local function LFUCASESTR

-- Adjust case of beginning letter or of all letters in a word or group
-- of words to upper or lower, with limited and adjustable unicode support.

-- Input  : * strenigo  : word or group of words (may be empty)
--          * boouprcas : "true" for uppercase and "false" for lowercase
--          * boodooall : "true" to adjust all letters, "false" only beginning
--          * numslsaet : 0 ASCII -- 2 eo -- 5 sv

-- Depends on functions : (restricted LFCASEREST)
-- [U] lfulnutf8char lfcaserest
-- [G] lftestuc lftestlc
-- [E] mathdiv mathmod mathbitwrit

local function lfucasestr (strenigo, boouprcas, boodooall, numslsaet)

  local numlein = 0
  local numposi = 1 -- octet position ONE-based
  local numcut = 0 -- length of an UTF8 char
  local bootryadj = false -- try to adjust single char
  local strte7mp = ''
  local strelygo = ''

  boouprcas = not (not boouprcas)
  boodooall = not (not boodooall)
  numlein = string.len (strenigo)

  while true do
    if (numposi>numlein) then
      break -- done
    end--if
    bootryadj = (boodooall or (numposi==1))
    numcut = lfulnutf8char(string.byte(strenigo,numposi,numposi))
    if ((numcut==0) or ((numposi+numcut-1)>numlein)) then
      numcut = 1 -- skip ie copy one faulty octet
      bootryadj = false
    end--if
    strte7mp = string.sub (strenigo,numposi,(numposi+numcut-1)) -- 1...4 oct
    if (bootryadj) then
      strte7mp = lfcaserest(strte7mp,boouprcas,numslsaet) -- (restricted LFCASEREST)
    end--if
    strelygo = strelygo .. strte7mp -- this can be slow
    numposi = numposi + numcut -- done 1...4 octet:s
  end--while

  return strelygo

end--function lfucasestr

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

---- HIGH LEVEL STRING FUNCTIONS [I] ----

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

-- Local function LFIVALIDATESTR

-- 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 defined
--          * 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 parameter "numapo" above)
--                     2 : only ASCII uppercase letters
--                     3 : only ASCII lowercase letters

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

-- Depends on functions :
-- [G] lftestnum lftestuc lftestlc

local function lfivalidatestr (stryn,varalt,nummyn,nummex,numapo,numpoz)
  local numlencx = 0
  local numynx = 0
  local numcxar = 0
  local numcxur = 0
  local bootnp = false
  local booisvalid = true -- preASSume innocence -- final verdict
  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)
      bootnp = (string.find(stryn, "''", 1, true)~=nil) -- pltxt search dblapo
      if ((numcxar==39) or (numcxur==39) or bootnp) 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 (not lftestnum(numcxar)) then
            booisvalid = false
            break -- abort search, crime detected (non-digit)
          end--if
        end--if
        if (numpoz==2) then
          if (lftestuc(numcxar)==false) then
            booisvalid = false
            break -- abort search, crime detected (non-uppercase)
          end--if
        end--if
        if (numpoz==3) then
          if (lftestlc(numcxar)==false) 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 lfivalidatestr

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

-- Local function LFIVALIDATEQUACK

-- Validate a Q-item.

-- Input  : * strqynq -- string

-- Output : * booqisvalid -- true if string is valid

-- Depends on functions :
-- [G] lftestnum

-- Criteria:
-- * length totally 3...9 chars ("Q" plus 2...8 digits)
-- * zeroth char "Q"
-- * then "1"..."9"
-- * subsequent chars (1...7 left) "0"..."9"

local function lfivalidatequack (strqynq)
  local numlendx = 0
  local numuinx = 0
  local numcyaar = 0
  local booqisvalid = false -- preASSume guilt -- final verdict
  while true do -- fake loop
    numlendx = string.len(strqynq)
    if ((numlendx<3) or (numlendx>9)) then
      break -- to join mark -- string is faulty, length
    end--if
    if (string.byte(strqynq,1,1)~=81) then
      break -- to join mark -- string is faulty, no "Q"
    end--if
    if (string.byte(strqynq,2,2)==48) then
      break -- to join mark -- string is faulty, ZERO "0" prohibited here
    end--if
    numuinx = 1 -- ZERO-based -- skip "Q"
    booqisvalid = true -- preASSume innocence
    while true do
      if (numuinx>=numlendx) then
        break -- done search, all OK
      end--if
      numcyaar = string.byte(strqynq,(numuinx+1),(numuinx+1))
      if (not lftestnum(numcyaar)) then
        booqisvalid = false -- guilty, no number
        break -- abort search
      end--if
      numuinx = numuinx + 1 -- ZERO-based
    end--while
    break -- finally to join mark
  end--while -- fake loop -- join mark
  return booqisvalid
end--function lfivalidatequack

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

-- Local function LFIVALIDATELNKOADV

-- Advanced test whether a string (intended to be a language code) is valid
-- containing only 2 or 3 lowercase letters, or 2...10 char:s and with some
-- dashes, or maybe a digit in middle position or maybe instead equals to "-"
-- or "??" and maybe additionally is not included on the ban list.

-- Input  : * strqooq -- string (empty is useless and returns
--                       "true" ie "bad" but cannot cause any major harm)
--          * booyesdsh -- "true" to allow special code dash "-"
--          * booyesqst -- "true" to allow special code doublequest "??"
--          * booloonkg -- "true" to allow long codes such as "zh-min-nan"
--          * boodigit -- "true" to allow digit in middle position
--          * boonoban -- (inverted) "true" to skip test against ban table

-- Output : * booisvaladv -- true if string is valid

-- Depends on functions :
-- [G] lftestnum lftestlc

-- Depends on constants :
-- * table "contabisbanned"

-- Incoming empty string is safe but type "nil" is NOT.

-- Digit is tolerable only ("and" applies):
-- * if boodigit is "true"
-- * if length is 3 char:s
-- * in middle position

-- Dashes are tolerable (except in special code "-") only ("and" applies):
-- * if length is at least 4 char:s (if this is permitted at all)
-- * in inner positions
-- * NOT adjacent
-- * maximally TWO totally
-- There may be maximally 3 adjacent letters, this makes at least ONE dash
-- obligatory for length 4...7, and TWO dashes for length 8...10.

local function lfivalidatelnkoadv (strqooq, booyesdsh, booyesqst, booloonkg, boodigit, boonoban)

  local varomongkosong = 0 -- for check against the ban list
  local numchiiar = 0
  local numukurran = 0
  local numindeex = 0 -- ZERO-based -- two loops
  local numadjlet = 0 -- number of adjacent letters (max 3)
  local numadjdsh = 0 -- number of adjacent dashes (max 1)
  local numtotdsh = 0 -- total number of dashes (max 2)
  local booislclc = false
  local booisdigi = false
  local booisdash = false
  local booisvaladv = true -- preASSume innocence -- later final verdict here

  while true do -- fake (outer) loop

    if (strqooq=="-") then
      booisvaladv = booyesdsh
      break -- to join mark -- good or bad
    end--if
    if (strqooq=="??") then
      booisvaladv = booyesqst
      break -- to join mark -- good or bad
    end--if
    numukurran = string.len (strqooq)
    if ((numukurran<2) or (numukurran>10)) then
      booisvaladv = false
      break -- to join mark -- evil
    end--if
    if (not booloonkg and (numukurran>3)) then
      booisvaladv = false
      break -- to join mark -- evil
    end--if

    numindeex = 0
    while true do -- ordinary inner loop over char:s
      if (numindeex>=numukurran) then
        break -- done -- good
      end--if
      numchiiar = string.byte (strqooq,(numindeex+1),(numindeex+1))
      booisdash = (numchiiar==45)
      booisdigi = lftestnum(numchiiar)
      booislclc = lftestlc(numchiiar)
      if (not (booislclc or booisdigi or booisdash)) then
        booisvaladv = false
        break -- to join mark -- inherently bad char
      end--if
      if (booislclc) then
        numadjlet = numadjlet + 1
      else
        numadjlet = 0
      end--if
      if (booisdigi and ((numukurran~=3) or (numindeex~=1) or (not boodigit))) then
        booisvaladv = false
        break -- to join mark -- illegal digit
      end--if
      if (booisdash) then
        if ((numukurran<4) or (numindeex==0) or ((numindeex+1)==numukurran)) then
          booisvaladv = false
          break -- to join mark -- illegal dash
        end--if
        numadjdsh = numadjdsh + 1
        numtotdsh = numtotdsh + 1 -- total
      else
        numadjdsh = 0 -- do NOT zeroize the total !!!
      end--if
      if ((numadjlet>3) or (numadjdsh>1) or (numtotdsh>2)) then
        booisvaladv = false
        break -- to join mark -- evil
      end--if
      numindeex = numindeex + 1 -- ZERO-based
    end--while -- ordinary inner loop over char:s

    if (not boonoban) then -- if "yesban" then
      numindeex = 0
      while true do -- ordinary lower inner loop
        varomongkosong = contabisbanned[numindeex+1] -- number of elem unknown
        if (type(varomongkosong)~="string") then
          break -- abort inner loop (then fake outer loop) due to end of table
        end--if
        numukurran = string.len (varomongkosong)
        if ((numukurran<2) or (numukurran>3)) then
          break -- abort inner loop (then fake outer loop) due to faulty table
        end--if
        if (strqooq==varomongkosong) then
          booisvaladv = false
          break -- abort inner loop (then fake outer loop) due to violation
        end--if
        numindeex = numindeex + 1 -- ZERO-based
      end--while -- ordinary lower inner loop
    end--if (not boonoban) then

    break -- finally to join mark
  end--while -- fake loop -- join mark

  return booisvaladv

end--function lfivalidatelnkoadv

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

---- HIGH LEVEL FUNCTIONS [H] ----

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

-- Local function LFBREWERRSV

-- note that #E00 is OK and NOT supposed to be processed here

-- Depends on functions :
-- [N] lfnumto2digit

-- We need 5 const strings "constremibg", "constremien",
-- "constrelabg", "constrelaen", "constrlaxhu" and const table "contaberaroj".

-- severity level can be 0 mini 1 lagom 2 huge

local function lfbrewerrsv (numerrorcode, numseverity)
  local varmaybenil = 0
  local stritsucks = '#E'
  varmaybenil = contaberaroj[numerrorcode]
  if (type(varmaybenil)=="string") then
    stritsucks = stritsucks .. lfnumto2digit(numerrorcode) .. ' ' .. varmaybenil
  else
    stritsucks = stritsucks .. '??'
  end--if
  if (numseverity==0) then
    stritsucks = constremibg .. stritsucks .. constremien
  else
    stritsucks = constrelabg .. stritsucks .. constrelaen
  end--if
  if (numseverity==2) then
    stritsucks = constrlaxhu .. stritsucks .. constrlaxhu
  end--if
  return stritsucks
end--function lfbrewerrsv

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

-- Local function LFINSERTULTIM

-- Insert selected extra strings into a given string at given positions
-- with optional discarding if the insertable item is empty. Discarding
-- is protected from access out of range by clamping the distances.

-- Input  : * strmdata -- main data string with control cod (syntax see below)
--          * tabinseert -- not-string element is safe and has same effect as
--                          empty string, still explicit type "nil" or empty
--                          string "" are preferred
-- Output : * strhazil

-- syntax of the insertion and discarding magic string:
-- "@" followed by 2 uppercase letters and 2 hex numbers
-- otherwise the hit is not expanded, but copied as-is instead
-- 2 letters select the insertable item from table supplied by the caller
-- 2 hex numbers control discarding left and right (0...15 char:s)

-- Empty item in "tabinseert" is legal and results in discarding if some of
-- the control numbers is non-ZERO. Left discarding is practically performed
-- on "strhazil" whereas right discarding on "strmdata" and "numdatainx".

-- If uppercasing or other adjustment is needed then the caller must take
-- care of it in the form of 2 or more separate items provided in the table
-- with separate names.

-- Depends on functions :
-- [G] lftestuc
-- [N] lfonehextoint

local function lfinsertultim (strmdata,tabinseert)

  local varduahuruf = 0
  local strhazil = ''
  local numdatalen = 0
  local numdatainx = 0 -- src index
  local numdataoct = 0 -- maybe @
  local numdataodt = 0 -- UC
  local numdataoet = 0 -- UC
  local numammlef = 0 -- hex and discard left
  local numammrig = 0 -- hex and discard right
  local boogotmagic = false

  numdatalen = string.len(strmdata)
  numdatainx = 1 -- ONE-based

  while true do -- genuine loop, "numdatainx" is the counter
    if (numdatainx>numdatalen) then -- beware of risk of overflow below
      break -- done (ZERO iterations possible)
    end--if
    boogotmagic = false
    numdataoct = string.byte(strmdata,numdatainx,numdatainx)
    numdatainx = numdatainx + 1
    while true do -- fake loop
      if ((numdataoct~=64) or ((numdatainx+3)>numdatalen)) then
        break -- no hit here
      end--if
      numdataodt = string.byte(strmdata, numdatainx   , numdatainx   )
      numdataoet = string.byte(strmdata,(numdatainx+1),(numdatainx+1))
      if (not (lftestuc(numdataodt)) or (not lftestuc(numdataoet))) then
        break -- no hit here
      end--if
      numammlef = string.byte(strmdata,(numdatainx+2),(numdatainx+2))
      numammrig = string.byte(strmdata,(numdatainx+3),(numdatainx+3))
      numammlef = lfonehextoint (numammlef)
      numammrig = lfonehextoint (numammrig)
      boogotmagic = ((numammlef~=255) and (numammrig~=255))
      break
    end--while -- fake loop -- join mark
    if (boogotmagic) then
      numdatainx = numdatainx + 4 -- consumed 5 char:s, cannot overflow here
      varduahuruf = string.char (numdataodt,numdataoet)
      varduahuruf = tabinseert[varduahuruf] -- risk of type "nil"
      if (type(varduahuruf)~="string") then
        varduahuruf = '' -- type "nil" or invalid type gives empty string
      end--if
      if (varduahuruf=='') then
        numdataoct = string.len(strhazil) - numammlef -- this can underflow
        if (numdataoct<=0) then
          strhazil = ''
        else
          strhazil = string.sub(strhazil,1,numdataoct) -- discard left
        end--if
        numdatainx = numdatainx + numammrig -- discard right this can overflow
      else
        strhazil = strhazil .. varduahuruf -- insert / expand
      end--if
    else
      strhazil = strhazil .. string.char(numdataoct) -- copy char as-is
    end--if (boogotmagic) else
  end--while

  return strhazil

end--function lfinsertultim

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

-- Local function LFHKODEOSG

-- Transcode eo X-surrogates (without "\", thus for example "kacxo",
-- NOT "ka\cxo") to cxapeloj in a single string (EO only).

-- Input  : * strsurr -- string (empty is useless but cannot cause major harm)

-- Output : * strcxapeloj -- UTF8 string

-- Depends on functions :
-- [E] mathdiv mathmod

-- Depends on constants :
-- * table "contabtransiltable" inherently holy

local function lfhkodeosg (strsurr)
  local varpeek = 0
  local strcxapeloj = ''
  local numinputl = 0
  local numininx = 0 -- ZERO-based source index
  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 -- preASSume 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 = mathmod (varpeek,256)
        numhaj = mathdiv (varpeek,256)
      end--if
    end--if
    if (numhaj~=0) then
      strcxapeloj = strcxapeloj .. string.char(numhaj,numlow) -- add UTF8 char
      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 lfhkodeosg

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

-- Local function LFHKODEOTB

-- Transcode eo X-surrogates to cxapeloj whole possibly holy table
-- with strings (EO only).

-- Depends on functions :
-- [H] lfhkodeosg
-- [E] mathdiv mathmod

-- Depends on constants :
-- * table "contabtransiltable" inherently holy

local function lfhkodeotb (tabsurr)
  local varitem = 0 -- variable without type
  local tabcxapeloj = {}
  local numtblindex = 0 -- ZERO-based
  local numholycrap = 0 -- tolerance for holes
  while true do
    varitem = tabsurr[numtblindex] -- expected type "string" or "nil"
    if (type(varitem)=="string") then -- number of messages is NOT hardcoded
      numholycrap = 0
      tabcxapeloj[numtblindex] = lfhkodeosg(varitem)
    else
      numholycrap = numholycrap + 1 -- skip hole
    end--if
    if (numholycrap==4) then -- max 3 consecutive holes
      break
    end--if
    numtblindex = numtblindex + 1
  end--while
  return tabcxapeloj
end--function lfhkodeotb

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

-- Local function LFHRLSTRIP

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

local function lfhrlstrip (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 lfhrlstrip

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

-- Local function LFINUMBERINKAT

local function lfinumberinkat (numjumlahorminone)
  local strnothing = '' -- "(16'384 pages)" or "(?? pages)"
  if (numjumlahorminone<0) then -- expected type integer, value -1 for unknown
    strnothing = '(??'
  else
    strnothing = '(' .. lfnumtodecbun(numjumlahorminone) -- ZERO is valid
  end--if
  strnothing = strnothing .. ' pages)'
  return strnothing
end--function lfinumberinkat

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

local function lfavailco (numava) -- translates number 2...0 to color (Y,grey)
  local strcolor = constrbkco -- preASSume 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 "contabd10d11w" with 2 strings at indexes ONE and TWO.

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

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

-- Local function LFEVILITEM

-- Brew complaint about faulty item in the source table.

-- Input  : * numtpitem -- type (0:code 1:langname 2:title 3:category
--                               4:Q-item 5:number)
--          * numcol  -- source column index (0...10) or special value 67
--          * strxx   -- the faulty string already suitably clamped

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

-- We need table "contabevilitem" (1...6) OFF-by-ONE with special
-- content at index ZERO.

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

local function lfevilitem (numtpitem,numcol,strxx)
  local strharang = ''
  local numquot = 0
  strharang = constrelabg .. contabevilitem[numtpitem+1] .. contabevilitem[0] .. constrelaen .. ' "c'
  if (numcol==67) then
    strharang = strharang .. '6" "c7' -- 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 type "nil" expected

-- Depends on functions :
-- [I] lfispacundr

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

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/' .. lfispacundr(varpage,true) -- replace 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 (for column or row) from index
-- number and two booleans.

-- Input  : * numindxe -- index number of column (ZERO-based)
--          * bootopp, boobotm

-- Depends on functions :
-- [N] lfnumto2digit

-- * (begin of bold) is always added at the very beginning
-- * (end of bold) is added at the very end if no "#" is present
-- * "#" is expanded to (end of bold) + EOL + word "and" + EOL
-- * maximally ONE "#" is permitted
-- * "%" is border between 2 selectable items, it is expanded to
--   (end of bold) + EOL + word "and" + EOL + (begin of bold) only
--   if both items are active
-- * maximally ONE "%" is permitted

-- An entry in the table "contabdestit" is NOT supposed to contain
-- "<b>" (even less triple-apo "'''"), nor "</b>" at end nor "<br>".

-- We need const table "contabdestit" and
-- contabmisc[0] (translated word "and").

local function lfbrewtitsel (numindxe, bootopp, boobotm)

  local strraw = ''
  local strdesc = ''
  local strandkajdan = ''
  local numlimiit = 0
  local numoindex = 1 -- ONE-based
  local numpycker = 0
  local numfragmm = 0 -- NOT relevant if both "bootopp" and "boobotm" are true
  local booslutbold = false
  local bootakeit = false

  strandkajdan = "<br>" .. contabmisc[0] .. "<br>" -- for both % and #
  strraw = contabdestit[numindxe]
  strdesc = '<b>'
  numlimiit = string.len (strraw)

  while true do
    if (numoindex>numlimiit) then
      break
    end--if
    bootakeit = true
    numpycker = string.byte(strraw,numoindex,numoindex)
    numoindex = numoindex + 1
    if (numpycker==35) then -- 35 is "#"
      strdesc = strdesc .. "</b>" .. strandkajdan -- no (begin of bold) !!!
      booslutbold = true
      bootakeit = false
      numfragmm = 2 -- following text taken unconditionally
    end--if
    if (numpycker==37) then -- 37 is "%"
      if (bootopp and boobotm) then
        strdesc = strdesc .. "</b>" .. strandkajdan .. "<b>"
      end--if
      numfragmm = numfragmm + 1
      bootakeit = false
    end--if
    if ((numfragmm==0) and (not bootopp)) then
      bootakeit = false
    end--if
    if ((numfragmm==1) and (not boobotm)) then
      bootakeit = false
    end--if
    if (bootakeit) then
      strdesc = strdesc .. string.char(numpycker)
    end--if
  end--while

  if (not booslutbold) then
    strdesc = strdesc .. '</b>' -- add "</b>" only if it is not yet in
  end--if
  strdesc = strdesc .. '<br>(d' .. lfnumto2digit (numindxe) .. ')'

  return strdesc

end--function lfbrewtitsel

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

---- MEDIAWIKI INTERACTION FUNCTIONS [W] ----

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

-- Local function LFWIFEXIST

-- Check whether a wiki page exists. The caller must use "pcall".

-- Input  : * strpgname    -- fullpagename (default NS 0, not template NS 10)

-- Output : * boomemangada -- "true" on success

-- Depends on upvalues :
-- * heterogeneous table "qtcostquery" with 5 elements

-- Extra colon is tolerable for non-NS-ZERO and non-template-NS-10 pages
-- such as "{{msgnw::Help:TOC}}" and returns ...":Help:TOC"... if the
-- page does not exist.

local function lfwifexist (strpgname)
  local boomemangada = false
  local arxxx = 0
  local metaa = 0
  if (qtcostquery[1]) then
    arxxx = qtcostquery[0] -- trick below does NOT work with substitution
    boomemangada = ( '&#91;&#91;:' .. strpgname .. '&#93;&#93;' ~= arxxx:preprocess ('{{msgnw::' .. strpgname .. '}}') )
    qtcostquery[4] = qtcostquery[4] + 1 -- free counter
  else
    metaa = mw.title.new (strpgname) -- 1 param
    boomemangada = metaa.exists -- expensive here
    qtcostquery[3] = qtcostquery[3] + 1 -- expensive counter
  end--if
  return boomemangada
end--function lfwifexist

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

-- Local function LFWKATROL

-- Peek summary of a category. The caller must use "pcall".

-- Input  : * strcatname           -- without prefix

-- Output : * numpages, numsubcats -- 2 values, value -1 for unknown

-- Depends on upvalues :
-- * heterogeneous table "qtcostquery" with 5 elements

local function lfwkatrol (strcatname)
  local metab = 0
  local numpages = -1
  local numsubcats = -1
  metab = mw.site.stats.pagesInCategory ( strcatname, "*" ) -- expensive here
  qtcostquery[2] = qtcostquery[2] + 1 -- expensive counter
  if (type(metab)=="table") then -- risk of type "number" or "nil"
    numpages = metab.pages
    numsubcats = metab.subcats
    if (numpages<0) then
      numpages = -1 -- YES MediaWiki is stupid
    end--if
    if (numsubcats<0) then
      numsubcats = -1 -- YES MediaWiki is stupid
    end--if
  end--if
  return numpages, numsubcats
end--function lfwkatrol

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

---- VERY HIGH LEVEL FUNCTIONS [Y]

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

-- Local function LFYKATTLAENK

-- Brew link to category possibly saving screen space and
-- optionally check existence and content.

-- Input  : * strkattnamn            -- without prefix

-- Output : * booisbiru, strlikatter -- 2 values

-- Depends on functions :
-- [W] lfwifexist lfwkatrol
-- [I] lfinumberinkat

-- Depends on upvalues :
-- * heterogeneous table "qtcostquery" with 5 elements

-- Depends on constants :
-- * constrkatq (ns prefix NOT ending with colon)
-- * contabmisc[1] (statement "does not exist")
-- * connumcatstyle (0 raw | 1 "Ka:" | 2 <br>)

local function lfykattlaenk (strkattnamn,boocheckdabl)
  local strfullcatname = ''
  local strlikatter = ''
  local straltprefix = ''
  local numjumlah = 0
  local booisbiru = true -- preASSume innocence
  strfullcatname = constrkatq .. ':' .. strkattnamn
  if (connumcatstyle==0) then
    strlikatter = "[[:" .. strfullcatname .. "]]" -- raw
  else
    if (connumcatstyle==1) then
      straltprefix = string.sub (constrkatq,1,2) .. ':' -- "Ca:" or "Ka:"
    else
      straltprefix = constrkatq .. ':<br>' -- "Category:" + EOL
    end--if
    strlikatter = "[[:" .. strfullcatname .. "|" .. straltprefix .. strkattnamn.. "]]"
  end--if
  if (boocheckdabl) then
    booisbiru = lfwifexist (strfullcatname)
    if (not booisbiru) then -- incidents reported here but counted by caller
      strlikatter = strlikatter .. '<br>(' .. contabmisc[1] .. ')' -- "does not exist"
    end--if
    numjumlah = lfwkatrol (strkattnamn) -- discard 1 of 2 results, can be -1
    strlikatter = strlikatter .. '<br>' .. lfinumberinkat(numjumlah) -- can be -1
  end--if
  return booisbiru,strlikatter
end--function lfykattlaenk

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

-- Local function LFYAPXINDLAENK

-- Brew link to appendix or index page and optionally check existence.

-- Input  : * strapxindnamn           -- without prefix

-- Output : * booitisblue, strailiink -- 2 values

-- Depends on functions :
-- [W] lfwifexist

-- Depends on upvalues :
-- * heterogeneous table "qtcostquery" with 5 elements

-- Depends on constants :
-- * constrapxq and constrindq (ns prefixes NOT ending with colon)
-- * contabmisc[1] (statement "does not exist")

local function lfyapxindlaenk (strapxindnamn,bootypetrueind,boocekexx)
  local strfullcainame = ''
  local strailiink = ''
  local booitisblue = true -- preASSume innocence
  if (bootypetrueind) then
    strfullcainame = constrindq .. ':' .. strapxindnamn -- "Index:" prefix
  else
    strfullcainame = constrapxq .. ':' .. strapxindnamn -- "Appendix:" prefix
  end--if
  strailiink = '[[' .. strfullcainame .. ']]'
  if (boocekexx) then
    booitisblue = lfwifexist (strfullcainame)
    if (not booitisblue) then -- incidents reported here but counted by caller
      strailiink = strailiink .. '<br>(' .. contabmisc[1] .. ')' -- "does not exist"
    end--if
  end--if
  return booitisblue,strailiink
end--function lfyapxindlaenk

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

-- Local function LFYSEIZESUBSTRING (komp YES sng YES)

-- Input  : * strbigline
--          * strxindex -- x-index, special value "-" means count substrings

-- Depends on imports :
-- * qpiksubstri.ek ie imported mpiksubstrind via constrpiks

-- Depends on constants :
-- * contabrxi

local function lfyseizesubstring (strbigline,strxindex)
  local strsubstringum = ''
  local strxxii = ''
  local varxxxindex = 0
  if (strxindex=="-") then -- no translate
    strsubstringum = qpiksubstri.ek { args = { strbigline, "-" } } -- count
  else
    varxxxindex = contabrxi [tonumber (strxindex)] -- translate x-index
    if (type(varxxxindex)=="number") then
      strxxii = tostring (varxxxindex)
      strsubstringum = qpiksubstri.ek { args = { strbigline, strxxii } } -- pi
    else
      strsubstringum = "="
    end--if
  end--if
  return strsubstringum
end--function lfyseizesubstring

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

---- VARIABLES [R] ----

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

function exporttable.ek (arxframent)

  -- general unknown type ie "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)

  -- stuff from incoming table

  local num0statcode = 0
  local num1lenfullo = 0
  local num2lenstrip = 0
  local num3errposit = 0
  local num4lineslin = 0

  local str5errorstr = ''
  local str6errorstr = ''

  local tab7list     = {}
  local tab8forward  = {}
  -- local tab9reverse  = {}
  -- local tab10extra   = {}

  -- general "tab"

  local tabstuff = {}  -- double-letter indexes for "lfinsertultim"

  -- general "str"

  local strinfsel = "" -- incoming parameter with 6 digi, reported at the end
  local strsrcrow = "" -- complete row from the source table
  local strbkn    = "" -- HTML HEX color (6 digits)
  local strt3d    = "" -- HTML "td" element concatenated from 3 parts
  local strtblcy  = "" -- src y-index marker (this is NOT the column "c0")
  local strtblc0  = "" -- src column 0 (this is NOT the y-index marker) (obli)
  local strtblc1  = "" -- src column 1 (nice to have) Q-item
  local strtblc2  = "" -- src column 2 (nice to have) propralingve
  local strtblc3  = "" -- src column 3 (nice to have) 1 digit
  local strtblc4  = "" -- src column 4 (nice to have) 2 letters ISO
  local strtblc5  = "" -- src column 5 (nice to have) 3 letters ISO
  local strtblc6  = ""
  local strtblc7  = ""
  local strtblc8  = "" -- src column 8
  local strtblc9  = "" -- src column 9
  local strtblca  = "" -- src column 10
  local strdeste  = "" -- destinat table element with both "td" HTML elements
  local strpurge  = "" -- purge quasi-external link complete with "[" and "]"
  local strsumbl  = "" -- technical summary block

  local strtmp   = ""  -- temp
  local strtpm   = ""  -- temp other

  -- general "num"

  local numproba  = 100  -- probability from arxourown[3] (komp YES sng NO)

  local numminwidth = 10    -- !!!FIXME!!!
  local nummaxwidth = 1000  -- !!!FIXME!!!

  local numc7pedi = 0    -- ipedia code "0"..."2" ("3" for "-" and reddish)
  local numc7tion = 0    -- tionary code "0"..."2" ("3" for "-" and reddish)

  local numafstbfcl = 0  -- string length aftr stripping rl lr before clamping
  local numafstbfkp = 0  -- string length aftr stripping rl lr before clamping

  local numoct    = 0    -- temp some char
  local numtamp   = 0    -- temp
  local numtump   = 0    -- temp
  local numlong   = 0    -- temp

  -- bunched info about the input table "num"

  local numrowinx = 0  -- row index becoming number of rows & langs at the end
  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 numminwyd = 0  -- evaluated min width
  local nummaxwyd = 0  -- evaluated max width
  local nummaxc0n = 0  -- evaluated max bloat of language name site (c0)
  local nummaxc2n = 0  -- evaluated max bloat of language name prop (c2)
  local nummaxkal = 0  -- evaluated max bloat of category link (limit hard)

  -- missing "num"

  local numerrtln = 0  -- missing "tln" top lng cat (not fatal) !!!FIXME!!!
  local numerrkap = 0  -- missing "kap" (not fatal)
  local numerrvor = 0  -- missing "vor" (not fatal) !!!FIXME!!!
  local numerrmal = 0  -- missing "mal" (not fatal)
  local numerrapx = 0  -- missing "apx" appendix page (not fatal) !!!FIXME!!!
  local numerrind = 0  -- missing "ind" index page (not fatal)

  -- general "boo"

  local booerr     = false  -- 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 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
  local boodofatal = false  -- brewed from 6 vari by OR, show fatal block

  local boohavtbl  = false
  local bootimp    = false  -- temp
  local boorussia  = false  -- toss a coin for every row from "numproba"

  -- dissatisfaction "boo"

  local booc0bad   = false  -- true if len(c0) out of rang, even "-" NOT valid
  local booc1bad   = false  -- Q-item
  local booc2bad   = false  -- propralingve
  local booc3bad   = false  -- 2-litera -- true if bad
  local booc4bad   = false  -- 3-litera -- true if bad
  local booc6c7bad = false  -- true if c6 or c7 is bad
  local booc8bad   = false  -- ipedia article -- true if bad

  -- from arxourown "boo"

  local bootlnsow  = false  -- f arxourown[1] d07 above show "tln" top lng cat
  local bootlnexp  = false  -- f arxourown[1] d07 above query "tln" top lng cat
  local bookapsow  = false  -- f arxourown[1] d07 below show "kap"
  local bookapexp  = false  -- f arxourown[1] d07 below query "kap"
  local bood07     = false

  local boovorsow  = false  -- f arxourown[1] d08 above show "vor"
  local boovorexp  = false  -- f arxourown[1] d08 above query "vor"
  local boomalsow  = false  -- f arxourown[1] d08 below show "mal"
  local boomalexp  = false  -- f arxourown[1] d08 below query "mal"
  local bood08     = false

  local booapxsow  = false  -- f arxourown[1] d09
  local booapxexp  = false  -- f arxourown[1] d09
  local booindsow  = false  -- f arxourown[1] d09
  local booindexp  = false  -- f arxourown[1] d09
  local bood09     = false

  local boosummar  = false  -- f arxourown[2] do show on success

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

---- UPVALUE-BASED FUNCTIONS !!!FIXME!!! move ----

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

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

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

  -- CHG : qtbunch (table), qstrret (string)

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

  -- NOTE: the thing needs to be flushed by "lfhoptconcat (nil)" before
  --       using "qstrret"

  -- NOTE: if the "qstrret" string has to be changed directly
  --       (by concatenation or replace), then "lfhoptconcat (nil)" (flush)
  --       or "qtbunch = {}" (discard) must be done before !!!

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

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

---- MAIN [Z] ----

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

  ---- GUARD AGAINST INTERNAL ERROR AGAIN ----

  booerr = qbooguard -- sort of #E01 internal

  qtcostquery[0] = arxframent -- constant
  qtcostquery[1] = conboofree -- constant
  qtcostquery[2] = 0          -- counter expensive PagesInCategory
  qtcostquery[3] = 0          -- counter expensive IfExists
  qtcostquery[4] = 0          -- counter free IfExists

  ---- PICK 11 ITEMS FROM THE HUGE TABLE AND PRECHECK ----

  -- we do NOT have "nummaxwidth" yet !!!FIXME!!!
  -- spec allows 32 ... 8'000'000 but here we restrict to 320...1'000'000

  while true do -- fake loop

    if (booerr or booearsyn) then
      break -- to join mark
    end--if

    num0statcode = qtbllingbaha[0]
    if (num0statcode~=0) then
      lftracemsg ("Submodule failed with error code " .. tostring (num0statcode))
      booearsyn = true
      break -- to join mark
    end--if

    num1lenfullo = qtbllingbaha[1]
    if ((num1lenfullo>=320) and (num1lenfullo<=1000000)) then
      lftracemsg ("Passed 320...1'000'000 check with length " .. tostring (num1lenfullo))
    else
      lftracemsg ("Failed 320...1'000'000 check with length " .. tostring (num1lenfullo))
      booearsyn = true
      break -- to join mark
    end--if

    num2lenstrip = qtbllingbaha[2]
    lftracemsg ('FYI: num2lenstrip=' .. tostring (num2lenstrip))
    num3errposit = qtbllingbaha[3]
    lftracemsg ('FYI: num3errposit=' .. tostring (num3errposit))
    num4lineslin = qtbllingbaha[4]
    lftracemsg ('FYI: num4lineslin=' .. tostring (num4lineslin))

    str5errorstr = qtbllingbaha[5]
    lftracemsg ('FYI: str5errorstr="' .. tostring (str5errorstr) .. '"')
    str6errorstr = qtbllingbaha[6]
    lftracemsg ('FYI: str6errorstr="' .. tostring (str6errorstr) .. '"')

    tab7list     = qtbllingbaha[7]
    tab8forward  = qtbllingbaha[8]
    -- tab9reverse  = qtbllingbaha[9]
    -- tab10extra   = qtbllingbaha[10]
    if ((type(tab7list)~='table') or (type(tab8forward)~='table')) then -- important check
      lftracemsg ('Submodule failed to deliver [7] [8]')
      booearsyn = true
      break -- to join mark
    end--if

    break -- finally to join mark
  end--while -- fake loop -- join mark

  lftracemsg ('Big pick of 11 done, booerr=' .. tostring(booerr) .. ', booearsyn=' .. tostring(booearsyn))

  ---- SEIZE 0 ... 2 PARAMETERS ----

  -- optional 1 digit into 1 boolean (default "false")
  -- optional 2 digits into 1 num (default 100 ie 100% ie 1) (komp YES sng NO)

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

  if (arxourown[3]) then
    booerr = true -- too much
  end--if

  if (not booerr) then
    vartmp = arxourown[1] -- optional, one binary digit expected "0" or "1"
    if (type(vartmp)=="string") then
        numlong = string.len(vartmp)
        if (numlong==1) then
          numoct = string.byte (vartmp,1,1) -- "boosummar" preassigned 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 technical summary block
          end--if
        else
          booerr = true -- invalid input
        end--if (numlong==1) else
    end--if
  end--if

  if (not booerr) then
    do -- scope
      local numofct = 0
      local numofdt = 0
      local booftimp = false
      vartmp = arxourown[2] -- optional, 2 decimal digits "02"..."98" expected
      if (type(vartmp)=="string") then
        if (string.len(vartmp)==2) then
          numofct = string.byte (vartmp,1,1)
          numofdt = string.byte (vartmp,2,2)
          numofct = lfdec1digit (numofct) -- 255 if invalid
          numofdt = lfdec1digit (numofdt) -- 255 if invalid
          numproba = numofct * 10 + numofdt -- was preassigned to defau va 100
          if ((numproba>=2) and (numproba<=98)) then
            booftimp = true -- valid value
          end--if
        end--if
        booerr = not booftimp -- param specified but invalid
      end--if (type(vartmp)=="string") then
    end--do scope
  end--if

  lftracemsg ('Small seizure done, numproba=' .. tostring(numproba) .. ', booerr=' .. tostring(booerr))

  ---- SEIZE ONE NAMED OBLIGATORY PARAMETER FROM CALLER ----

  -- obligatory 6 digits about 6 items in 3 columns into 15
  -- boolean:s (all preassigned to "false")

  -- in "infsel=" expecting 6 decimal digits, value "2" accepted in some posi

  if (not booerr) then
    do -- scope
      local numluung = 0
      local numooct = 0
      strinfsel = arxourown["infsel"] -- 6 digits: tln kap vor mal apx ind
      numluung = string.len(strinfsel)
      if (numluung==6) then
        numooct = string.byte (strinfsel,1,1)
        numooct = lfdec1diglm (numooct,2) -- 255 if invalid
        booerr = booerr or (numooct==255) -- invalid input
        bootlnsow = (numooct~=0) -- show tln in d07
        bootlnexp = (numooct==2) -- query tln in d07 !!!FIXME!!!
        numooct = string.byte (strinfsel,2,2)
        numooct = lfdec1diglm (numooct,2) -- 255 if invalid
        booerr = booerr or (numooct==255) -- invalid input
        bookapsow = (numooct~=0) -- show kap in d07
        bookapexp = (numooct==2) -- query kap in d07
        bood07 = bootlnsow or bookapsow
        numooct = string.byte (strinfsel,3,3)
        numooct = lfdec1diglm (numooct,2) -- 255 if invalid
        booerr = booerr or (numooct==255) -- invalid input
        boovorsow = (numooct~=0) -- show vor in d08
        boovorexp = (numooct==2) -- query vor in d08 !!!FIXME!!!
        numooct = string.byte (strinfsel,4,4)
        numooct = lfdec1diglm (numooct,2) -- 255 if invalid
        booerr = booerr or (numooct==255) -- invalid input
        boomalsow = (numooct~=0) -- show mal in d08
        boomalexp = (numooct==2) -- query mal in d08
        bood08 = boovorsow or boomalsow
        numooct = string.byte (strinfsel,5,5) -- "apx"
        numooct = lfdec1diglm (numooct,2) -- 255 if invalid
        booerr = booerr or (numooct==255) -- invalid input
        booapxsow = (numooct~=0) -- show apx
        booapxexp = (numooct==2) -- query apx !!!FIXME!!!
        numooct = string.byte (strinfsel,6,6) -- "ind"
        numooct = lfdec1diglm (numooct,2) -- 255 if invalid
        booerr = booerr or (numooct==255) -- invalid input
        booindsow = (numooct~=0) -- show ind
        booindexp = (numooct==2) -- query ind
        bood09 = booapxsow or booindsow
      else
        booerr = true -- invalid input
      end--if (numluung==6) else
    end--do scope
  end--if

  lftracemsg ('Big seizure done, strinfsel=' .. strinfsel .. ', booerr=' .. tostring(booerr))

  ---- SEIZE NAMED PARAMETER "DETRC" EVEN IF WE ALREADY SUCK ----

  -- try to pick named param "detrc=" even if we already have an error
  -- so far have collected to "qstrtrace" unconditionally, maybe shut up now

  if (arxourown["detrc"]=="true") then
    lftracemsg ('"detrc=true" seized')
  else
    qboodetrc = false -- was preassigned to "true"
    qstrtrace = '' -- shut up now
  end--if

  lftracemsg ('All params done, "booerr" is "' .. tostring(booerr) .. '" so far')

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

  if (constrpriv=="eo") then
    constrlnkpu    = lfhkodeosg(constrlnkpu)   -- "Klaku cxi tie (kaj" ...
    contabpages[4] = lfhkodeosg(contabpages[4])
    contabd10d11w  = lfhkodeotb(contabd10d11w) -- 1,2 -- "fermita aux malplena"
    contaberaroj   = lfhkodeotb(contaberaroj)
    contabdestit   = lfhkodeotb(contabdestit)  -- 0...13 -- table headings
    contabbigtiny  = lfhkodeotb(contabbigtiny) -- 0...4 -- for big & tiny 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 = lfispacundr(strtpm,true) -- replace space by underscore in URL
  strtmp = 'http://' .. constrpriv .. '.wiktionary.org/wiki/' .. strtpm .. '?action=purge'

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

  ---- CHECK THE 0TH Y-INDEX MARKER ----

  -- check against "constrpriv" and assign "booearsyn"

  if (not (booerr or booearsyn)) then
    booearsyn = (tab7list[0]~=constrpriv) -- must be "eo" or "id"
  end--if

  if (not (booerr or booearsyn)) then
    numrowinx = 0 -- main index
    numminwyd = nummaxwidth -- record will sink
    nummaxwyd = 0 -- record will grow
    nummaxc0n = 0 -- evaluated maximal bloat of language name site
    nummaxc2n = 0 -- evaluated maximal bloat of language name propralingve
    nummaxkal = 0 -- evaluated maximal bloat of category link
  end--if

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

  -- using "constrtdbgtit" and "constrtden" for "<td"...">" and "</td>"

  -- here we start using "lfhoptconcat", the thing has been initialized
  -- by <<"local qstrret = "">> and <<local qtbunch = {}>>

  -- using function "lfbrewtitsel" som does NOT add "<td"...">" "</td>"

  if (not (booerr or booearsyn)) then
    boohavtbl = true
    lfhoptconcat (constrhutabegin) -- "<table"... and "<tr>"
    do -- scope
      local numtaamp = 0 -- ZERO-based
      local booxxtop = false
      local booxxbtm = false
      local bootiimp = false
      while true do -- iterate over table columns
        if (numtaamp==14) then -- valid indexes 0...13
          break
        end--if
        booxxtop = true
        booxxbtm = true
        booshowthiscol = true -- hide column if false
        if (numtaamp==7) then
          booshowthiscol = bood07 -- column "d07" "tln" "kap" can be hidden
          booxxtop = bootlnsow
          booxxbtm = bookapsow
        end--if
        if (numtaamp==8) then
          booshowthiscol = bood08 -- column "d08" "vor" "mal" can be hidden
          booxxtop = boovorsow
          booxxbtm = boomalsow
        end--if
        if (numtaamp==9) then
          booshowthiscol = bood09 -- column "d09" "apx" "ind" can be hidden
          booxxtop = booapxsow
          booxxbtm = booindsow
        end--if
        if (booshowthiscol) then
          lfhoptconcat (constrtdbgtit .. lfbrewtitsel (numtaamp,booxxtop,booxxbtm) .. constrtden) -- submit table cell
        end--if
        numtaamp = numtaamp + 1 -- count even hidden columns
      end--while
      lfhoptconcat ('</tr>') -- close line but keep table open
    end--do scope
  end--if

  ---- MAIN LOOP ----

  if (not (booerr or booearsyn)) then

    while true do -- iterate over all table rows

      strtblcy = tab7list[numrowinx] or '' -- value is lng code
      lftracemsg ('about to begin a new row, numrowinx=' .. tostring(numrowinx) .. ', strtblcy=' .. strtblcy)
      strsrcrow = tab8forward[strtblcy] or '' -- value is complete line
      if ((strtblcy=='') or (strsrcrow=='')) then
        lftracemsg ('end of table reached, numrowinx=' .. tostring (numrowinx))
        break
      end--if
      numtump = string.len(strtblcy) + 5 -- get ONE-based position after "]]"
      numtamp = string.len(strsrcrow)
      if (numtump>numtamp) then
        boosinerr = true -- this criminal, abort table generation after row
        strsrcrow = "??" -- should impossible to occur unless submodule broken
      else
        strsrcrow = string.sub(strsrcrow,numtump,numtamp) -- discard "cy" part
      end--if

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

      lfhoptconcat ('<tr>')

      -- begin "d00" -- index number and lang code
      strbkn = constrbkco -- color code without "#" cross
      if (strtblcy=="eo") then
        strbkn = '90FF90' -- green decoration
      end--if
      strdeste = '(' .. tostring (numrowinx) .. ') <b>' .. strtblcy .. '</b>'
      if (not boomxwerr) then
        numtamp = 0
        strtmp = lfyseizesubstring (strsrcrow,"-") -- count substrings
        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<11) then -- expect all "c0" to "c10"
            strbkn = 'FFD8D8' -- reddish
            strdeste = strdeste .. '<br>' .. lfbrewerrsv(12,0) -- err (#E12 mini)
            numerrtru = numerrtru + 1 -- this is NOT fatal (not "kec" either)
          end--if
          if (numtamp>11) then
            strbkn = 'FFB0B0' -- red -- error overrides decoration
            strdeste = strdeste .. '<br>' .. lfbrewerrsv(15,1) -- err (#E15 lagom)
            numerrtlo = numerrtlo + 1 -- this is NOT fatal (but lagom)
          end--if
          if (numtamp~=11) then
            strdeste = strdeste .. ' (' .. tostring(numtamp) .. ')'
          end--if
        end--if (numtamp==0) else
      end--if
      if (boomxwerr or boosinerr) then -- or have_sort_error !!!FIXME!!!
        strbkn = 'FFB0B0' -- red -- error overrides decoration
      end--if
      strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme with color
      lfhoptconcat (strt3d .. strdeste .. constrtden)
      -- done "d00"

      if (not (boomxwerr or boosinerr)) then

        -- begin "c0" -- lingvonomo in site language -- no rl-enclos possible
        strtblc0 = lfyseizesubstring (strsrcrow,"0")
        strtblc0 = lfpreproeqmi (strtblc0) -- "=" -> "-"
        booc0bad = (not lfivalidatestr(strtblc0,nil,2,connummaaxc0nlen,0,0))
        boosinerr = boosinerr or booc0bad
        numafstbfcl = string.len (strtblc0) -- no stripping here len befor cli
        strtblc0 = lfclamp(strtblc0,(connummaaxc0nlen+4)) -- even "-" is bad
        if (numafstbfcl>nummaxc0n) then
          nummaxc0n = numafstbfcl -- new record established
        end--if
        -- done "c0"

        tabstuff["LK"] = strtblcy -- for "lfinsertultim"
        tabstuff["LN"] = strtblc0 -- for "lfinsertultim"
        tabstuff["LU"] = lfucasestr(strtblc0,true,false,2) -- lng name uppercase

        -- begin "d01" -- lemma page
        strbkn = constrbkco -- preASSume -- color code without "#" cross
        if (booc0bad) then
          strbkn = 'FFB0B0' -- red
          strdeste = lfevilitem(1,0,strtblc0) -- show the evil -- bad lng name
        else
          strtpm = lfinsertultim(contabpages[0],tabstuff) -- augment and maybe uc
          strdeste = '[[' .. strtpm .. '|' .. strtblc0 .. ']]' -- wl to lem pg
        end--if
        strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
        lfhoptconcat (strt3d .. strdeste .. constrtden)
        -- done "d01"

        -- begin "c1" -- Q-item -- no rl-enclos possible
        strtblc1 = lfyseizesubstring (strsrcrow,"1")
        strtblc1 = lfpreproeqmi (strtblc1) -- "=" -> "-"
        strtblc1 = lfclamp(strtblc1,14) -- valid len range 3...9 including "Q"
        booc1bad = false
        if (strtblc1~="-") then
          booc1bad = not lfivalidatequack(strtblc1) -- sub gives true if valid
        end--if
        -- done "c1"

        -- begin "d02" -- Q-item
        strbkn = constrbkco -- preASSume -- color code without "#" cross
        strdeste = strtblc1 -- preASSume -- already clamped
        if (booc1bad) then
          strbkn = 'FFB0B0' -- red
          strdeste = lfevilitem(4,1,strtblc1) -- show the evil -- bad Q-item
          boosinerr = true -- this criminal, abort table generation after row
        else
          if (strtblc1=="-") then -- nice to have, do not abort
            strbkn = 'FFD8D8' -- reddish if not available
            numerrkec = numerrkec + 1
          else
            strdeste = '[[d:' .. strtblc1 .. '|' .. strtblc1 .. ']]' -- link
          end--if
        end--if
        strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
        lfhoptconcat (strt3d .. strdeste .. constrtden)
        -- done "d02"

        -- begin "c2" -- propralingve -- rl-enclos possible
        strtblc2 = lfyseizesubstring (strsrcrow,"2")
        strtblc2 = lfpreproeqmi (strtblc2) -- "=" -> "-"
        strtblc2 = lfhrlstrip(strtblc2)
        numafstbfcl = string.len (strtblc2) -- len after strip before clamp
        if (numafstbfcl>nummaxc2n) then
          nummaxc2n = numafstbfcl -- new record established
        end--if
        strtblc2 = lfclamp(strtblc2,(connummaaxc2nlen+4))
        booc2bad = (not lfivalidatestr(strtblc2,"-",2,connummaaxc2nlen,0,0))
        -- done "c2"

        -- begin "d03" -- propralingve
        strbkn = constrbkco -- preASSume -- color code without "#" cross
        strdeste = strtblc2 -- preASSume -- already clamped
        if (booc2bad) then
          strbkn = 'FFB0B0' -- red
          strdeste = lfevilitem(1,2,strtblc2) -- show the evil -- bad lng name
          boosinerr = true -- this criminal, abort table generation after row
        else
          if (strtblc2=="-") then -- nice to have, do not abort
            strbkn = 'FFD8D8' -- reddish if not available
            numerrkec = numerrkec + 1
          end--if
        end--if
        strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
        lfhoptconcat (strt3d .. strdeste .. constrtden)
        -- done "d03"

        -- begin "c3" -- constructed and antique status
        strtblc3 = lfyseizesubstring (strsrcrow,"3")
        strtblc3 = lfpreproeqmi (strtblc3) -- "="->"-" but no rl-enclos possib
        strtblc3 = lfclamp(strtblc3,10) -- valid length 1 only
        -- done "c3"

        -- begin "d04" -- constructed and antique status
        strbkn = constrbkco -- color code without "#" cross
        boolocerr = false
        if (strtblc3=="-") then -- nice to have, do not abort
          strbkn = 'FFD8D8' -- reddish
          strdeste = "-"
          numerrkec = numerrkec + 1
        else
          numtamp = string.len(strtblc3) -- length after clamping
          if (numtamp~=1) then -- length after clamping
            boolocerr = true
          else
            numoct = string.byte (strtblc3,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 (strtblc3=="-") else
        if (boolocerr) then
          strbkn = 'FFB0B0' -- red -- error overrides decoration
          strdeste = lfevilitem(0,3,strtblc3) -- show the evil -- "bad code"
          boosinerr = true -- this criminal, abort table generation after row
        end--if
        strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
        lfhoptconcat (strt3d .. strdeste .. constrtden)
        -- done "d04"

        -- begin "c4" -- 2-letter code -- no rl-enclos possible
        strtblc4 = lfyseizesubstring (strsrcrow,"4")
        strtblc4 = lfpreproeqmi (strtblc4) -- "=" -> "-"
        strtblc4 = lfclamp(strtblc4,10) -- 2-letter code or "--" expected
        if (strtblc4=="--") then
          booc3bad = false -- 2 valid alternative values "-" and "--" exist
        else
          booc3bad = (not lfivalidatestr(strtblc4,"-",2,2,2,3))
        end--if -- done "c4"

        -- begin "d05" -- 2-letter code
        strbkn = constrbkco -- color code without "#" cross
        if (booc3bad) 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' -- reddish if no ISO 639-1:2002 code
            numerrkec = numerrkec + 1
          end--if
        end--if
        strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
        lfhoptconcat (strt3d .. strdeste .. constrtden)
        -- done "d05"

        strtblc5 = lfyseizesubstring (strsrcrow,"5") -- bg src "c5"
        strtblc5 = lfpreproeqmi (strtblc5) -- "="->"-" but no rl-enclos possib
        strtblc5 = lfclamp(strtblc5,10) -- 3-letter code or "---" expected
        if (strtblc5=="---") then
          booc4bad = false -- 2 valid alternative values "-" and "---" exist
        else
          booc4bad = (not lfivalidatestr(strtblc5,"-",3,3,2,3))
        end--if -- nice to have -- done "c5"

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

        -- begin "d07" -- "tln" + "kap" (!!! can be hidden !!!)
        if (bood07) then
          strbkn = constrbkco -- color code without "#" cross
          if (booc0bad) then
            strbkn = 'FFB0B0' -- red
            strdeste = "??" -- kat (we have already seen bad "c0")
          else
            strdeste = '' -- crucial
            if (bootlnsow) then
              strtmp = lfinsertultim(contabpages[5],tabstuff) -- augm maybe uc
              bootimp,strtmp = lfykattlaenk (strtmp,false)
              strdeste = strtmp -- "tln"
            end--if (bootlnsow) then
            if (bootlnsow and bookapsow) then
              strdeste = strdeste .. '<br>'
            end--if
            if (bookapsow) then
              strtmp = lfinsertultim(contabpages[6],tabstuff) -- augm maybe uc
              bootimp,strtmp = lfykattlaenk (strtmp,(bookapexp and boorussia))
              strdeste = strdeste .. strtmp -- "kap"
              if (not bootimp) then
                strbkn = 'FFD8D8' -- reddish if "kap" kat does not exist
                numerrkap = numerrkap + 1
              end--if
            end--if (bookapsow) then
          end--if
          strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
          lfhoptconcat (strt3d .. strdeste .. constrtden)
        end--if (bood07) then
        -- done "d07"

        -- begin "d08" -- "vor" + "mal" (!!! can be hidden !!!)
        if (bood08) then
          strbkn = constrbkco -- color code without "#" cross
          if (booc0bad) then
            strbkn = 'FFB0B0' -- red
            strdeste = "??" -- kat (we have already seen bad "c0")
          else
            strdeste = '' -- crucial
            if (boovorsow) then
              strtmp = lfinsertultim(contabpages[3],tabstuff) -- augm maybe uc
              bootimp,strtmp = lfykattlaenk (strtmp,false)
              strdeste = strtmp -- "vor"
            end--if (boovorsow) then
            if (boovorsow and boomalsow) then
              strdeste = strdeste .. '<br>'
            end--if
            if (boomalsow) then
              strtmp = lfinsertultim(contabpages[4],tabstuff) -- augm maybe uc
              bootimp,strtmp = lfykattlaenk (strtmp,(boomalexp and boorussia))
              strdeste = strdeste .. strtmp -- "mal"
              if (not bootimp) then
                strbkn = 'FFD8D8' -- reddish if "mal" kat does not exist
                numerrmal = numerrmal + 1
              end--if
            end--if (boomalsow) then
          end--if
          strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
          lfhoptconcat (strt3d .. strdeste .. constrtden)
        end--if (bood08) then
        -- done "d08"

        -- begin "d09" -- Appendix + Index (!!! can be hidden !!!)
        if (bood09) then
          strbkn = constrbkco -- color code without "#" cross
          if (booc0bad) then
            strbkn = 'FFB0B0' -- red
            strdeste = "??" -- non-kat (we have already seen bad "c0")
          else
            strdeste = '' -- crucial
            if (booapxsow) then
              strtmp = lfinsertultim(contabpages[1],tabstuff) -- augm maybe uc
              bootimp,strtmp = lfyapxindlaenk (strtmp,false,false)
              strdeste = strtmp -- "apx"
            end--if (booapxsow) then
            if (booapxsow and booindsow) then
              strdeste = strdeste .. '<br>'
            end--if
            if (booindsow) then
              strtmp = lfinsertultim(contabpages[2],tabstuff) -- augm maybe uc
              bootimp,strtmp = lfyapxindlaenk (strtmp,true,(booindexp and boorussia))
              strdeste = strdeste .. strtmp -- "ind"
              if (not bootimp) then
                strbkn = 'FFD8D8' -- reddish if "ind" page does not exist
                numerrind = numerrind + 1
              end--if
            end--if (booindsow) then
          end--if
          strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
          lfhoptconcat (strt3d .. strdeste .. constrtden)
        end--if (bood09) then
        -- done "d09"

        booc6c7bad = false -- common for "c6" and "c7"

        -- begin "c6" -- wiki access code -- no rl-enclos possib
        strtblc6 = lfyseizesubstring (strsrcrow,"6")
        strtblc6 = lfpreproeqmi (strtblc6) -- "="->"-" but no rl-enclos possib
        strtblc6 = lfclamp(strtblc6,16) -- wiki access code
        if (strtblc6=="-") then -- nice to have, long codes permitted, "??" permitted
          strtblc6 = strtblcy -- copy access code from "cy"
        else
          if (not lfivalidatelnkoadv(strtblc6,false,true,true,false,false)) then -- function returns true if valid
            booc6c7bad = true -- this will become "boosinerr = true"
          end--if
        end--if
        -- done "c6"

        -- begin "c7" -- wiki availability code -- no rl-enclos possib
        strtblc7 = lfyseizesubstring (strsrcrow,"7")
        strtblc7 = lfpreproeqmi (strtblc7) -- "="->"-" but no rl-enclos possib
        strtblc7 = lfclamp(strtblc7,10) -- availability 2 digits
        numtamp = string.len(strtblc7) -- length after clamping
        numc7pedi = 3
        numc7tion = 3
        if (strtblc7~="-") then -- nice to have (otherwise reddish !!!)
          if (numtamp==2) then
            numc7pedi = string.byte(strtblc7,1,1) -- availability code
            numc7tion = string.byte(strtblc7,2,2) -- availability code
            numc7pedi = lfdec1diglm (numc7pedi,2) -- 0...2 or 255 if invalid
            numc7tion = lfdec1diglm (numc7tion,2) -- 0...2 or 255 if invalid
            if ((numc7pedi==255) or (numc7tion==255)) then
              booc6c7bad = true -- this will become "boosinerr = true"
            end--if
          else
            booc6c7bad = true -- this will become "boosinerr = true"
          end--if
        end--if
        -- done "c7"

        -- begin "d10" -- other ipedia main page
        strbkn = constrbkco -- color code without "#" cross
        if (booc6c7bad) then
          strbkn = 'FFB0B0' -- red -- error overrides decoration
          strdeste = lfevilitem(0,67,strtblc6) -- show the evil -- "bad code"
          boosinerr = true -- this criminal, abort table generation after row
        else
          strdeste = lfbrewurl (strtblc6,false,nil) -- other ipedia main page
          if (numc7pedi==3) then
            strbkn = 'FFD8D8' -- reddish if "c6" was empty or "-"
          else
            strbkn = lfavailco(numc7pedi)
            strdeste = strdeste .. lfavailnt(numc7pedi) -- <br>+notice or empty
          end--if (numc7pedi==3) else
        end--if
        strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
        lfhoptconcat (strt3d .. strdeste .. constrtden)
        -- done "d10"

        -- begin "d11" -- other tionary main page
        strbkn = constrbkco -- color code without "#" cross
        if (booc6c7bad) then
          strbkn = 'FFB0B0' -- red -- error overrides decoration
          strdeste = lfevilitem(0,67,strtblc7) -- show the evil -- "bad code"
          boosinerr = true -- this criminal, abort table generation after row
        else
          if (strtblcy==constrpriv) then
           strdeste = ':-)' -- only for "d11" cell "other tionary" and "d13"
          else
            strdeste = lfbrewurl (strtblc6,true,nil) -- other tionary main page
            if (numc7tion==3) then
              strbkn = 'FFD8D8' -- reddish if "c6" was empty or "-"
            else
              strbkn = lfavailco(numc7tion)
              strdeste = strdeste .. lfavailnt(numc7tion) -- <br>+notice or empt
            end--if (numc7tion==3) else
          end--if
        end--if
        strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
        lfhoptconcat (strt3d .. strdeste .. constrtden)
        -- done "d11"

        -- begin "c8" -- article in own wikipedia -- no rl-enclos possib
        strtblc8 = lfyseizesubstring (strsrcrow,"8")
        strtblc8 = lfpreproeqmi (strtblc8) -- "="->"-" but no rl-enclos possib
        booc8bad = (not lfivalidatestr(strtblc8,"-",2,32,0,0))
        strtblc8 = lfclamp(strtblc8,36) -- name of ipedia article -- done "c8"
        -- done "c8"

        -- begin "d12" -- article in own wikipedia
        strbkn = constrbkco -- color code without "#" cross
        if (booc8bad) then -- "c7" is bad
          strbkn = 'FFB0B0' -- red
          strdeste = lfevilitem(2,8,strtblc8) -- show the evil -- "bad title"
          boosinerr = true -- this criminal, abort table generation after row
        else
          if ((strtblc8=="-") and booc0bad) then -- nice to have "c7"
            strbkn = 'FFB0B0' -- red if we have neither "c0" nor "c7"
            strdeste = '-'
          else
            strtmp = strtblc8 -- name of wp article, BEWARE: may contain space
            bootimp = false
            if (strtmp=="-") then
              bootimp = true -- this is semi-evil, we have to guess
              strtmp = lfinsertultim(contabpages[7],tabstuff) -- augment and maybe uc
            end--if
            strdeste = lfbrewurl (constrpriv,false,strtmp) -- own ipedia article
            if (bootimp) then
              strbkn = 'FFD8D8' -- reddish if we had to guess
              strdeste = strdeste .. ' (??)'
              numerrkec = numerrkec + 1
            end--if
          end--if
        end--if
        strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
        lfhoptconcat (strt3d .. strdeste .. constrtden)
        -- done "d12"

        -- begin "c9" -- cat in other tionary -- rl-enclos is possib
        strtblc9 = lfyseizesubstring (strsrcrow,"9")
        strtblc9 = lfpreproeqmi (strtblc9) -- "="->"-" and rl-enclos possible
        strtblc9 = lfhrlstrip(strtblc9) -- category link
        numafstbfcl = string.len(strtblc9) -- length after strip before clamp
        if (numafstbfcl>nummaxkal) then
          nummaxkal = numafstbfcl -- new record establishd "connummaxc8catlen"
        end--if
        strtblc9 = lfclamp(strtblc9,(connummaxc8catlen+4))
        -- done "c9"

        -- begin "ca" -- number of lemmas in that cat -- no rl-enclos possib
        strtblca = lfyseizesubstring (strsrcrow, "10")
        strtblca = lfpreproeqmi (strtblca) -- "="->"-" but no rl-enclos possib
        numafstbfkp = string.len(strtblca) -- length before clamping
        strtblca = lfclamp(strtblca,12)
        -- done "ca"

        -- begin "d13" -- cat in other tionary with number of lemmas
        strbkn = constrbkco -- color code without "#" cross
        boolocerr = false
        boolokeer = false
        if (strtblc9~="-") then -- do NOT evaluate evilness of "-" in "c9"
          if ((numafstbfcl<8) or (numafstbfcl>connummaxc8catlen)) then -- "c9" bad
            boolocerr = true -- length out of range
          else
            numtamp = lfcountchr(strtblc9,58)
            if ((numtamp==0) or (numtamp>2)) then -- "c9" bad
              boolocerr = true -- bad number of colons, ONE or TWO required
            end--if
          end--if
        end--if
        if (strtblca~="-") then -- do NOT evaluate evilness of "-" in "ca"
          if (numafstbfkp>8) then -- "ca" bad
            boolokeer = true -- length out of range (no minimum)
          else
            if (lfcountndg(strtblca,2)~=0) then -- "ca" 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 "c9" or "ca"
          strdeste = '' -- preassign to empty, may be needed below
          if (boolocerr) then
            strdeste = lfevilitem(3,9,strtblc9) -- 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(5,10,strtblca) -- ev "bad number"
          end--if
          boosinerr = true -- this criminal, abort table generation after row
        else
          if (strtblcy==constrpriv) then
            strdeste = ':-)' -- only for "d11" cell "other tionary" and "d13"
          else
            if (strtblc9=='-') then
              strbkn = 'FFD8D8' -- reddish if no category
              strdeste = '-'
              numerrkec = numerrkec + 1
            else
              strdeste = lfbrewurl (strtblc6,true,strtblc9) -- other tionary cat
              strdeste = strdeste .. '<br>'
              if (strtblca=="-") then
                strdeste = strdeste .. lfinumberinkat(-1) -- NOT count as error
              else
                numtump = tonumber(lfremovenondi(strtblca)) -- apo:s tolerable
                strdeste = strdeste .. lfinumberinkat(numtump) -- apo:s added
              end--if (strtblca=='-') else
            end--if (strtblc9=='-') else
          end--if (strtblcy==constrpriv) else
        end--if (boolocerr or boolokeer) else
        strt3d = constrtddf .. strbkn .. constrtdfd -- long "td" eleme
        lfhoptconcat (strt3d .. strdeste .. constrtden)
        -- done "d13"

      end--if (not (boomxwerr or boosinerr)) then

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

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

      numrowinx = numrowinx + 1 -- main ZERO-based counter

    end--while

  end--if (not (booerr or booearsyn)) then

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

  if (booerr or booearsyn) then
    qtbunch = {} -- crucial
    if (num0statcode==0) then
      lfhoptconcat (lfbrewerrsv(1,2)) -- #E01 param or internal, huge
    else
      lfhoptconcat (lfbrewerrsv(num0statcode,2)) -- #E02...#E12 from submodule, huge
    end--if
  else
    if (boohavtbl) then
      lfhoptconcat ('</table>')
    end--if
    if (boomxwerr) then
      lfhoptconcat (lfbrewerrsv(17,2)) -- #E17 outside the table -- "maxwidth" vi !!!FIXME!!!
    end--if
    if (boosinerr) then
      lfhoptconcat (lfbrewerrsv(16,2)) -- #E16 outside the table -- other error
    end--if
  end--if

  ---- MERGE BAD NEWS ----

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

  boogtabort = (booearsyn or boosinerr or boomxwerr)
  boodofatal = ((booerr or boogtabort) or (numerrtlo~=0))

  ---- BREW THE BIG FATAL BLOCK OR TINY SUCCESS BLOCK ----

  -- * block is displayed in any case and enclosed in a "div" box in any case,
  --   but the style heavily depends on "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 .. contabbigtiny[0] .. '. ' .. strpurge .. ' ' .. contabbigtiny[1]
    strtmp = strtmp .. ' ' .. constrsumbr .. ' ' .. contabbigtiny[2] .. '. ' .. contabbigtiny[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 .. ' ' .. contabbigtiny[4] .. ' ' .. constrsumbr .. '.</div>'
  end--if

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

  -- * the technical 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)
  -- * we use "lfnumtodecbun" for numbers with risk
  --   of >= 1'000 and partially "lftostwauc" and "lftostwaz" and "lftostw2p"

  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 .. '"' .. strinfsel .. '", ' .. tostring(numproba) .. '</li>'

    strsumbl = strsumbl .. '<li>' .. contabsum[1] .. lfnumtodecbun(num1lenfullo) .. ' -> ' .. lfnumtodecbun(num2lenstrip) .. '</li>' -- source
    strsumbl = strsumbl .. '<li>' .. contabsum[2] .. lfnumtodecbun(numrowinx) .. '</li>' -- lang
    strsumbl = strsumbl .. '<li>' .. contabsum[3] .. lftostwaz(0) .. '</li>' -- sort !!!FIXME!!!
    strsumbl = strsumbl .. '<li>' .. contabsum[4] .. lfnumtodecbun(numerrtru) .. '</li>' -- trunc (ele)
    strsumbl = strsumbl .. '<li>' .. contabsum[5] .. lftostwaz(numerrtlo) .. '</li>' -- too long (ele)
    strsumbl = strsumbl .. '<li>' .. 'errkec : ' .. lfnumtodecbun(numerrkec) .. '</li>' -- minor
    strsumbl = strsumbl .. '<li>' .. 'errkap : ' .. lfnumtodecbun(numerrkap) .. '</li>' -- missing "kap" cat
    strsumbl = strsumbl .. '<li>' .. 'errmal : ' .. lfnumtodecbun(numerrmal) .. '</li>' -- missing "mal" cat
    strsumbl = strsumbl .. '<li>' .. 'errind : ' .. lfnumtodecbun(numerrind) .. '</li>' -- missing "ind" page
    strsumbl = strsumbl .. '<li>' .. 'srctblbeg : ' .. lfnumtodecbun(0) .. '</li>' -- bloat !!!FIXME!!! area
    strsumbl = strsumbl .. '<li>' .. 'srctblend : ' .. lfnumtodecbun(0) .. '</li>' -- bloat !!!FIXME!!! area

    strsumbl = strsumbl .. '<li>' .. 'srctblper : ' -- earliest abort syntax err
    if (boogtabort) then
      strsumbl = strsumbl .. lftostwauc(0) -- !!!FIXME!!! position
    else
      strsumbl = strsumbl .. 'N/A'
    end--if
    strsumbl = strsumbl .. '</li>'

    strsumbl = strsumbl .. '<li>' .. 'eval minwid, limit minwid : ' -- minwidth
    strsumbl = strsumbl .. tostring(numminwyd) .. ', ' .. tostring(numminwidth) .. '</li>'
    strsumbl = strsumbl .. '<li>' .. 'eval maxwid, limit maxwid : ' -- maxwidth
    strsumbl = strsumbl .. tostring(nummaxwyd) .. ', ' .. tostring(nummaxwidth) .. '</li>'

    strsumbl = strsumbl .. '<li>' .. 'eval maxc0lngname, limit maxc0lngname : '
    strsumbl = strsumbl .. tostring(nummaxc0n) .. ', ' .. tostring(connummaaxc0nlen) .. '</li>'
    strsumbl = strsumbl .. '<li>' .. 'eval maxc2lngname, limit maxc2lngname : '
    strsumbl = strsumbl .. tostring(nummaxc2n) .. ', ' .. tostring(connummaaxc2nlen) .. '</li>'
    strsumbl = strsumbl .. '<li>' .. 'eval maxkatlink, limit maxkatlink : '
    strsumbl = strsumbl .. tostring(nummaxkal) .. ', ' .. tostring(connummaxc8catlen) .. '</li>'

    strsumbl = strsumbl .. '<li>' .. 'expe-pik : ' .. lftostw2p(qtcostquery[2],499) .. '</li>' -- expensive "pagesincategory"
    strsumbl = strsumbl .. '<li>' .. 'expe-ife : ' .. lftostw2p(qtcostquery[3],499) .. '</li>' -- expensive "ifexist"
    strsumbl = strsumbl .. '<li>' .. 'free-ife : ' .. lftostw2p(qtcostquery[4],499) .. '</li>' -- free "ifexist"
    strsumbl = strsumbl .. '<li>' .. 'dsttbl-siz : ' .. lfnumtodecbun(string.len(qstrret)) .. '</li>' -- dst bloat

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

  end--if

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

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

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

  if (qboodetrc) then
    qstrret = "<br>" .. qstrtrace .. "<br><br>" .. qstrret
  end--if
  return qstrret

end--function

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

return exporttable