Saltu al enhavo

Modulo:eht

El Vikivortaro
 MODULO
Memtesto disponeblas sur la paĝo Ŝablono:eht.

--[===[

MODULE "EHT" (enhavtabelo)

"eo.wiktionary.org/wiki/Modulo:eht" <!--2024-Nov-08-->

Purpose: displays TOC of a cat only if there are at least 300
         pages or at least 300 subcategories, and automatically picks
         correct alphabet based on langname read out from pagename

Utilo: montras enhavtabelon de kategorio nur se disponeblas almenaux 300
       pagxoj aux almenaux 300 sukategorioj, kaj ...

Manfaat: menlihatkan daftar isi kategori ...

Used by templates / Uzata far sxablonoj /
Digunakan oleh templat / Anvaent av mallar:
* only "eht"

Required submodules / Bezonataj submoduloj /
Submodul yang diperlukan / Behoevda submoduler:
* "loaddata-tbllingvoj" T80 in turn requiring template "tbllingvoj" (EO)
* "loaddata-tblbahasa" T80 in turn requiring template "tblbahasa" (ID)
* "loaddata-tblalfabetoj"  !!!FIXME!!!
* "ind12dim"               !!!FIXME!!!

Required templates:
* "KategorioEHT-etiopia-skribo"  !!!FIXME!!!
* "eht-kat-alfa"                 !!!FIXME!!!

Incoming: * no ordinary parameters
          * 4 hidden parameters
            * "pagenameoverridetestonly=" -- can directly cause #E01
            * "nsnumberoverridetestonly="
            * "tocforceoverridetestonly=" -- "on" or "off"
            * "detrc=" no error possible

Returned: * either a box or error message or empty, tracking cat:s
            only on error

Possible errors:
* <<#E01 Internal error in module "eht">>
  Possible causes:
  * strings not uncommented
  * function "mw.title.getCurrentTitle().text" AKA "{{PAGENAME}}" failed
* <<#E02 Malica eraro en subprogramaro uzata far sxablono "eht">>
  Possible causes:
  * submodule "loaddata-tbllingvoj" not found
  * submodule "loaddata-tbllingvoj" caused unspecified failure
* <<#E03 Nombrigita eraro en subprogramaro uzata far sxablono "eht">>
  Possible causes:
  * submodule failed and returned valid error code
* <<#E10 Erara uzo de sxablono (eht), uzebla nur en nomspaco 14 (kategorio)>>
* <<#E11 Evidente nevalida lingvokodo en pagxonomo>>
* <<#E15 Erara uzo de sxablono (eht), nevalida aux nekonata
         lingvonomo en pagxonomo>>
* <<#E16 SXablono ne redonis validan rezulton>>  !!!FIXME!!!

Possible tracking cat:s:
* [[Kategorio:Evidente nevalida lingvokodo]]         #E11
* [[Kategorio:Nekonata lingvonomo]]                  #E15
* [[Kategorio:Erara uzo de sxablono]]                #E10 #E16
* [[Kategorio:Erara uzo de sxablono (eht)]]          #E10 #E16
* [[Kategorio:Erara uzo de sxablono (eht, E16)]]     #E10 #E16

]===]

local exporttable = {}

require('strict')

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

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

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

-- constant table -- ban list -- add obviously invalid access codes (2-letter or 3-letter) only

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

-- controversial codes (sh sr hr), (zh cmn)
-- "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/gem" only valid in ISO 639-2 and 639-5, "collective"
-- "iso639-3.sil.org/code/zxx" "No linguistic content"

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

-- uncommentable (site-related features)

      local constringvoj = 'Modulo:loaddata-tbllingvoj'    -- EO
        -- local constringvoj = 'Modul:loaddata-tblbahasa'    -- ID
      local constrbetoj = 'Modulo:loaddata-tblalfabetoj'   -- EO
        -- local constrbetoj = 'Modul:loaddata-tblabjad"      -- ID

-- uncommentable constant table (error messages)

-- #E02...#E99, holes permitted
-- note that #E00 and #E01 are NOT supposed to be included here
-- separate "strpikparent" needed for "\\@"

local contaberaroj = {}
      contaberaroj[02] = 'Malica eraro en subprogramaro uzata far \\@'               -- EO #E02
        -- contaberaroj[02] = 'Kesalahan jahat dalam subprogram digunakan oleh \\@'     -- ID #E02
      contaberaroj[03] = 'Nombrigita eraro en subprogramaro uzata far \\@'           -- EO #E03
        -- contaberaroj[03] = 'Kesalahan ternomor dalam subprogram digunakan oleh \\@'  -- ID #E03
      contaberaroj[10] = 'Erara uzo de \\@, uzebla nur en nomspaco 14 (kategorio)'                      -- EO #E10
        -- contaberaroj[10] = 'Penggunaan salah \\@, hanya bisa digunakan dalam ruang nama 14 (kategori)'  -- ID #E10

-- uncommentable constant table (tracking cat:s)

local contabtrack = {}
      contabtrack['E11']    = 'Evidente nevalida lingvokodo'
      contabtrack['E15']    = 'Nekonata lingvonomo'
      contabtrack['cetere'] = 'Erara uzo de sxablono'

-- uncommentable patterns for cat names for lfhgetlangfromcat

local contabfarado = {} -- 3 types -- there can follow space and script code
contabfarado['Vorto -'    ] = '- enhavanta morfemon ' -- "Vorto -en- enhavanta morfemon U (-ist)" -- BEWARE ends with space
contabfarado['Frazo -'    ] = '- enhavanta vorton ('  -- "Frazo -en- enhavanta vorton (nope)"
contabfarado['Vortgrupo -'] = '- enhavanta ('         -- "Vortgrupo -en- enhavanta (nope)"

local contabfullcat = {}
contabfullcat['Aldona pagxo pri unuopa lingvo'] = 'eo'
contabfullcat['Fundamenta elemento'           ] = 'eo'
contabfullcat['SXablonaro pri specifa lingvo' ] = 'en'
contabfullcat['Vortfarado'                    ] = 'mul'

local contabsuffcat = {}
contabsuffcat[' laux lingvo'] = 'eo' -- BEWARE begins with space

-- surrogate transcoding table (only needed for EO)

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

-- constant strings (error circumfixes)

local constrelabg = '<span class="error"><b>'  -- lagom whining begin
local constrelaen = '</b></span>'              -- lagom whining end
local constrlaxhu = '&nbsp;&#42;&#42;&nbsp;'   -- lagom -> huge circumfix " ** "

-- langcodes with fallbacks

local contabfall = {} -- left column for supported codes and possible targets, other columns fallback codes
contabfall [ 1] = {'sv', 'da', 'fi', 'fit', 'no', 'nb', 'nn'}
contabfall [ 2] = {'ru', 'be', 'bg', 'sr', 'uk'}
contabfall [ 3] = {'de', 'bar', 'lb', 'vo'}
contabfall [ 4] = {'etio', 'am', 'gez', 'om', 'ti', 'tig', 'har'}
contabfall [ 5] = {'en'}
contabfall [ 6] = {'cv'}
contabfall [ 7] = {'eo'}
contabfall [ 8] = {'hy'}
contabfall [ 9] = {'mul'}
contabfall [10] = {'os'}
contabfall [11] = {'rue'}
contabfall [12] = {'sud'}
contabfall [13] = {'tg'}

-- diverse tuning values in separate variables

local conbookodlng = false -- "true" to allow long codes like "zh-min-nan"
local conboomiddig = false -- "true" to allow middle digit like "s7a"

-- uncommentable (override)

-- * name of table MUST always be defined, OTOH elements are usually NOT
-- * for testing only, values automatically peeked otherwise

local contabovrd = {}
  -- contabovrd['sitelang'] = 'eo'                                    -- "en"
  -- contabovrd['sitelang'] = 'id'
  -- contabovrd['katprefi'] = 'Kategorio'                             -- "Category"
  -- contabovrd['katprefi'] = 'Kategori'
  -- contabovrd['parentfn'] = string.char(0xC5,0x9C) .. 'ablono:eht'  -- "Template:eht" (!!! no surr translation !!!)

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

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

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

  -- SPECIAL VAR:S

local qldingvoj = {}     -- type "table" but metaized with some subtables
local qldbetoj = {}      -- type "table" but metaized with some subtables
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="

---- GUARD AGAINST INTERNAL ERROR AND IMPORT ONE VIA LOADDATA ----  !!!FIXME!!! betoj

qbooguard = (type(constringvoj)~='string')
if (not qbooguard) then
  qldingvoj = mw.loadData(constringvoj) -- can crash here
  qbooguard = (type(qldingvoj)~='table') -- seems to be always false
end--if

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

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

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

-- Local function LFDTRACEMSG

-- Enhance upvalue "qstrtrace" with fixed text.

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

-- no size limit

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

-- uses upvalue "qboodetrc"

local function lfdtracemsg (strshortline)
  if (qboodetrc and (type(strshortline)=='string')) then
    qstrtrace = qstrtrace .. strshortline .. '.<br>' -- dot added !!!
  end--if
end--function lfdtracemsg

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

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

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

local function mathisintrange (numzjinput, numzjmin, numzjmax)
  local booisclean = false -- preASSume guilt
  if (type(numzjinput)=='number') then -- no non-numbers, thanks
    if (numzjinput==math.floor(numzjinput)) then -- no transcendental
      booisclean = ((numzjinput>=numzjmin) and (numzjinput<=numzjmax)) -- rang
    end--if
  end--if
  return booisclean
end--function mathisintrange

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

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

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

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

-- Local function LFNUMTO2DIGIT

-- Convert integer 0...99 to decimal ASCII string always 2 digits "00"..."99".

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

local function lfnumto2digit (numzerotoninetynine)
  local strtwodig = '??' -- always 2 digits
  if (mathisintrange(numzerotoninetynine,0,99)) then
    strtwodig = tostring(mathdiv(numzerotoninetynine,10)) .. tostring(mathmod(numzerotoninetynine,10))
  end--if
  return strtwodig
end--function lfnumto2digit

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

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

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

-- Local function LFGSTRINGRANGE

local function lfgstringrange (varvictim, nummini, nummaxi)
  local nummylengthofstr = 0
  local booveryvalid = false -- preASSume guilt
  if (type(varvictim)=='string') then
    nummylengthofstr = string.len(varvictim)
    booveryvalid = ((nummylengthofstr>=nummini) and (nummylengthofstr<=nummaxi))
  end--if
  return booveryvalid
end--function lfgstringrange

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

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

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

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

-- Local function LFGCMPBEG

-- Check whether a given substring can be found at begin of a longer
-- string (equality optionally valid).

-- Input  : * strbig, strtiny
--          * booalso6ekv -- allow equality

local function lfgcmpbeg (strbig, strtiny, booalso6ekv)
  local numlen6big = 0
  local numlen6tiny = 0
  local boof6ound = false
  numlen6big = string.len (strbig)
  numlen6tiny = string.len (strtiny)
  if (numlen6tiny>0) then
    if ((numlen6tiny<numlen6big) or (booalso6ekv and (numlen6tiny==numlen6big))) then
      boof6ound = ( strtiny == (string.sub (strbig,1,numlen6tiny)) )
    end--if
  end--if
  return boof6ound
end--function lfgcmpbeg

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

-- Local function LFGCMPEND

-- Check whether a given substring can be found at end of a longer
-- string (equality optionally valid).

-- Input  : * strbig, strtiny
--          * booalso7ekv -- allow equality

local function lfgcmpend (strbig, strtiny, booalso7ekv)
  local numlen7big = 0
  local numlen7tiny = 0
  local boof7ound = false
  numlen7big = string.len (strbig)
  numlen7tiny = string.len (strtiny)
  if (numlen7tiny>0) then
    if ((numlen7tiny<numlen7big) or (booalso7ekv and (numlen7tiny==numlen7big))) then
      boof7ound = ( strtiny == (string.sub (strbig,(numlen7big-numlen7tiny+1),numlen7big)) )
    end--if
  end--if
  return boof7ound
end--function lfgcmpend

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

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

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

-- Local function LFIKATALDIGU  !!!FIXME!!! use LFIKATPALDIGU

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 LFISEPBRACKET

-- Separate bracketed part of a string and return the inner and outer
-- part, the outer one with the brackets. There must be exactly ONE "("
-- and exactly ONE ")" in correct order.

-- Input  : * strsep33br
--          * numxmin33len -- minimal length of inner part, must be >= 1

-- Output : * boosaxes, strinner, strouter

-- Note that for length of hit ZERO ie "()" we would have "begg" + 1 = "endd"
-- and for length of hit ONE ie "(x)" we have "begg" + 2 = "endd".

-- Example: "crap (NO)" -> len = 9
--           123456789
-- "begg" = 6 and "endd" = 9
-- Expected result: "NO" and "crap ()"

-- Example: "(XX) YES" -> len = 8
--           12345678
-- "begg" = 1 and "endd" = 4
-- Expected result: "XX" and "() YES"

local function lfisepbracket (strsep33br, numxmin33len)

  local strinner = ''
  local strouter = ''
  local num33idx = 1 -- ONE-based
  local numdlong = 0
  local num33wesel = 0
  local numbegg = 0 -- ONE-based, ZERO invalid
  local numendd = 0 -- ONE-based, ZERO invalid
  local boosaxes = false -- preASSume guilt

  numdlong = string.len (strsep33br)
  while true do
    if (num33idx>numdlong) then
      break -- ONE-based -- if both "numbegg" "numendd" non-ZERO then maybe
    end--if
    num33wesel = string.byte(strsep33br,num33idx,num33idx)
    if (num33wesel==40) then -- "("
      if (numbegg==0) then
        numbegg = num33idx -- pos of "("
      else
        numbegg = 0
        break -- damn: more than 1 "(" present
      end--if
    end--if
    if (num33wesel==41) then -- ")"
      if ((numendd==0) and (numbegg~=0) and ((numbegg+numxmin33len)<num33idx)) then
        numendd = num33idx -- pos of ")"
      else
        numendd = 0
        break -- damn: more than 1 ")" present or ")" precedes "("
      end--if
    end--if
    num33idx = num33idx + 1
  end--while

  if ((numbegg~=0) and (numendd~=0)) then
    boosaxes = true
    strouter = string.sub(strsep33br,1,numbegg) .. string.sub(strsep33br,numendd,-1)
    strinner = string.sub(strsep33br,(numbegg+1),(numendd-1))
  end--if

  return boosaxes, strinner, strouter

end--function lfisepbracket

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

-- Local function LFIVALIDATELNKOADV

-- Advanced test whether a string (intended to be a langcode) 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] lfgtestnum lfgtestlc

-- 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 -- inner genuine 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 = lfgtestnum(numchiiar)
      booislclc = lfgtestlc(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 -- inner genuine loop over char:s

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

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

  return booisvaladv

end--function lfivalidatelnkoadv

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

-- Local function LFIFILLINX

-- Replace placeholders "\@" "\\@" or "\~" "\\~" by given substitute string.

-- Input  : * strbeforfill -- request string with placeholders to be filled
--                            in, no placeholders or empty input is useless
--                            but cannot cause major harm
--          * numaskikodo  -- ASCII code of placeholder, 64 for "@" or
--                            126 for "~"
--          * varsupstitu  -- substitute, either string (same content reused
--                            if multiple placeholders), or ZERO-based table
--                            (with one element per placeholder such as
--                            {[0]="none","neniu"}), length 1...60

-- Output : * strafterfill

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

local function lfifillinx (strbeforfill, numaskikodo, varsupstitu)

  local varpfiller    = 0  -- risky picking
  local strufiller    = '' -- final validated filler
  local strafterfill  = ''
  local numlenbigtext = 0  -- len of strbeforfill
  local numsfrcindex  = 0  -- char index ZERO-based
  local numinsrtinde  = 0  -- index in table ZERO-based
  local numtecken0d   = 0
  local numtecken1d   = 0

  numlenbigtext = string.len (strbeforfill)

  while true do
    if (numsfrcindex>=numlenbigtext) then
      break -- empty input is useless but cannot cause major harm
    end--if
    numtecken0d = string.byte(strbeforfill,(numsfrcindex+1),(numsfrcindex+1))
    numsfrcindex = numsfrcindex + 1 -- INC here
    numtecken1d = 0 -- preASSume none
    if (numsfrcindex<numlenbigtext) then -- pick but do NOT INC
      numtecken1d = string.byte(strbeforfill,(numsfrcindex+1),(numsfrcindex+1))
    end--if
    if ((numtecken0d==92) and (numtecken1d==numaskikodo)) then -- "\@" "\~"
      numsfrcindex = numsfrcindex + 1 -- INC more, now totally + 2
      varpfiller = 0 -- preASSume nothing available
      strufiller = '??' -- preASSume nothing available
      if (type(varsupstitu)=='string') then
        varpfiller = varsupstitu -- take it as-is (length check below)
      end--if
      if (type(varsupstitu)=='table') then
        varpfiller = varsupstitu [numinsrtinde] -- risk of type "nil"
        numinsrtinde = numinsrtinde + 1 -- INC tab index on every placeholder
      end--if
      if (lfgstringrange(varpfiller,1,60)) then -- !!!FIXME!!! nowiki and other sanitization
        strufiller = varpfiller -- now the substitute is finally accepted
      end--if
    else
      strufiller = string.char (numtecken0d) -- no placeholder -> copy octet
    end--if
    strafterfill = strafterfill .. strufiller -- add one of 4 possible cases
  end--while

  return strafterfill

end--function lfifillinx

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

-- Local function LFIKODEOSG

-- Transcode eo X-surrogates to cxapeloj in a single string (eo only).

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

-- Output : * strutf8eo -- UTF8 string

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

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

-- To be called ONLY from "lfhfillsurrstrtab".

-- * the "x" in a surr pair is case insensitive,
--   for example both "kacxo" and "kacXo" give same result
-- * avoid "\", thus for example "ka\cxo" would get converted but the "\" kept
-- * double "x" (both case insensitive) prevents conversion and becomes
--   reduced to single "x", for example "kacxxo" becomes "kacxo"

local function lfikodeosg (streosurr)

  local vareopeek = 0
  local strutf8eo = ''
  local numeoinplen = 0
  local numinpinx = 0 -- ZERO-based source index
  local numknar0k = 0 -- current char
  local numknaf1x = 0 -- next char (ZERO is NOT valid)
  local numknaf2x = 0 -- post next char (ZERO is NOT valid)
  local boonext1x = false
  local boonext2x = false
  local boosudahdone = false

  numeoinplen = string.len(streosurr)

  while true do

    if (numinpinx>=numeoinplen) then
      break
    end--if

    numknar0k = string.byte(streosurr,(numinpinx+1),(numinpinx+1))
    numknaf1x = 0 -- preASSume no char
    numknaf2x = 0 -- preASSume no char
    if ((numinpinx+1)<numeoinplen) then
      numknaf1x = string.byte(streosurr,(numinpinx+2),(numinpinx+2))
    end--if
    if ((numinpinx+2)<numeoinplen) then
      numknaf2x = string.byte(streosurr,(numinpinx+3),(numinpinx+3))
    end--if

    boonext1x = ((numknaf1x==88) or (numknaf1x==120)) -- case insensitive
    boonext2x = ((numknaf2x==88) or (numknaf2x==120)) -- case insensitive
    boosudahdone = false
    if (boonext1x and boonext2x) then -- got "xx"
      strutf8eo = strutf8eo .. string.char(numknar0k,numknaf1x) -- keep one "x" only
      numinpinx = numinpinx + 3 -- eaten 3 written 2
      boosudahdone = true
    end--if
    if (boonext1x and (not boonext2x)) then -- got yes-"x" and no-"x"
      vareopeek = contabtransluteo[numknar0k] -- UINT16 or type "nil"
      if (type(vareopeek)=='number') then
        strutf8eo = strutf8eo .. string.char(mathdiv(vareopeek,256),mathmod(vareopeek,256)) -- add UTF8 char
        numinpinx = numinpinx + 2 -- eaten 2 written 2
        boosudahdone = true
      end--if
    end--if
    if (not boosudahdone) then
      strutf8eo = strutf8eo .. string.char(numknar0k) -- copy char
      numinpinx = numinpinx + 1 -- eaten 1 written 1
    end--if

  end--while

  return strutf8eo

end--function lfikodeosg

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

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

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

-- Local function LFHVALI1STATUS99CODE

-- Depends on functions :
-- [E] mathisintrange

local function lfhvali1status99code (varvalue)
  local boovalid = false -- preASSume guilt
  while true do -- fake loop
    if (varvalue==0) then
      break -- success thus keep false since no valid error code ;-)
    end--if
    if (mathisintrange(varvalue,1,99)) then
      boovalid = true -- got an error and valid error code returned
    else
      varvalue = 255 -- failed to return valid status code
    end--if
    break -- finally to join mark
  end--while -- fake loop -- join mark
  return varvalue, boovalid
end--function lfhvali1status99code

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

-- Local function LFHCONSTRUCTERAR

-- Construct error message maybe peeking description.

-- Input  : * numerar3code -- 1 ... 99 or 2 ... 99 (resistant against invalid
--                            data type, giving "??" on such)
--          * boopeek3it -- do peek description #E02...#E99 from table

-- Depends on functions :
-- [N] lfnumto2digit
-- [E] mathisintrange mathdiv mathmod

-- Depends on constants :
-- * maybe table contaberaroj TWO-based (holes permitted)

-- To be called ONLY from lfhbrewerror, lfhbrewerrsm,
-- lfhbrewerrsvr, lfhbrewerrinsi.

local function lfhconstructerar (numerar3code, boopeek3it)
  local vardes3krip = 0
  local numbottom3limit = 1
  local stryt3sux = '#E'
  if (boopeek3it) then
    numbottom3limit = 2 -- #E01 is a valid code for submodule only
  end--if
  if (mathisintrange(numerar3code,numbottom3limit,99)) then
    stryt3sux = stryt3sux .. lfnumto2digit(numerar3code)
    if (boopeek3it) then
      vardes3krip = contaberaroj[numerar3code] -- risk of type "nil"
      if (type(vardes3krip)=='string') then
        stryt3sux = stryt3sux .. ' ' .. vardes3krip
      else
        stryt3sux = stryt3sux .. ' ??' -- no text found
      end--if
    end--if (boopeek3it) then
  else
    stryt3sux = stryt3sux .. '??' -- no valid error code
  end--if
  return stryt3sux

end--function lfhconstructerar

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

-- Local function LFHBREWERROR

-- Input  : * numerar6code -- TWO-based error code 2 ... 99 (resistant
--                            against invalid data type, giving "??" on such)

-- Output : * stryt6sux -- message

-- Depends on functions :
-- [H] lfhconstructerar
-- [N] lfnumto2digit
-- [E] mathisintrange mathdiv mathmod

-- Depends on constants :
-- * 3 strings constrelabg constrelaen constrlaxhu
-- * table contaberaroj TWO-based (holes permitted)

-- #E02...#E99, note that #E00 and #E01 are NOT supposed to be included here.

local function lfhbrewerror (numerar6code)
  local stryt6sux = ''
  stryt6sux = constrlaxhu .. constrelabg .. lfhconstructerar (numerar6code,true) .. constrelaen .. constrlaxhu
  return stryt6sux
end--function lfhbrewerror

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

-- Local function LFHFILLSURRSTRTAB

-- Process (fill in, transcode) either a single string, or all string
-- items in a table (even nested) using any type of keys/indexes (such
-- as a holey number sequence and non-numeric ones). Items with a
-- non-string value are kept as-is. Optional filling in own name,
-- and optional transcoding of eo and sv surrogates (via 3 separate
-- sub:s). Optionally even string keys/indexes are transcoded but
-- NOT filled in.

-- Input  : * varinkommen -- type "string" or "table"
--          * varfyllo -- string, or type "nil" if no filling-in desired
--          * strlingkod -- "eo" or "sv" to transcode surrogates,
--                          anything else (preferably type "nil") to skip this
--          * bookeys -- transcode keys too (preferably "true" or type "nil")

-- Depends on functions :
-- [I] lfifillinx (only if filling-in desired)
-- [I] lfikodeosg (only if conv of eo X-surrogates desired)
-- [I] lfikodsvsg (only if conv of sv blackslash-surrogates desired)
-- [G] lfgstringrange (via "lfifillinx")
-- [E] mathdiv mathmod (via "lfikodeosg" and "lfikodsvsg")

-- Depends on constants :
-- * table "contabtransluteo" inherently holey (via "lfikodeosg")
-- * table "contabtranslutsv" inherently holey (via "lfikodsvsg")

-- We always fully rebrew tables from scratch, thus do NOT replace
-- single elements (doing so would break "in pairs").

local function lfhfillsurrstrtab (varinkommen, varfyllo, strlingkod, bookeys)

  local varnky = 0 -- variable without type
  local varutmatning = 0
  local boodone = false

  if (type(varinkommen)=='string') then
    if (type(varfyllo)=='string') then
      varinkommen = lfifillinx (varinkommen,64,varfyllo) -- fill-in "\@"
    end--if
    if (strlingkod=='eo') then
      varinkommen = lfikodeosg (varinkommen) -- surr
    end--if
    if (strlingkod=='sv') then
      varinkommen = lfikodsvsg (varinkommen) -- surr
    end--if
    varutmatning = varinkommen -- copy, risk for no change
    boodone = true
  end--if

  if (type(varinkommen)=='table') then
    varutmatning = {} -- brew new table from scratch
    for k4k,v4v in pairs(varinkommen) do -- nothing done if table empty
      if ((bookeys==true) and (type(k4k)=='string')) then
        varnky = lfhfillsurrstrtab (k4k, false, strlingkod, nil) -- RECURSION
      else
        varnky = k4k
      end--if
      if ((type(v4v)=='string') or (type(v4v)=='table')) then
        v4v = lfhfillsurrstrtab (v4v, varfyllo, strlingkod, bookeys) -- RECURSION
      end--if
      varutmatning[varnky] = v4v -- write same or diff place in dest table
    end--for
    boodone = true
  end--if

  if (not boodone) then
    varutmatning = varinkommen -- copy as-is whatever it is, useless
  end--if

  return varutmatning

end--function lfhfillsurrstrtab

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

-- Local function LFHGETLANGFROMCAT

-- Input  : * strcatname -- without ns prefix

-- Output : * strlingvo
--          * numtristato -- ZERO nothing | ONE langcode (2...10) |
--                           TWO langname (>=3)

-- Depends on functions :
-- [I] lfisepbracket
-- [G] lfgcmpend
-- [E] mathisintrange

-- Depends on constants :
-- * contabfarado contabfullcat contabsuffcat

-- apply chain of rules:
-- * two fragments of catname found in contabfarado -> get langcode
--   >=2 sandwiched beween them
-- * full catname is found in contabfullcat -> get langcode from there (1)
-- * catname is suffixed by item found contabsuffcat -> get langcode
--   from there (1)
-- * there is bracketed part >= 3 char:s -> take it as langname (2)
-- * else return ZERO

local function lfhgetlangfromcat(strcatname)

  local vartpm = 0
  local str7tomp = ''
  local str7tump = ''
  local strlingvo = ''
  local num7lencleft = 0
  local num7posirajt = 0
  local num7sandwitch = 0
  local numtristato = 0 -- preASSume nothing found
  local boopmt = false

  while true do -- fake loop

    for k7k,v7v in pairs(contabfarado) do -- nothing done if table empty
      if ((type(k7k)~='string') or (type(v7v)~='string')) then
        break -- protect from terrorism
      end--if
      if (lfgcmpbeg(strcatname,k7k,false)) then -- equality NOT appreci
        num7lencleft = string.len(k7k)
        vartpm = string.find(strcatname,v7v,1,true)
        if (type(vartpm)=='number') then
          num7posirajt = vartpm
          num7sandwitch = num7posirajt - num7lencleft - 1
          if (mathisintrange(num7sandwitch,2,10)) then
            strlingvo = string.sub(strcatname,(num7lencleft+1),(num7posirajt-1))
            numtristato = 1
            break -- got langcode (validity NOT certified yet)
          end--if
        end--if
      end--if (lfgcmpbeg(strcatname,k7k,false)) then
    end--for
    if (numtristato==1) then
      break -- got langcode, exit fake loop too
    end--if

    vartpm = contabfullcat[strcatname] -- single query gives the verdict
    if (type(vartpm)=='string') then
      strlingvo = vartpm
      numtristato = 1
      break -- got langcode
    end--if

    for k7k,v7v in pairs(contabsuffcat) do -- nothing done if table empty
      if ((type(k7k)~='string') or (type(v7v)~='string')) then
        break -- protect from terrorism
      end--if
      if (lfgcmpend(strcatname,k7k,false)) then -- equality NOT appreci
        strlingvo = v7v
        numtristato = 1
        break -- got langcode
      end--if
    end--for
    if (numtristato==1) then
      break -- got langcode, exit fake loop too
    end--if

    boopmt, str7tomp, str7tump = lfisepbracket(strcatname,3) -- succ innr outr
    if (boopmt) then -- langname found (validity NOT certified yet)
      strlingvo = str7tomp
      numtristato = 2 -- got langname
    end--if

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

  return strlingvo, numtristato

end--function lfhgetlangfromcat

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

-- Local function LFHFALLBACK

-- Output : * str55rezult -- empty string if nothing found

-- Depends on constants :
-- * table contabfall

local function lfhfallback (str55incom)

  local var55target = 0
  local var55nonleft = 0
  local varone55line = 0
  local str55rezult = ''
  local num55outer = 1 -- ONE-based
  local num55inner = 0 -- ONE-based but starts from TWO

  while true do
    varone55line = contabfall [num55outer]
    if (type(varone55line)~='table') then
      break -- we have run out of outer table, nothing found, abort outer loop
    end--if
    var55target = varone55line[1]
    if (type(var55target)~='string') then
      break -- should be impossible, abort outer loop too
    end--if
    if (str55incom==var55target) then
      str55rezult = str55incom -- supported as-is, abort outer loop
      break
    end--if
    num55inner = 2
    while true do
      var55nonleft = varone55line[num55inner]
      if (type(var55nonleft)~='string') then
        break -- no fallback in this line, abort inner loop only
      end--if
      if (str55incom==var55nonleft) then
        str55rezult = var55target -- fallback success
        break -- abort inner loop only
      end--if
      num55inner = num55inner + 1
    end--while
    num55outer = num55outer + 1
  end--while

  return str55rezult

end--function lfhfallback

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

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

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

-- Local function LFWKATROL

-- Peek summary of a category.

-- Input  : * strcat8name          -- without prefix

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

-- Always expensive, the caller must use "pcall".

local function lfwkatrol (strcat8name)
  local metab = 0
  local numpages = -1 -- preASSume unknown
  local numsubcats = -1 -- preASSume unknown
  metab = mw.site.stats.pagesInCategory ( strcat8name, '*' ) -- expensive here
  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

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

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

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

function exporttable.ek (arxframent)

  -- general unknown type

  local vartymp = 0    -- variable without type multipurpose

  -- special type "args" AKA "arx"

  local arxsomons = 0  -- metaized "args" from our own or caller's "frame"

  -- general tab

  local tablg80lefty = {}

  -- peeked stuff

  local strpiklangcode = '' -- "en" privileged site language
  local strpikkatns    = '' -- "Category"
  local strpikparent   = '' -- "Template:attack" FULLPAGENAME
  local strpikpareuf   = '' -- "attack" PAGENAME unfull

  -- override

  local strtocoverride = '' -- from "tocforceoverridetestonly="

  -- general str

  local strpagenam = '' -- {{PAGENAME}} or "pagenameoverridetestonly="
  local strruangna = '' -- {{NAMESPACENUMBER}} or "nsnumberoverridetestonly="
  local strkodbah  = '' -- langcode

  local strtump    = '' -- temp

  local strvisgud  = ''  -- visible output on success
  local strviserr  = ''  -- visible error message on error
  local strtrakat  = ''  -- invisible tracking categories on error
  local strret     = ''  -- final result string

  -- general num

  local numerr       = 0   -- 0 OK | 1 inter | 2 sub fail | 3 sub statuscode
  local num2statcode = 0
  local numpages     = 0
  local numsubkatt   = 0

  -- general boo

  local boobigenough = false
  local bootimp      = false

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

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

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

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

  -- later reporting of #E01 must NOT depend on uncommentable stuff

  lfdtracemsg ('This is "Module:eht", requested "detrc" report')

  if (qbooguard) then
    numerr = 1 -- #E01 internal
  end--if

  ---- PEEK STUFF THAT IS NOT OVERRIDDEN GENEROUS ----

  -- this depends on "arxframent" (only if parent requested) but NOT on "arx"

  -- "strpikkatns" and "strpikindns" and "strpikapxns" do NOT
  -- include a trailing ":" colon, and are for "lfykattlaenk"
  -- and "lfyapxindlaenk" and "lfikatpaldigu"

  -- full "strpikparent" is used for error messages
  -- unfull "strpikpareuf" is used for tracking cat:s

  if (numerr==0) then
    strpiklangcode = contabovrd['sitelang'] or mw.getContentLanguage():getCode() or 'en'              -- privileged site language
    strpikkatns    = contabovrd['katprefi'] or (mw.site.namespaces[ 14] or {})['name'] or 'Category'  -- standard namespace
    strpikparent   = contabovrd['parentfn'] or arxframent:getParent():getTitle() or 'Template:eht'    -- fullpagename
    if ((type(strpiklangcode)~='string') or (type(strpikkatns)~='string') or (type(strpikparent)~='string')) then
      numerr = 1 -- #E01 internal (unlikely)
    end--if
    vartymp = string.find(strpikparent,':',1,true)
    if (mathisintrange(vartymp,2,(string.len(strpikparent)-1))) then
      strpikpareuf = string.sub(strpikparent,(vartymp+1),-1) -- make unfull
    else
      strpikpareuf = strpikparent -- dubi call from ns ZERO or misplaced ":"
    end--if
  end--if (numerr==0) then

  ---- GET THE ARX (ONE OF TWO) ----

  -- must be seized independently on "numerr" even if we
  -- already suck due to possible "detrc=true"

  -- give a f**k in possible params other than "caller=true"

  arxsomons = arxframent.args -- "args" from our own "frame"
  if (type(arxsomons)~='table') then
    arxsomons = {} -- guard against indexing error from our own
    numerr = 1 -- #E01 internal
  end--if
  if (arxsomons['caller']=='true') then
    arxsomons = arxframent:getParent().args -- "args" from caller's "frame"
  end--if
  if (type(arxsomons)~='table') then
    arxsomons = {} -- guard against indexing error again
    numerr = 1 -- #E01 internal
  end--if

  ---- PROCESS MESSAGES, FILL IN ALWAYS, SURR ONLY IF NEEDED ----

  -- only for some languages the surr-transcoding is subsequently performed

  if (numerr==0) then
    contabfullcat = lfhfillsurrstrtab (contabfullcat, nil, strpiklangcode, true)
    contabsuffcat = lfhfillsurrstrtab (contabsuffcat, nil, strpiklangcode, true)
    contaberaroj  = lfhfillsurrstrtab (contaberaroj, strpikparent, strpiklangcode, nil)
    contabtrack   = lfhfillsurrstrtab (contabtrack, nil, strpiklangcode, nil)
  end--if

  ---- PICK SUBTABLE T80 FROM ONE IMPORT ----

  -- here risk of #E02 #E03

  -- on error we assign "numerr" and maybe "num2statcode" both used far below

  while true do -- fake loop

    if (numerr~=0) then -- #E01 possible
      break -- to join mark
    end--if

    num2statcode, bootimp = lfhvali1status99code (qldingvoj[2])
    if (num2statcode~=0) then
      if (bootimp) then
        numerr = 3 -- #E03 nombrigita
      else
        numerr = 2 -- #E02 malica
      end--if
      break -- to join mark
    end--if

    vartymp = qldingvoj['T80'] -- from "loaddata-tbllingvoj"
    if (type(vartymp)~='table') then -- important check
      numerr = 2 -- #E02 malica
      break -- to join mark
    end--if
    tablg80lefty = vartymp -- leftmost column -> y-index (langname to langcode)

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

  ---- PROCESS 3 HIDDEN NAMED PARAMS INTO 3 STRING:S ----

  -- this may override "mw.title.getCurrentTitle().text" and
  -- stipulate content in "strpagenam", empty is NOT valid

  -- bad "pagenameoverridetestonly=" can give #E01
  -- no error is possible from other hidden parameters

  strpagenam = '' -- using vartymp here
  if (numerr==0) then -- get pagename (error if bad, silent if absent)
    vartymp = arxsomons['pagenameoverridetestonly']
    if (type(vartymp)=='string') then
      if (lfgstringrange(vartymp,1,200)) then -- empty or too long NOT legal
        strpagenam = vartymp
      else
        numerr = 1 -- #E01 internal
      end--if
    end--if
  end--if

  strruangna = '' -- using vartymp here
  if (numerr==0) then -- get namespace (silent if bad, silent if absent)
    vartymp = arxsomons['nsnumberoverridetestonly']
    if (lfgstringrange(vartymp,1,4)) then -- empty or too long NOT legal
      strruangna = vartymp
    end--if
  end--if

  if (numerr==0) then
    vartymp = arxsomons['tocforceoverridetestonly']
    if ((vartymp=='on') or (vartymp=='off')) then
      strtocoverride = vartymp
    end--if
  end--if

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

  ---- SEIZE PAGENAME AND NS FROM MW ----

  -- "pagenameoverridetestonly=" "nsnumberoverridetestonly=" processed above

  -- later reporting of #E01 must NOT depend on uncommentable
  -- or peekable stuff

  -- pagename must be 1...200 octet:s keep consistent
  -- with "pagenameoverridetestonly="

  if ((numerr==0) and (strpagenam=='')) then -- get pagename (error if bad)
    vartymp = mw.title.getCurrentTitle().text -- without namespace prefix
    if (lfgstringrange(vartymp,1,200)) then -- empty or too long NOT legal
      strpagenam = vartymp -- cannot be left empty
    else
      numerr = 1 -- #E01 internal
    end--if
  end--if

  if ((numerr==0) and (strruangna=='')) then -- get namespace (silent if bad)
    vartymp = mw.title.getCurrentTitle().namespace -- type is "number"
    if (mathisintrange(vartymp,0,9999)) then -- negative NOT legal but silent
      strruangna = tostring(vartymp) -- can be left empty, check below required
    end--if
  end--if

  ---- CHECK NS ----

  if ((numerr==0) and (strruangna~='14')) then -- must be "Category:"
    numerr = 10 -- #E10 called from wrong ns
  end--if

  lfdtracemsg ('Seized pagename and ns, numerr=' .. tostring(numerr))

  ---- WHINE IF YOU MUST #E01 ----

  -- reporting of this error #E01 must NOT depend on uncommentable
  -- stuff such as "strpikparent" and "contaberaroj"

  if (numerr==1) then
    strtump = '#E01 Internal error in "Module:eht".'
    strviserr = constrlaxhu .. constrelabg .. strtump .. constrelaen .. constrlaxhu
  end--if

  ---- CHECK WHETHER SPECIAL OR LANGNAME AVAILABLE OR TRANSLINGUAL CAT ----

  -- strkodbah is empty string so far, assign it based on a chain of rules:
  -- * two fragments of catname found in contabfarado -> get langcode
  --   sandwiched beween them, BEWARE needs strict validation
  -- * full catname is found in contabfullcat -> get langcode from there
  -- * catname is suffixed by item found contabsuffcat -> get langcode
  --   from there (for example "Kategorio:Biologio laux lingvo" look at
  --   last 12 char:s and from them get "eo" via that table)
  -- * there is bracketed part >= 3 char:s -> take it as langname and
  --   do reverse query
  -- * else translingual cat -> langcode is "mul"

  -- here call [H] lfhgetlangfromcat and maybe peek tablg80lefty

  -- numerr, strpagenam -> numerr, strkodbah

  if (numerr==0) then
    do -- scope
      local varmpt = 0
      local strmylang = ''
      local numwhat = 0 -- ZERO nothing | ONE langcode | TWO langname
      strmylang, numwhat = lfhgetlangfromcat(strpagenam)
      if (numwhat==0) then
        strkodbah = 'mul' -- nothing found -> assume translingual cat
      end--if
      if (numwhat==1) then -- must validate  !!!FIXME!!! forward query needed too
        if (lfivalidatelnkoadv(strmylang,false,false,conbookodlng,conboomiddig,false)) then
          strkodbah = strmylang
        else
          numerr = 11 -- #E11 obviously invalid langcode
        end--if
      end--if
      if (numwhat==2) then -- get langcode by reverse query
        varmpt = tablg80lefty[strmylang] -- reverse query
        if (type(varmpt)=='string') then
          strkodbah = varmpt -- got ordinary langcode from (...)
        else
          numerr = 15 -- #E15 invalid or unknown langname
        end--if
      end--if (numwhat==2) then
    end--do scope
  end--if (numerr==0) then

  lfdtracemsg ('After "lfhgetlangfromcat" strkodbah="' .. strkodbah .. '", numerr=' .. tostring(numerr))

  ---- CHECK WHETHER IT IS BIG ENOUGH ----

  -- if it's too big to fail then it's too big but here we
  -- require at least 300 pages or at least 300 subcategories

  if (numerr==0) then
    boobigenough = (strtocoverride=='on')
    if ((not boobigenough) and (strtocoverride~='off')) then
      numpages, numsubkatt = lfwkatrol(strpagenam) -- without namespace prefix
      boobigenough = ((numpages>=300) or (numsubkatt>=300))
    end--if
  end--if

  lfdtracemsg ('Size check, boobigenough=' .. tostring(boobigenough))

  ---- PERFORM POSSIBLE FALLBACK ----

-- everything not listed fallbacks here to "en", this is good for "io"
-- and "id" and possibly a few more, but desperate for many others

  if ((numerr==0) and boobigenough) then
    strkodbah = lfhfallback(strkodbah) -- risk of empty "" or special "etio"
    if (strkodbah=='') then
      strkodbah = 'en'
    end--if
  end--if

  ---- FIRE THE TEMPLATE ----  !!!FIXME!!!

  if ((numerr==0) and boobigenough) then
    do -- scope
      local strforwardajxo = ''
      local boo3crap = false

      strforwardajxo = 'pagenameoverridetestonly=' .. strpagenam .. '|fullpanaoverridetestonly=' .. strpikkatns .. ':' .. strpagenam .. '|nsnumberoverridetestonly=14'
      if (strkodbah=='etio') then
        strvisgud = arxframent:preprocess ('{{KategorioEHT-etiopia-skribo|'..strforwardajxo..'}}')
      else
        strvisgud = arxframent:preprocess ('{{eht-kat-alfa|ling='..strkodbah..'|'..strforwardajxo..'}}')
      end--if
      if (string.len(strvisgud)<50) then
        boo3crap = true
      else
        boo3crap = (string.byte(strvisgud,1,1)==91) or (string.sub(strvisgud,1,5)=='&#91;')
      end--if
      if (boo3crap) then
        numerr = 16 -- #E16 template failed
      end--if

    end--do scope
  end--if

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

  ---- WHINE IF YOU MUST ON #E02...#E99 ----

  -- reporting of errors #E02...#E99 depends on uncommentable stuff
  -- and name of the caller filled in from "strpikparent"

  if (numerr>=2) then
    strviserr = lfhbrewerror(numerr)
  end--if

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

  ---- TRACKING CAT:S ON #E10 #E11 #E15 #E16 ----

  -- here we use "strpikpareuf" ie the UNFULL name of the parent

  while true do -- fake loop
    if (numerr<10) then -- #E10
      break
    end--if
    if (numerr==11) then -- #E11
      strtrakat = lfikataldigu(strpikkatns,contabtrack['E11'])
      break
    end--if
    if (numerr==15) then -- #E15
      strtrakat = lfikataldigu(strpikkatns,contabtrack['E15'])
      break
    end--if
    strtrakat =              lfikataldigu(strpikkatns,contabtrack['cetere'])
    strtrakat = strtrakat .. lfikataldigu(strpikkatns,contabtrack['cetere'] .. ' (' .. strpikpareuf .. ')')
    strtrakat = strtrakat .. lfikataldigu(strpikkatns,contabtrack['cetere'] .. ' (' .. strpikpareuf .. ', E' .. lfnumto2digit(numerr) .. ')')
    break -- finally
  end--while -- fake loop -- join mark

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

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

  -- on #E02 and higher we risk partial results in "strvisgud"

  if (numerr==0) then
    strret = strvisgud
  else
    strret = strviserr .. strtrakat
  end--if
  if (qboodetrc) then -- "qstrtrace" declared separately outside main function
    strret = '<br>' .. qstrtrace .. '<br><br>' .. strret
  end--if
  return strret

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

end--function

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

return exporttable