Modulo:mchar

El Vikivortaro
Salti al navigilo Salti al serĉilo

Dokumentado por ĉi tiu modulo povas esti kreata ĉe Modulo:mchar/dokumentado

--[===[

MODULE "MCHAR" (unicode character)

"eo.wiktionary.org/wiki/Modulo:mchar" <!--2021-Apr-12-->
"id.wiktionary.org/wiki/Modul:mchar"

Purpose: brews a box located on the right about
         a unicode char read from pagename

Utilo: kreas skatolon lokigitan dekstre pri
       unikoda signo legata el pagxonomo

Manfaat: membutat kotak terletak di sebelah kanan halaman tentang
         karakter unikode dibaca dari nama halaman

Syfte: skapar en ruta belaegen till hoeger ...

Used by templates / Uzata far sxablonoj / Digunakan oleh templat:
- signo (EO)

Required submodules / Bezonataj submoduloj / Submodul yang diperlukan:
- none

This module can accept parameters whether sent to itself (own frame) or
to the caller (caller's frame). If there is a parameter "caller=true"
on the own frame then that own frame is discarded in favor of the
caller's one.

Incoming: - no anonymous parameters
          - 3 optional named parameters
            - "des=" -- official name written with uppercase letters (4...80)
            - "en=" -- (4...80)
            - "sl=" -- description in site language (4...80)
          - 1 hidden named parameter
            - "pagenameoverridetestonly="

Returned: - one string with a HTML table or inline ERROR

]===]

local char = {}

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

---- CONSTANTS ----

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

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

  local constrpriv = "eo"                 -- EO (privileged site language)
  -- local constrpriv = "id"                 -- ID (privileged site language)

  -- constant table (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 (error circumfixes)

  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 " [] "

  -- uncommentable EO vs ID string (caller name for error messages)

  local constrkoll = 'sxablono "signo"'    -- EO augmented name of the caller (semi-hardcoded, we do NOT peek it)
  -- local constrkoll = 'templat "karakter"'  -- ID augmented name of the caller (semi-hardcoded, we do NOT peek it)

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

  -- #E02...#E99, holes permitted (max 3 consecutive)
  -- note that #E00 and #E01 are NOT supposed to be included here
  -- separate "constrkoll" needed for "\\@"

  local contaberaroj = {}
  contaberaroj[2] = 'Erara uzo de \\@, legu gxian dokumentajxon'                                       -- EO #E02
  -- contaberaroj[2] = 'Penggunaan salah \\@, bacalah dokumentasinya'                                     -- ID #E02
  contaberaroj[3] = 'Erara uzo de \\@ pro pagxonomo, estu unu signo'                                   -- EO #E03
  -- contaberaroj[3] = 'Penggunaan salah \\@ oleh karena nama halaman, sebaiknya satu karakter"'          -- ID #E03
  contaberaroj[4] = 'Erara uzo de \\@ pro "des=" priskriba parametro, estu majuskla'                   -- EO #E04
  -- contaberaroj[4] = 'Penggunaan salah \\@ oleh karena "des=" parameter deskripsi, sebaiknya kapital'   -- ID #E04

  -- constant table (HTML)

  local contabhtml = {}
  contabhtml[0] = '<table style="float:right; margin:0 0 0.3em 0.3em; background-color:#DDEEFF; border:2px solid #AAAAFF; padding:0.1em;">'
  contabhtml[1] = '<tr><td style="padding:0.2em; text-align:center; font-size:600%; line-height:65%;">'
  contabhtml[2] = '<tr><td style="padding:0.1em; text-align:center; line-height:1em;">'
  contabhtml[3] = '</td></tr>'
  contabhtml[4] = '<tr><td>&nbsp;</td></tr>' -- empty table row
  contabhtml[5] = '</table>'

  -- uncommentable EO vs ID constant table (unconditional boasting and ranges)

  -- ranges start at index 10 step 10
  -- +0 is name of the range
  -- +1 is starting codepoint
  -- +2 is last codepoint

  local contabboasting = {}

  contabboasting [ 0] = "signo"      -- EO
  -- contabboasting [ 0] = "karakter"   -- ID
  contabboasting [ 1] = "unikoda"    -- EO
  -- contabboasting [ 1] = "unikode"    -- ID

  contabboasting [10] = "videbla askia"      -- EO
  -- contabboasting [10] = "ASCII terlihat"     -- ID
  contabboasting [11] = 33
  contabboasting [12] = 126

  contabboasting [20] = "greka aux kopta"
  -- contabboasting [20] = "Yunani atau Koptik"
  contabboasting [21] = 880
  contabboasting [22] = 1023

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

---- SPECIAL STUFF OUTSIDE MAIN FUNCTION ----

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

---- VAR:S ----

local qbooguard = false  -- only for the guard test, pass to other var ASAP

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

if ((type(constrpriv)~="string") or (type(constrkoll)~="string")) then
  qbooguard = true
end--if

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

---- ORDINARY LOCAL MATH FUNCTIONS ----

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

-- Local function MATHDIV

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

-- Local function MATHMOD

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 MATHXOR

-- This sub depends on "MATH FUNCTIONS"\"mathdiv"
-- and "MATH FUNCTIONS"\"mathmod".

local function mathxor (xa, xb)
  local resultxor = 0
  local crap6 = 0
  local crap7 = 0
  local crap8 = 1 -- single bit value 1 -> 2 -> 4 -> 8 ...
  while (true) do
    if ((xa==0) and (xb==0)) then
      break
    end--if
    crap6 = mathmod (xa,2) -- seize remainder before dividing
    crap7 = mathmod (xb,2) -- seize remainder before dividing
    xa    = mathdiv (xa,2)
    xb    = mathdiv (xb,2)
    if (crap6~=crap7) then
      resultxor = resultxor + crap8
    end--if
    crap8 = crap8 * 2
  end--while
  return resultxor
end--function mathxor

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

---- ORDINARY LOCAL CONVERSION FUNCTIONS ----

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

-- Local function LFUINT8TOHEX

-- Convert UINT8 (0...255) to a 2-digit hex string.

-- This sub depends on "MATH FUNCTIONS"\"mathdiv"
-- and "MATH FUNCTIONS"\"mathmod".

local function lfuint8tohex (numinclow)
  local strheksulo = ''
  local numhajhaj = 0
  numhajhaj = mathdiv (numinclow,16)
  numinclow = mathmod (numinclow,16)
  if (numhajhaj>9) then
    numhajhaj = numhajhaj + 7 -- now 0...9 or 17...22
  end--if
  if (numinclow>9) then
    numinclow = numinclow + 7 -- now 0...9 or 17...22
  end--if
  strheksulo = string.char (numhajhaj+48) .. string.char (numinclow+48)
  return strheksulo
end--function lfuint8tohex

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

-- Local function LFUINT32TOHEX

-- Convert UINT32 (0 ... $FFFF'FFFF = #4'294'967'295) to
-- a (2 or 4 or 6 or 8)-digit hex string.

-- This sub depends on "MATH FUNCTIONS"\"mathdiv" and
-- "MATH FUNCTIONS"\"mathmod" and "CONVERSION FUNCTIONS"\"lfuint8tohex".

local function lfuint32tohex (numincom)
  local strheksulego = ''
  while (true) do
    strheksulego = lfuint8tohex ( mathmod (numincom,256) ) .. strheksulego
    numincom = mathdiv (numincom,256)
    if (numincom==0) then
      break
    end--if
  end--while
  return strheksulego
end--function lfuint32tohex

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

-- Local function LFNUMTODECBUN

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

-- This sub depends on "MATH FUNCTIONS"\"mathdiv"
-- and "MATH FUNCTIONS"\"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

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

-- This sub depends on "MATH FUNCTIONS"\"mathdiv"
-- and "MATH FUNCTIONS"\"mathmod".

local function lfnumto2digit (numzerotoninetynine)
  local strtwodig = ''
  strtwodig = mathdiv(numzerotoninetynine,10) .. mathmod(numzerotoninetynine,10)
  return strtwodig
end--function lfnumto2digit

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

---- ORDINARY LOCAL STRING FUNCTIONS ----

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

-- test whether char is an ASCII digit "0"..."9", return boolean

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

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

-- test whether char is an ASCII uppercase letter, return boolean

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

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

---- ORDINARY LOCAL UTF8 FUNCTIONS ----

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

-- Local function LFUTF8DEKO

-- Decode a UTF8 char, return ZERO length if invalid.

-- Result is a table: [0] length and [1] codepoint

-- This sub depends on "MATH FUNCTIONS"\"mathxor".

local function lfutf8deko (num0, num1, num2, num3)

  local tabresult = {}
  local numlength = 0 -- preassume invalid
  local numkodepoin = 0 -- preassume invalid

  num1 = mathxor (num1,128) -- XOR 3 of 4
  num2 = mathxor (num2,128) -- XOR 3 of 4
  num3 = mathxor (num3,128) -- XOR 3 of 4

  while (true) do -- fake loop

    if ((num0>193) and (num1>63)) then
      break -- to join mark
    end--if
    if ((num0>223) and (num2>63)) then
      break -- to join mark
    end--if
    if ((num0>239) and (num3>63)) then
      break -- to join mark
    end--if

    if (num0<128) then -- ZERO to $7F
      numkodepoin = num0
      numlength = 1
      break -- to join mark
    end--if

    if ((num0>193) and (num0<224)) then -- $C0 # $C2 to $DF
      numkodepoin = (mathxor(num0,192)) * 64 + num1
      if ((numkodepoin>127) and (numkodepoin<2048)) then
        numlength = 2
      end--if
      break -- to join mark
    end--if

    if ((num0>223) and (num0<240)) then -- $E0 to $EF
      numkodepoin = (mathxor(num0,224)) * 4096 + num1 * 64 + num2
      if (((numkodepoin>2047) and (numkodepoin<55296)) or ((numkodepoin>57343) and (numkodepoin<65536))) then
        numlength = 3
      end--if
      break -- to join mark
    end--if

    if ((num0>239) and (num0<245)) then -- $F0 to $F7 # $F4
      numkodepoin = (mathxor(num0,240)) * 262144 + num1 * 4096 + num2 * 64 + num3
      if ((numkodepoin>65535) and (numkodepoin<1114112)) then
        numlength = 4
      end--if
      break -- to join mark
    end--if

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

  tabresult [0] = numlength
  tabresult [1] = numkodepoin
  return tabresult

end--function lfutf8deko

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

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

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

-- Local function LFBREWERROR

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

-- We need 3 const strings "constrelabg", "constrelaen",
-- "constrlaxhu" and const table "contaberaroj".

-- This sub depends on "CONVERSION FUNCTIONS"\"lfnumto2digit".

local function lfbrewerror (numerrorcode)
  local vardeskrip = 0
  local strytsux = '#E'
  vardeskrip = contaberaroj[numerrorcode] -- risk of type "nil"
  if (type(vardeskrip)=="string") then
    strytsux = strytsux .. lfnumto2digit(numerrorcode) .. ' ' .. vardeskrip
  else
    strytsux = strytsux .. '??'
  end--if
  strytsux = constrlaxhu .. constrelabg .. strytsux .. constrelaen .. constrlaxhu
  return strytsux
end--function lfbrewerror

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

-- Local function LFFILLNAME

-- Replace placeholder "\@" "\\@" by augmented name of the caller.

-- The caller name is submitted to us as a parameter thus we
-- do NOT access any constants and do NOT have to peek it either.

local function lffillname (strmessage,strcaller)

  local strhasill = ''
  local numstrloen = 0
  local numindfx = 1 -- ONE-based
  local numcjar = 0
  local numcjnext = 0

  numstrloen = string.len (strmessage)

  while (true) do
    if (numindfx>numstrloen) then
      break -- empty input is useless but cannot cause major harm
    end--if
    numcjar = string.byte (strmessage,numindfx,numindfx)
    numindfx = numindfx + 1
    numcjnext = 0
    if (numindfx<=numstrloen) then
      numcjnext = string.byte (strmessage,numindfx,numindfx)
    end--if
    if ((numcjar==92) and (numcjnext==64)) then
      strhasill = strhasill .. strcaller -- invalid input is caller's risk
      numindfx = numindfx + 1 -- skip 2 octet:s of the placeholder
    else
      strhasill = strhasill .. string.char (numcjar)
    end--if
  end--while

  return strhasill

end--function lffillname

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

-- Local function LFKODEOSG

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

-- Input  : * strsurr -- string (empty is useless but can't cause major harm)

-- Output : * strcxapeloj

-- We need const table "contabtransiltable".

-- This sub depends on "MATH FUNCTIONS"\"mathdiv"
-- and "MATH FUNCTIONS"\"mathmod".

local function lfkodeosg (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 -- pre-assume no translation
    if ((numknarp~=0) and ((numknark==88) or (numknark==120))) then -- got "x"
      varpeek = contabtransiltable[numknarp] -- UINT16 or nil
      if (varpeek~=nil) then
        numlow = mathmod (varpeek,256)
        numhaj = mathdiv (varpeek,256)
      end--if
    end--if
    if (numhaj~=0) then
      strcxapeloj = strcxapeloj .. string.char(numhaj,numlow)
      numknark = 0 -- invalidade current char
    else
      if (numknarp~=0) then -- add previous char only if valid
        strcxapeloj = strcxapeloj .. string.char(numknarp) -- add it
      end--if
    end--if
    numknarp = numknark -- copy to previous even if invalid
  end--while
  if (numknarp~=0) then -- add previous and last char only if valid
    strcxapeloj = strcxapeloj .. string.char(numknarp) -- add it
  end--if
  return strcxapeloj
end--function lfkodeosg

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

---- MAIN EXPORTED FUNCTION ----

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

function char.ek (arxframent)

  -- general unknown type

  local vartmp = 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 tabutf8dec = {}

  -- general str

  local strpagenam  = '' -- from "{{PAGENAME}}" or "pagenameoverridetestonly"
  local strdesdes   = '' -- "des="
  local strenen     = '' -- "en="
  local strslsl     = '' -- "sl="

  local strtmp      = '' -- temp
  local strextra    = '' -- 1 or 2 extra lines with TR&TD-stuff
  local strviserr   = '' -- visible error
  local strvisgud   = '' -- visible good output
  local strret      = '' -- final result string

  -- general num

  local numerr    = 0  -- 1 inter 2 param 3 pagename 4 des
  local numutflen = 0  -- decoded length (ZERO invalid)
  local numdecode = 0  -- decoded "codepoint" value
  local numlong   = 0  -- length of pagename
  local numoct    = 0  -- temp some char
  local numodt    = 0  -- temp some char
  local numoet    = 0  -- temp some char
  local numoft    = 0  -- temp some char
  local numtamp   = 0
  local numtump   = 0

  -- general boo

  local boohavdes  = false
  local boohaven   = false
  local boohavsl   = false

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

  -- later reporting of #E01 may NOT depend on uncommentable strings

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

  ---- FILL IN ERROR MESSAGES AND TRANSCODE EO IF NEEDED ----

  -- placeholder "\@" "\\@" is replaced by augmented name of the caller
  -- from "constrkoll" in any case, for example 'sxablono "test"'
  -- or 'templat "test"'

  -- only for EO the X-substitution is subsequently performed

  if (numerr==0) then

    numtamp = 2 -- start with #E02
    numtump = 0 -- tolerance for holes
    while (true) do
      vartmp = contaberaroj[numtamp] -- risk of type "nil"
      if (type(vartmp)=="string") then -- number of messages is NOT hardcoded
        numtump = 0
        strtmp = lffillname (vartmp,constrkoll)
        if (constrpriv=="eo") then
          strtmp = lfkodeosg (strtmp)
        end--if
        contaberaroj[numtamp] = strtmp
      else
        numtump = numtump + 1
      end--if
      if (numtump==4) then -- max 3 consecutive holes
        break
      end--if
      numtamp = numtamp + 1 -- TWO-based
    end--while

    contabboasting[20] = lfkodeosg (contabboasting[20])

  end--if

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

  -- must be seized independently on "numerr" even if we already suck

  -- give a f**k in possible anon params for now (would cause #E02)

  arxsomons = arxframent.args -- "args" from our own "frame"
  if (type(arxsomons)~="table") then
    arxsomons = {} -- guard against indexing error
    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 1 HIDDEN NAMED PARAM PAGENAME ----

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

  -- bad "pagenameoverridetestonly=" can give #E01

  -- give a f**k in possible anon params for now (would cause #E02)

  strpagenam = ""
  if (numerr==0) then
    vartmp = arxsomons['pagenameoverridetestonly']
    if (type(vartmp)=="string") then
      numtamp = string.len(vartmp)
      if ((numtamp>=1) and (numtamp<=120)) then
        strpagenam = vartmp -- empty is not legal
      else
        numerr = 1 -- #E01 internal
      end--if
    end--if
  end--if

  ---- SEIZE THE PAGENAME FROM MW AFTER OVERRIDE AND PROHIBIT EMPTY ----

  -- later reporting of #E01 may NOT depend on uncommentable strings

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

  if ((numerr==0) and (strpagenam=='')) then
    vartmp = mw.title.getCurrentTitle().text -- without namespace prefix
    if (type(vartmp)=="string") then -- this can leave bhnd "strpagenam" empty
      numtamp = string.len(vartmp)
      if ((numtamp>=1) and (numtamp<=120)) then
        strpagenam = vartmp -- pagename here (empty is NOT legal)
      else
        numerr = 1 -- #E01 internal
      end--if
    end--if
  end--if

  if (strpagenam=='') then
    numerr = 1 -- #E01 internal -- no other error is possible so far
  end--if

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

  -- reporting of this error #E01 may NOT depend on
  -- uncommentable strings such as "constrkoll" and "contaberaroj"

  -- do NOT use sub "lfbrewerror", report our name (NOT of template) and in EN

  if (numerr==1) then
    strtmp = '#E01 Internal error in module "mchar".'
    strviserr = constrlaxhu .. constrelabg .. strtmp .. constrelaen .. constrlaxhu
  end--if

  ---- PROHIBIT ANON ----

  if ((numerr==0) and (arxsomons[1])) then
    numerr = 2 -- #E02 param
  end--if

  ---- PROCESS 3 OPTIONAL NAMED PARAMS ----

  -- "des=" (restrictive: only uppercase !!! bad -> #E04)
  -- "en=" "sl=" (bad -> #E02)

  if (numerr==0) then
    while (true) do -- fake loop -- abort on both success or failure -- "des="
      vartmp = arxsomons['des'] -- "des="
      if (type(vartmp)~="string") then
        break -- parameter not supplied
      end--if
      numtamp = string.len(vartmp)
      if ((numtamp<4) or (numtamp>80)) then
        numerr = 4 -- #E04
        break
      end--if
      boohavdes = true
      strdesdes = vartmp
      numlong = string.len (strdesdes) -- 4...80
      numtamp = 1 -- ONE-based
      while (true) do -- inner genuine loop
        if (numtamp>numlong) then
          break -- inner -- OK
        end--if
        numoct = string.byte (strdesdes,numtamp,numtamp)
        if ((lftestnum(numoct)==false) and (lftestuc(numoct)==false) and (numoct~=32) and (numoct~=45)) then
          numerr = 4 -- #E04 "des=" bad (must be number or uc or "-")
          break -- inner
        end--if
        numtamp = numtamp + 1
      end--while
      break -- finally
    end--while
  end--if

  if (numerr==0) then
    while (true) do -- fake loop -- abort on both success or failure -- "en="
      vartmp = arxsomons['en']
      if (type(vartmp)~="string") then
        break -- parameter not supplied
      end--if
      numtamp = string.len(vartmp)
      if ((numtamp<4) or (numtamp>80)) then
        numerr = 2 -- #E02
        break
      end--if
      boohaven = true
      strenen = vartmp
      break -- finally
    end--while
  end--if

  if (numerr==0) then
    while (true) do -- fake loop -- abort on both success or failure -- "sl="
      vartmp = arxsomons['sl']
      if (type(vartmp)~="string") then
        break -- parameter not supplied
      end--if
      numtamp = string.len(vartmp)
      if ((numtamp<4) or (numtamp>80)) then
        numerr = 2 -- #E02
        break
      end--if
      boohavsl = true
      strslsl = vartmp
      break -- finally
    end--while
  end--if

  ---- DECODE THE PAGENAME AND CHECK VALIDITY ----

  -- it is in "strpagenam" and nonempty

  -- decoding if longer than 4 octet:s is actually unneeded

  if (numerr==0) then
    numlong = string.len (strpagenam) -- 1...120 legal so far but see below
    numoct = string.byte (strpagenam,1,1)
    numodt = 0
    numoet = 0
    numoft = 0
    if (numlong>=2) then
      numodt = string.byte (strpagenam,2,2)
    end--if
    if (numlong>=3) then
      numoet = string.byte (strpagenam,3,3)
    end--if
    if (numlong>=4) then
      numoft = string.byte (strpagenam,4,4)
    end--if
    tabutf8dec = lfutf8deko (numoct,numodt,numoet,numoft)
    numutflen = tabutf8dec [0]
    numdecode = tabutf8dec [1]
    if (numutflen~=numlong) then
      numerr = 3 -- #E03 -- length must be one character only
    end--if
  end--if

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

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

  if (numerr>1) then
    strviserr = lfbrewerror(numerr)
  end--if

  ---- PREBREW 1 OR 2 EXTRA LINES ----

  -- incoming "numdecode"

  -- this depends on "constrpriv"

  -- this depends on "contabhtml" and "contabboasting"

  if (numerr==0) then
    if (constrpriv=="eo") then
      strtmp = contabboasting[1] .. ' ' .. contabboasting[0] -- "nigra lumo"
    else
      strtmp = contabboasting[0] .. ' ' .. contabboasting[1] -- "cahaya hitam"
    end--if
    strextra = contabhtml[2] .. strtmp .. contabhtml[3] -- unconditional line
    numtamp = 10 -- index step 10
    strtmp = '' -- preassume bugger all
    while (true) do
      vartmp = contabboasting[numtamp] -- risk of type "nil"
      if (type(vartmp)~="string") then -- number of ranges is NOT hardcoded
        break -- NOT found
      end--if
      if ((contabboasting[numtamp+1]<=numdecode) and (numdecode<=contabboasting[numtamp+2])) then
        strtmp = vartmp -- name of the range
        break -- found the range
      end--if
      numtamp = numtamp + 10 -- step 10 !!!
    end--while
    if (strtmp~='') then
      if (constrpriv=="eo") then
        strtmp = strtmp .. ' ' .. contabboasting[0] -- "griza lumo"
      else
        strtmp = contabboasting[0] .. ' ' .. strtmp -- "cahaya abu-abu"
      end--if
      strextra = strextra .. contabhtml[2] .. strtmp .. contabhtml[3]
    end--if
  end--if

  ---- BREW THE BOX ----

  -- incoming "strpagenam" and "numdecode" and "strextra"

  -- do NOT link "des" but do link "en" and "sl" (EO or ID)

  -- this depends on "contabhtml"

  if (numerr==0) then
    strvisgud = contabhtml[0] .. strextra -- begin table and 1 or 2 lines
    strvisgud = strvisgud .. contabhtml[1] .. strpagenam .. contabhtml[3] .. contabhtml[4]
    strvisgud = strvisgud .. contabhtml[2] .. "<small>kodopunkto</small> U+$" .. lfuint32tohex (numdecode) .. contabhtml[3]
    strvisgud = strvisgud .. contabhtml[2] .. "<small>dec</small> #" .. lfnumtodecbun (numdecode) .. contabhtml[3]
    if (boohavdes) then
      strvisgud = strvisgud .. contabhtml[2] .. strdesdes .. contabhtml[3]
    end--if
    if (boohaven) then
      strvisgud = strvisgud .. contabhtml[2] .. '[[' .. strenen .. ']]' .. contabhtml[3]
    end--if
    if (boohavsl) then
      strvisgud = strvisgud .. contabhtml[2] .. '[[' .. strslsl .. ']]' .. contabhtml[3]
    end--if
    strvisgud = strvisgud .. contabhtml[5] -- close table
  end--if

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

  strret = strviserr .. strvisgud
  return strret

end--function

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

return char