--[===[
MODULE "KAT"
"eo.wiktionary.org/wiki/Modulo:kat" <!--2024-Oct-11-->
Purpose: automatically generated content for categories
Utilo: auxtogenerita enhavo por kategorioj
Manfaat: isi dibangkitkan secara otomatis untuk kategori
Syfte: automatiskt genererat innehaall foer kategorier
Used by templates / Uzata far sxablonoj:
* only "kat" (not to be called from any other place)
Required submodules / Bezonataj submoduloj / Submodul yang diperlukan:
* "loaddata-tbllingvoj" T78 T80 in turn requiring template "tbllingvoj" (EO)
* "loaddata-tblbahasa" T78 T80 in turn requiring template "tblbahasa" (ID)
Required images:
* "Vista-folder open.png"
* "Hidden icon.png"
* "User-invisible.svg"
* "Nuvola filesystems folder template.png"
Required templates:
* YES, see above
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 ordinary parameters
* 3 hidden named and optional parameters
* "pagenameoverridetestonly=" can directly cause #E01
* "nsnumberoverridetestonly=" can indirectly cause #E10
* "detrc=" no error possible
Returned: * one string with visible part (HTML box) and category part,
or red error and tracking category part
All relevant information is peeked from the pagename and thus
ordinary parameters are not used.
To be called from category namespace only.
This module reads out the pagename, dissects it consulting relevant
lists (both built-in and via other modules), displays a suitable header
for the category, including a TOC if appropriate, hides the category
if appropriate, and cares about insertion into parent categories.
There are three steps all controlled by ONE common LUA table with patterns:
* identify the pagename resulting in a LUA table with details
* brew the visible text later showed in a box (plus determine icon and colour)
* brew the parent cat insertions
For the procesing here, following details are defined:
* LK langcode
* lk other langcode
* LN langname short (for example "dana" or "Ido")
* LU langname short uppercased (for example "Dana" or "Ido")
* LO langname short not own (empty if own)
* LY langname long (for example "bahasa Swedia")
* LV langname short uppercased not own (empty if own)
* LZ langname long not own (empty if own)
* WC word class (for example "substantivo")
* wc other word class
* GR grammar detail such as "uncountable noun"
* MI other detail such as "misspelling"
* WU word class uppercased (for example "Substantivo")
* TO topic
* TU topic uppercased
* LL language level 0...4 or 0...5 or "D"
* MT mortyp C I M N P U
* SK script code T S K P H C L
* SC langcode + script code zhT zhS zhK zhP jaK jaH jaR hrC hrL
* FR fragment (for example "peN-...-an" or "abelujo")
* LA link to appendix page raw
* LB link to appendix page showing langname short
* LJ link to appendix page showing langname short adjectivized and plural
Those are used in several contexts, but not the full set is applicable in
every context:
* pattern for parsing the pagename, they apprear in the strig prefixed by "@"
* pattern for generating visible text, they apprear in the string
prefixed by "@"
* pattern for generating parent categories, they apprear in the string
prefixed by "@"
* LUA table passed from the parsing stage into the generation stage, the
strings listed above appear as string keys without "@"
Two are lowercase "lk" and "wc" whereas all other are uppercase.
Types of categories by content and icon showed are:
* G generic
* H hidden
* U user
* T template
Types of categories by title structure are:
* simple raw such as "Substantivo" or "Kemio" or "Sveda"
-> no fixed pattern at all
-> cannot be validated without running through all lists (languages,
word classes, topics)
* double raw such as "Substantivo (sveda)" or "Kemio (sveda)"
-> insufficient fixed pattern such as "("...")"
-> cannot be validated without running through all lists (languages,
word classes, topics)
* mostly identifiable such as "El Sanskrito"
-> contain a pattern than is sufficient for reliable identification
together with absence of other pattern such as "("...")"
* reliably identifiable such as "Vortaro (indonezia)" or "El Sanskrito (Ido)"
Pattern for parsing the pagename can contain following variable elements:
* LK, LN, LU, LY, WC, GR, MI, WU, TO, TU, LL, MT, SK, SC, FR
The variable elements belong to three groups:
* directly listed: LK LN WC GR MI TO LL MT SK SC
* indirectly listed: LU LY WU TU
* fully free and not listed: FR
Parsing steps:
* no lists used:
* apply the 3 steps "preliminary check" and "double bracket separation"
and "extra final letter separation" with help of "lfhthree3steps", on
error however throw #E13 (bad char or doublechar) or #E14 (bad bracketing)
* report (3 integers and 4 strings)
* number of slashes
* number of colons
* number of pairs of brackets 0...2
* content of zero:th pair of brackets (can be empty)
* content of first pair of brackets (can be empty)
* extra final stuff (can be empty)
* remaining content (cannot be empty)
* many lists used:
* there are lists of patterns, languages, word classes, topics
* list of patterns is sorted from "reliably identifiable" to "simple raw"
* walk through the list of patterns, pick and test pattern after pattern
* on every pattern apply the 3 steps "preliminary check" and "double
bracket separation" and "extra final letter separation" with help of
"lfhthree3steps", on error however throw #E01 for both status
codes 13 and 14
* compare results of those steps on incoming pagename vs tested pattern
* buy the title if minimal requirements are met, for example buy not
only "Vortaro (indonezia)" but also "Vortaro (stultulo)" since the
latter lacks chance to match another pattern
The identified title is reported in the form of a LUA table. Details are
standardized to a reduced set
* LK (convert from LN LU LY)
* WC (convert from WU)
* GR
* MI
* TO (convert from TU)
* LL
* MT
* SC
* FR
Unfortunately certain elements can occur two times, namely language
(for etymological cat:s) and word class (for derived words). The final
LUA table contains following string keys (type "nil" if unused):
* type -- one of many
* LK
* lk -- other language
* WC
* wc -- other word class
* GR
* MI
* TO
* LL
* MT
* SK -- without attached langcode
* FR
Those elements are used to brew the text (plus determine the icon and
colour) as well as parent categories.
Unfortunately wikis define some dialects and scripts that we have to support
natively here ie circumventing our central language and dialect tables:
* en-GB, en-CA (but NOT "en-US")
* de-AT
* zh-Hans, zh-Hant
In order to ensure the correct order of analyzing from "reliably identifiable"
to "simple raw" we reprocess the LUA table with patterns. The incoming table
has string keys and subtables as values, every subtable has numerical indexes
starting at ONE. What we do is to brew a new table with numerical indexes,
taking elements in the corect order from "reliably identifiable" to "simple
raw" walking through the source table 4 times, and replace the value at index
ONE having the sortorder hint by the key from the source table. That way we
do no longer have to rely on "pairs" when parsing the pagename, and do not
have to bother with sortorder.
So far 6 or 8 types of pagename patterns after "Kategorio:" are recognized:
* G "El la anglosaksa" "El Sanskrito"
* has opposite cat
* in cat "Sanskrito" no hint and
in cat "Laux fonta lingvo" langname is hint
* G "Laux stilo (indonezia)"
* H "Tradukoj (indonezia)" needs __HIDDENCAT__ except "Tradukoj (Esperanto)"
* U "Vikivortaristo mi"
* in cat "Vikivortaristo laux lingvo" langcode is hint
* U "Vikivortaristo mi-D"
* in cat "Vikivortaristo mi" level is hint
* G "Vortaro (indonezia)"
* T "SXablonaro -ay-" !!!FIXME!!! not yet "kat-specifa-lng"
* in cat "Ajmara" no hint and
in cat "SXablonaro pri specifa lingvo" langcode is hint
* H "Pagxoj kun sondosiero (tamila)" !!!FIXME!!! not yet "kat-sono"
* in cat "Tamila" with fixed hint "sond" and
in cat "Pagxoj kun sondosiero" langname is hint
Tracking categories:
* #E06 "Kategori:Auxtokato kun nesubtenata pagxonomo"
* #E07 "Kategori:Auxtokato kun nekonata lingvonomo"
* #E05 #E10 "Kategori:Erara uzo de sxablono" &
"Kategori:Erara uzo de sxablono (kat)"
]===]
local exporttable = {}
------------------------------------------------------------------------
---- CONSTANTS [O] ----
------------------------------------------------------------------------
-- uncommentable strings (core site-related features)
local constringvoj = "Modulo:loaddata-tbllingvoj" -- EO
-- local constringvoj = "Modul:loaddata-tblbahasa" -- ID
local constrpriv = "eo"
-- local constrpriv = "id"
local constrapxq = "Aldono" -- EO !!!FIXME!!!
-- local constrapxq = "Lampiran" -- ID
local constrkatq = "Kategorio" -- EO
-- local constrkatq = "Kategori" -- ID
local constrkoll = 'sxablono "kat"' -- EO augmented name of the caller (semi-hardcoded, we do NOT peek it) !!!FIXME!!!
-- local constrkoll = 'templat "kat"' -- ID augmented name of the caller (semi-hardcoded, we do NOT peek it)
-- 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
-- strings (error circumfixes)
local constrelabg = '<span class="error"><b>' -- lagom whining begin
local constrelaen = '</b></span>' -- lagom whining end
local constrlaxhu = ' ** ' -- lagom -> huge circumfix " ** "
-- uncommentable table (error messages)
-- #E02...#E99, note that #E00 and #E01 are NOT supposed to be included here
local contaberaroj = {}
contaberaroj[ 5] = 'Parametroj estas maldezirindaj por \\@, legu gxian dokumentajxon' -- EO #E05 change to unknown param
-- contaberaroj[ 5] = 'Parameter tidak diterima oleh \\@, bacalah dokumentasinya' -- ID #E05 !!!FIXME!!!
contaberaroj[ 6] = 'Erara pagxonomo (neniu el 6) por \\@' -- EO #E06
-- contaberaroj[ 6] = 'Nama halaman salah (tidak satu dari 6) untuk \\@' -- ID #E06
contaberaroj[ 7] = 'Nekonata lingvonomo por \\@' -- EO #E07
-- contaberaroj[ 7] = 'Nama bahasa yang tidak dikenal untuk \\@' -- ID #E07
contaberaroj[10] = 'Erara nomspaco (estu 14, "Kategorio:") por \\@' -- EO #E10
-- contaberaroj[10] = 'Ruang nama salah (sebaiknya 14, "Kategori:") untuk \\@' -- ID #E10
contaberaroj[13] = 'Forjxetas pagxonomon pro . :: // -- (( )) en \\@' -- EO #E13
-- contaberaroj[13] = 'Nama halaman ditolak oleh karena . :: // -- (( )) dalam \\@' -- ID #E13
-- uncommentable table (boasting)
local contabboasting = {}
contabboasting['g0'] = 'En aux sub cxi tiu'
contabboasting['g1'] = 'kategorio trovigxas'
contabboasting['g2'] = 'lingvokodo'
contabboasting['elel0'] = 'kapvortoj derivitaj el'
contabboasting['elel1'] = 'La kontrauxa kategorio estas'
contabboasting['stil0'] = 'subkategorioj por kapvortoj en la lingvo'
contabboasting['stil1'] = 'laux stilo AKK lingvoregistro'
contabboasting['trad'] = 'kapvortoj kun tradukoj al la lingvo'
contabboasting[30] = 'vortaroj (aliaj ol tuta vikivortaro mem), kiuj specifas por la lingvo'
contabboasting[31] = 'La esperantan vikivortaron vi jam uzas' -- if code is "eo"
contabboasting[32] = 'La' -- if it exists
contabboasting[33] = 'Bedauxrinde ne disponeblas' -- if it lacks
contabboasting[34] = 'vikivortaro' -- in both cases
contabboasting[35] = 'provu' -- if it lacks
contabboasting[36] = 'kaj ecx la kodo estas okupita' -- if it lacks and ... (for example "als", has "??" in /c6/)
contabboasting['isnl'] = 'subkategorioj por uzantoj kiuj indikis sian nivelon en'
contabboasting['islv0'] = 'uzantoj kiuj indikis sian nivelon en'
contabboasting['islv1'] = 'je'
-- main list with pagename patterns -- !!!FIXME!!! DEPRECATED
-- * [1] parsing method
-- * 3 -> sepbracket
-- * 4 "el"-type with "la" trouble
-- * 5 isto with level
-- * 6 isto without level
-- * [2] pattern for parsing method (outer string for 3 | unused for 4 5 6)
-- * [3] reserved
-- * [4] (char) type by content and icon G H U
-- * [5] (boo) categorize in lang (for example in "Kategori:Sveda" or in "Kategori:Greka antikva") with no hint
-- * [6] (char) type of hint in extra cat
-- * "" empty string to deactive this cat
-- * "N" lang name lowercase -- "Ido -> ido"
-- * "K" lang code
-- * "L" level -- "0" "1" "2" "3" "4" "D" -> "d"
-- * [7] name of extra cat (by lang or by level or by something else)
-- (empty if none, but [6] is the control, also empty if cat
-- used but name not needed)
local contabtypesofcats = {}
contabtypesofcats['elel'] = {4, '', '', 'G', true, 'N', 'Laux fonta lingvo'} -- "El la anglosaksa"
contabtypesofcats['stil'] = {3, 'Laux stilo', '', 'G', true, 'N', 'Laux stilo kaj lingvo'} -- "Laux stilo (indonezia)"
contabtypesofcats['trad'] = {3, 'Tradukoj', '', 'H', true, 'N', 'Laux traduko'} -- "Tradukoj (indonezia)"
contabtypesofcats['isnl'] = {6, '', '', 'U', false, 'K', 'Vikivortaristo laux lingvo'} -- "Vikivortaristo mi"
contabtypesofcats['islv'] = {5, '', '', 'U', false, 'L', ''} -- "Vikivortaristo mi-D"
contabtypesofcats['varo'] = {3, 'Vortaro', '', 'G', true, 'N', 'Vortaro laux lingvo'} -- "Vortaro (indonezia)"
-- main list with types of cat:s --
-- * [1] (string) here type of category by priority and title
-- structure "sr" (last) "dr" "mi" "ri" (earliest)
-- * [1] (string) later replaced by the key such as "elel"
-- * [2] (string) pattern for identification
-- * [3] (string) deviations (for example prohibition against
-- certain languages or allowed extra ones)
-- * [4] (char) type by content and icon G H U
-- * [5] reserved
-- * [6]...[9] patterns for parent cat:s (optional hint separated by
-- wall "|", hint goes always though LFIBREWCATHINT)
local contabtypesofkat = {}
contabtypesofkat['elel'] = {'mi', 'El @LY' , '' , 'G', '', '@LU', 'Laux fonta lingvo|@LN' } -- "El la anglosaksa"
contabtypesofkat['stil'] = {'ri', 'Laux stilo (@LN)' , '' , 'G', '', '@LU', 'Laux stilo kaj lingvo|@LN' } -- "Laux stilo (indonezia)"
contabtypesofkat['trad'] = {'ri', 'Tradukoj (@LN)' , 'noeo' , 'H', '', '@LU', 'Laux traduko|@LN' } -- "Tradukoj (indonezia)"
contabtypesofkat['isnl'] = {'mi', 'Vikivortaristo@LK' , '' , 'U', '', 'Vikivortaristo laux lingvo|@LK' } -- "Vikivortaristo mi"
contabtypesofkat['islv'] = {'ri', 'Vikivortaristo@LK-@LL' , '' , 'U', '', 'Vikivortaristo@LK|@LL' } -- "Vikivortaristo mi-D"
contabtypesofkat['varo'] = {'ri', 'Vortaro (@LN)' , '' , 'G', '', '@LU', 'Vortaro laux lingvo|@LN' } -- "Vortaro (indonezia)"
-- tracking cat:s --
local contabtracking = {}
contabtracking[0] = 'Auxtokato kun nesubtenata pagxonomo' -- #E06
contabtracking[1] = 'Auxtokato kun nekonata lingvonomo' -- #E07
contabtracking[2] = 'Erara uzo de sxablono' -- #E05 #E10
contabtracking[3] = 'Erara uzo de sxablono (kat)' -- #E05 #E10
-- icons and descriptions for types of category by content
local contabicon = {}
contabicon['G'] = 'Vista-folder open.png' -- generic
contabicon['H'] = 'Hidden icon.png' -- hidden
contabicon['U'] = 'User-invisible.svg' -- user, alternative image "Nuvola apps personal unisex.svg"
contabicon['T'] = 'Nuvola filesystems folder template.png' -- template
local contabdesc = {}
contabdesc['G'] = ''
contabdesc['H'] = 'kasxita'
contabdesc['U'] = 'uzanta'
-- table (HTML)
local contabhtml = {}
contabhtml[0] = '<table style="border:1px solid #A0A0A0; background:#F0F0F0; width:95%; margin:0.6em auto 0.6em auto; padding:0.6em; text-align:justify;">'
contabhtml[3] = '<tr><td style="width:30px;">[[File:'
contabhtml[4] = '|50px]]</td><td style="padding-left:1em;">'
contabhtml[5] = '</td></tr></table>'
------------------------------------------------------------------------
---- SPECIAL STUFF OUTSIDE MAIN [B] ----
------------------------------------------------------------------------
---- SPECIAL VAR:S ----
require('strict')
local qldingvoj = {} -- type "table" and nested
local qboodetrc = true -- from "detrc=true" but default is "true" !!!
local qstrtrace = '<br>' -- for main & sub:s, debug report request by "detrc="
local qbooguard = false -- only for the guard test, pass to other var ASAP
---- GUARD AGAINST INTERNAL ERROR AND IMPORT ONE VIA LOADDATA ----
qbooguard = ((type(constringvoj)~='string') or (type(constrkoll)~='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
------------------------------------------------------------------------
-- Local function LFDMINISANI
-- Input : * strdangerous -- must be type "string", empty legal
-- * numlimitdivthree
-- Output : * strsanitized -- can happen to be quasi-empty with <<"">>
-- To be called from "lfdshowvcore" <- "lfdshowvar" only.
-- * we absolutely must disallow: cross "#" 35 | apo "'" 39 |
-- star "*" 42 | dash 45 | colon 58 | "<" 60 | ">" 62 | "[" 91 | "]" 93
-- * spaces are showed as "{32}" if repetitive or at begin or at end
local function lfdminisani (strdangerous, numlimitdivthree)
local strsanitized = '"' -- begin quot
local num38len = 0
local num38index = 1 -- ONE-based
local num38signo = 0
local num38prev = 0
local boohtmlenc = false
local boovisienc = false
num38len = string.len (strdangerous)
while true do
boohtmlenc = false -- % reset on
boovisienc = false -- % every iteration
if (num38index>num38len) then -- ONE-based
break -- done string char after char
end--if
num38signo = string.byte (strdangerous,num38index,num38index)
if ((num38signo<43) or (num38signo==45) or (num38signo==58) or (num38signo==60) or (num38signo==62) or (num38signo==91) or (num38signo==93) or (num38signo>122)) then
boohtmlenc = true
end--if
if ((num38signo<32) or (num38signo>126)) then
boovisienc = true -- overrides "boohtmlenc"
end--if
if ((num38signo==32) and ((num38prev==32) or (num38index==1) or (num38index==num38len))) then
boovisienc = true -- overrides "boohtmlenc"
end--if
if (boovisienc) then
strsanitized = strsanitized .. '{' .. tostring (num38signo) .. '}'
else
if (boohtmlenc) then
strsanitized = strsanitized .. '&#' .. tostring (num38signo) .. ';'
else
strsanitized = strsanitized .. string.char (num38signo)
end--if
end--if
if ((num38len>(numlimitdivthree*3)) and (num38index==numlimitdivthree)) then
num38index = num38len - numlimitdivthree -- jump forwards
strsanitized = strsanitized .. '" ... "'
else
num38index = num38index + 1 -- ONE-based
end--if
num38prev = num38signo
end--while
strsanitized = strsanitized .. '"' -- don't forget final quot
return strsanitized
end--function lfdminisani
------------------------------------------------------------------------
-- Local function LFDSHOWVCORE
-- Prebrew report about content of a variable including optional full
-- listing of a table with numeric and string keys. !!!FIXME!!!
-- Input : * vardubious -- content (any type including "nil" is acceptable)
-- * str77name -- name of the variable (string)
-- * vardescri -- optional comment, default empty, begin with "@" to
-- place it before name of the variable, else after
-- * varlim77tab -- optional limit, limits both string keys and
-- numeric keys, default ZERO no listing
-- Depends on functions :
-- [D] lfdminisani
local function lfdshowvcore (vardubious, str77name, vardescri, varlim77tab)
local taballkeystring = {}
local strtype = ''
local strreport = ''
local numindax = 0
local numlencx = 0
local numkeynumber = 0
local numkeystring = 0
local numkeycetera = 0
local numkey77min = 999999
local numkey77max = -999999
local boobe77fore = false
if (type(str77name)~='string') then
str77name = '??' -- bite the bullet
else
str77name = '"' .. str77name .. '"'
end--if
if (type(vardescri)~='string') then
vardescri = '' -- omit comment
end--if
if (string.len(vardescri)>=2) then
boobe77fore = (string.byte(vardescri,1,1)==64) -- prefix "@"
if (boobe77fore) then
vardescri = string.sub(vardescri,2,-1) -- CANNOT become empty
end--if
end--if
if (type(varlim77tab)~='number') then
varlim77tab = 0 -- deactivate listing of a table
end--if
if ((vardescri~='') and (not boobe77fore)) then
str77name = str77name .. ' (' .. vardescri .. ')' -- now a combo
end--if
strtype = type(vardubious)
if (strtype=='table') then
for k,v in pairs(vardubious) do
if (type(k)=='number') then
numkey77min = math.min (numkey77min,k)
numkey77max = math.max (numkey77max,k)
numkeynumber = numkeynumber + 1
else
if (type(k)=='string') then
taballkeystring [numkeystring] = k
numkeystring = numkeystring + 1
else
numkeycetera = numkeycetera + 1
end--if
end--if
end--for
strreport = 'Table ' .. str77name
if ((numkeynumber==0) and (numkeystring==0) and (numkeycetera==0)) then
strreport = strreport .. ' is empty'
else
strreport = strreport .. ' contains '
if (numkeynumber==0) then
strreport = strreport .. 'NO numeric keys'
end--if
if (numkeynumber==1) then
strreport = strreport .. 'a single numeric key equal ' .. tostring (numkey77min)
end--if
if (numkeynumber>=2) then
strreport = strreport .. tostring (numkeynumber) .. ' numeric keys ranging from ' .. tostring (numkey77min) .. ' to ' .. tostring (numkey77max)
end--if
strreport = strreport .. ' and ' .. tostring (numkeystring) .. ' string keys and ' .. tostring (numkeycetera) .. ' other keys'
end--if
if ((numkeynumber~=0) and (varlim77tab~=0)) then -- !!!FIXME!!!
strreport = strreport .. ' ### content num keys :'
numindax = numkey77min
while true do
if ((numindax>varlim77tab) or (numindax>numkey77max)) then
break -- done table
end--if
strreport = strreport .. ' ' .. tostring(numindax) .. ' -> ' .. lfdminisani(tostring(vardubious[numindax]),30)
numindax = numindax + 1
end--while
end--if
if ((numkeystring~=0) and (varlim77tab~=0)) then -- !!!FIXME!!!
strreport = strreport .. ' ### content string keys :'
end--if
else
strreport = 'Variable ' .. str77name .. ' has type "' .. strtype .. '"'
if (strtype=='string') then
numlencx = string.len (vardubious)
strreport = strreport .. ' and length ' .. tostring (numlencx)
if (numlencx~=0) then
strreport = strreport .. ' and content ' .. lfdminisani (vardubious,30)
end--if
else
if (strtype~='nil') then
strreport = strreport .. ' and content "' .. tostring (vardubious) .. '"'
end--if
end--if (strtype=='string') else
end--if (strtype=='table') else
if ((vardescri~='') and boobe77fore) then
strreport = vardescri .. ' : ' .. strreport -- very last step
end--if
return strreport
end--function lfdshowvcore
------------------------------------------------------------------------
-- Local function LFDSHOWVAR
-- Enhance upvalue "qstrtrace" with report about content of a variable
-- including optional full listing of a table with numeric and string keys. !!!FIXME!!!
-- Depends on functions :
-- [D] lfdminisani lfdshowvcore
-- upvalue "qstrtrace" must NOT be type "nil" on entry (is inited to "<br>")
-- uses upvalue "qboodetrc"
local function lfdshowvar (varduubious, strnaame, vardeskkri, vartabljjm)
if (qboodetrc) then
qstrtrace = qstrtrace .. lfdshowvcore (varduubious, strnaame, vardeskkri, vartabljjm) .. '.<br>' -- dot added !!!
end--if
end--function lfdshowvar
------------------------------------------------------------------------
---- 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))
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
------------------------------------------------------------------------
-- Local function MATHBITWRIT
-- Write bit selected by ZERO-based index assigning it to "1" or "0".
-- Depends on functions :
-- [E] mathdiv 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
------------------------------------------------------------------------
---- 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 LFGPOKESTRING
-- Replace single octet in a string.
-- Input : * strinpokeout -- empty legal
-- * numpokepoz -- ZERO-based, out of range legal
-- * numpokeval -- new value
-- This is inefficient by design of LUA. The caller is responsible to
-- minimize the number of invocations of this, in particular, not to
-- call if the new value is equal the existing one.
local function lfgpokestring (strinpokeout, numpokepoz, numpokeval)
local numpokelen = 0
numpokelen = string.len(strinpokeout)
if ((numpokelen==1) and (numpokepoz==0)) then
strinpokeout = string.char(numpokeval) -- totally replace
end--if
if (numpokelen>=2) then
if (numpokepoz==0) then
strinpokeout = string.char(numpokeval) .. string.sub (strinpokeout,2,numpokelen)
end--if
if ((numpokepoz>0) and (numpokepoz<(numpokelen-1))) then
strinpokeout = string.sub (strinpokeout,1,numpokepoz) .. string.char(numpokeval) .. string.sub (strinpokeout,(numpokepoz+2),numpokelen)
end--if
if (numpokepoz==(numpokelen-1)) then
strinpokeout = string.sub (strinpokeout,1,(numpokelen-1)) .. string.char(numpokeval)
end--if
end--if (numpokelen>=2) then
return strinpokeout
end--function lfgpokestring
------------------------------------------------------------------------
-- test whether char is an ASCII digit "0"..."9", return boolean
local function lfgtestnum (numkaad)
local boodigit = false
boodigit = ((numkaad>=48) and (numkaad<=57))
return boodigit
end--function lfgtestnum
------------------------------------------------------------------------
-- test whether char is an ASCII uppercase letter, return boolean
local function lfgtestuc (numkode)
local booupperc = false
booupperc = ((numkode>=65) and (numkode<=90))
return booupperc
end--function lfgtestuc
------------------------------------------------------------------------
-- test whether char is an ASCII lowercase letter, return boolean
local function lfgtestlc (numcode)
local boolowerc = false
boolowerc = ((numcode>=97) and (numcode<=122))
return boolowerc
end--function lfgtestlc
------------------------------------------------------------------------
---- 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 -- unit octet, number 1...4, or ZERO if invalid
-- Does NOT thoroughly check the validity, looks at ONE 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 LFUTRISTLETR
-- Evaluate char (from ASCII + selectable extra set from UTF8) to
-- tristate result (no letter vs uppercase letter vs lowercase letter).
-- Input : * strin5trist : single unicode char (1 or 2 octet:s) or
-- longer string
-- * strsel5set : "ASCII" (default, empty string or type "nil"
-- will do too) "eo" "sv" (value "GENE" NOT here)
-- Output : * numtype5x : 0 no letter or invalid UTF8 -- 1 upper -- 2 lower
-- Depends on functions : (this is LFUTRISTLETR)
-- [U] lfulnutf8char
-- [G] lfgtestuc lfgtestlc
-- [E] mathdiv mathmod mathbitwrit
-- Possible further char:s or fragments of such are disregarded, the
-- question answered is "Is there one uppercase or lowercase letter
-- available at begin?".
-- Defined sets:
-- "eo" 2 x 6 uppercase and lowercase (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
-- "sv" 2 x 4 uppercase and lowercase (AE AA EE OE ae aa ee oe)
-- upper AE $00C4 AA $00C5 EE $00C9 OE $00D6 lower +$20
local function lfutristletr (strin5trist, strsel5set)
local numtype5x = 0 -- preASSume invalid
local numlong5den = 0 -- actual length of input string
local numlong5bor = 0 -- expected length of single char
local numcha5r = 0 -- UINT8 beginning char
local numcha5s = 0 -- UINT8 later char (BIG ENDIAN, lower value here above)
local numcxa5rel = 0 -- UINT8 code relative to beginning of block $00...$FF
local numtem5p = 0
local boois5uppr = false
local boois5lowr = false
while true do -- fake loop -- this is LFUTRISTLETR
numlong5den = string.len (strin5trist)
if (numlong5den==0) then
break -- bad string length
end--if
numcha5r = string.byte (strin5trist,1,1)
numlong5bor = lfulnutf8char(numcha5r)
if ((numlong5bor==0) or (numlong5den<numlong5bor)) then
break -- truncated char or invalid
end--if
if (numlong5bor==1) then
boois5uppr = lfgtestuc(numcha5r)
boois5lowr = lfgtestlc(numcha5r)
break -- success with ASCII, almost done
end--if
numcha5s = string.byte (strin5trist,2,2) -- only $80 to $BF
numcxa5rel = (mathmod(numcha5r,4)*64) + (numcha5s-128) -- 4 times 64
if ((strsel5set=='eo') and ((numcha5r==196) or (numcha5r==197))) then
numtem5p = mathbitwrit (numcxa5rel,0,false) -- bad way to do AND $FE
if ((numtem5p==8) or (numtem5p==28) or (numtem5p==36) or (numtem5p==52) or (numtem5p==92) or (numtem5p==108)) then
boois5uppr = (numtem5p==numcxa5rel) -- UC below, block of 1
boois5lowr = not boois5uppr
break -- success with -eo-, almost done
end--if
end--if ((strsel5set=='eo') and ...
if ((strsel5set=='sv') and (numcha5r==195)) then
numtem5p = mathbitwrit (numcxa5rel,5,false) -- bad way to do AND $DF
if ((numtem5p==196) or (numtem5p==197) or (numtem5p==201) or (numtem5p==214)) then
boois5uppr = (numtem5p==numcxa5rel) -- UC below, block of 32
boois5lowr = not boois5uppr
break -- success with -sv-, almost done
end--if
end--if ((strsel5set=='sv') and ...
break -- finally to join mark -- unknown non-ASCII char is a fact :-(
end--while -- fake loop -- join mark
if (boois5uppr) then
numtype5x = 1
end--if
if (boois5lowr) then
numtype5x = 2
end--if
return numtype5x
end--function lfutristletr
------------------------------------------------------------------------
-- Local function LFUCASEREST
-- Adjust (restricted) case of a single letter (from ASCII + selectable
-- extra set from UTF8) or longer string. (this is REST)
-- Input : * strinco6cs : single unicode letter (1 or 2 octet:s) or
-- longer string
-- * booup6cas : for desired output uppercase "true" and for
-- lowercase "false"
-- * boodo6all : "true" to adjust all letters, "false"
-- only beginning letter
-- * strsel6set : "ASCII" (default, empty string or type "nil"
-- will do too) "eo" "sv" (value "GENE" NOT here)
-- Output : * strinco6cs
-- Depends on functions : (this is REST)
-- [U] lfulnutf8char
-- [G] lfgpokestring lfgtestuc lfgtestlc
-- [E] mathdiv mathmod mathbitwrit
-- This process never changes the length of a string in octet:s. Empty string
-- on input is legal and results in an empty string returned. When case is
-- adjusted, a 1-octet or 2-octet letter is replaced by another letter of same
-- length. Unknown valid char:s (1-octet ... 4-octet) are copied. Broken UTF8
-- stream results in remaining part of the output string (from 1 char to
-- complete length of the incoming string) filled by "Z".
-- Defined sets:
-- "eo" 2 x 6 uppercase and lowercase (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
-- "sv" 2 x 4 uppercase and lowercase (AE AA EE OE ae aa ee oe)
-- upper AE $00C4 AA $00C5 EE $00C9 OE $00D6 lower +$20
-- We peek max 2 values per iteration, and change the string in-place, doing
-- so strictly only if there indeed is a change. This is important for LUA
-- where the in-place write access must be emulated by means of a less
-- efficient function.
local function lfucaserest (strinco6cs, booup6cas, boodo6all, strsel6set)
local numlong6den = 0 -- actual length of input string
local numokt6index = 0
local numlong6bor = 0 -- expected length of single char
local numdel6ta = 0 -- quasi-signed +32 or -32 or +1 or -1 or ZERO
local numcha6r = 0 -- UINT8 beginning char
local numcha6s = 0 -- UINT8 later char (BIG ENDIAN, lower value here above)
local numcxa6rel = 0 -- UINT8 code relative to beginning of block $00...$FF
local numtem6p = 0
local boowan6tlowr = false
local boois6uppr = false
local boois6lowr = false
local boodo6adj = true -- preASSume innocence -- continue changing
local boobotch6d = false -- preASSume innocence -- NOT yet botched
booup6cas = not (not booup6cas)
boowan6tlowr = (not booup6cas)
numlong6den = string.len (strinco6cs)
while true do -- genuine loop over incoming string (this is REST)
if (numokt6index>=numlong6den) then
break -- done complete string
end--if
if ((not boodo6all) and (numokt6index~=0)) then -- loop can skip index ONE
boodo6adj = false
end--if
boois6uppr = false -- preASSume on every iteration
boois6lowr = false -- preASSume on every iteration
numdel6ta = 0 -- preASSume on every iteration
numlong6bor = 1 -- preASSume on every iteration
while true do -- fake loop (this is REST)
numcha6r = string.byte (strinco6cs,(numokt6index+1),(numokt6index+1))
if (boobotch6d) then
numdel6ta = 90 - numcha6r -- "Z" -- delta must be non-ZERO to write
break -- fill with "Z" char:s
end--if
if (not boodo6adj) then
break -- copy octet after octet
end--if
numlong6bor = lfulnutf8char(numcha6r)
if ((numlong6bor==0) or ((numokt6index+numlong6bor)>numlong6den)) then
numlong6bor = 1 -- reassign to ONE !!!
numdel6ta = 90 - numcha6r -- "Z" -- delta must be non-ZERO to write
boobotch6d = true
break -- truncated char or broken stream
end--if
if (numlong6bor>=3) then
break -- copy UTF8 char, no chance for adjustment
end--if
if (numlong6bor==1) then
boois6uppr = lfgtestuc(numcha6r)
boois6lowr = lfgtestlc(numcha6r)
if (boois6uppr and boowan6tlowr) then
numdel6ta = 32 -- ASCII UPPER->lower
end--if
if (boois6lowr and booup6cas) then
numdel6ta = -32 -- ASCII lower->UPPER
end--if
break -- success with ASCII and one char almost done
end--if
numcha6s = string.byte (strinco6cs,(numokt6index+2),(numokt6index+2)) -- only $80 to $BF
numcxa6rel = (mathmod(numcha6r,4)*64) + (numcha6s-128) -- 4 times 64
if ((strsel6set=='eo') and ((numcha6r==196) or (numcha6r==197))) then
numtem6p = mathbitwrit (numcxa6rel,0,false) -- bad way to do AND $FE
if ((numtem6p==8) or (numtem6p==28) or (numtem6p==36) or (numtem6p==52) or (numtem6p==92) or (numtem6p==108)) then
boois6uppr = (numtem6p==numcxa6rel) -- UC below, block of 1
boois6lowr = not boois6uppr
if (boois6uppr and boowan6tlowr) then
numdel6ta = 1 -- UPPER->lower
end--if
if (boois6lowr and booup6cas) then
numdel6ta = -1 -- lower->UPPER
end--if
break -- success with -eo- and one char almost done
end--if
end--if ((strsel6set=='eo') and ...
if ((strsel6set=='sv') and (numcha6r==195)) then
numtem6p = mathbitwrit (numcxa6rel,5,false) -- bad way to do AND $DF
if ((numtem6p==196) or (numtem6p==197) or (numtem6p==201) or (numtem6p==214)) then
boois6uppr = (numtem6p==numcxa6rel) -- UC below, block of 32
boois6lowr = not boois6uppr
if (boois6uppr and boowan6tlowr) then
numdel6ta = 32 -- UPPER->lower
end--if
if (boois6lowr and booup6cas) then
numdel6ta = -32 -- lower->UPPER
end--if
break -- success with -sv- and one char almost done
end--if
end--if ((strsel6set=='sv') and ...
break -- finally to join mark -- unknown non-ASCII char is a fact :-(
end--while -- fake loop -- join mark (this is REST)
if ((numlong6bor==1) and (numdel6ta~=0)) then -- no risk of carry here
strinco6cs = lfgpokestring (strinco6cs,numokt6index,(numcha6r+numdel6ta))
end--if
if ((numlong6bor==2) and (numdel6ta~=0)) then -- no risk of carry here
strinco6cs = lfgpokestring (strinco6cs,(numokt6index+1),(numcha6s+numdel6ta))
end--if
numokt6index = numokt6index + numlong6bor -- advance in incoming string
end--while -- genuine loop over incoming string (this is REST)
return strinco6cs
end--function lfucaserest
------------------------------------------------------------------------
---- HIGH LEVEL STRING FUNCTIONS [I] ----
------------------------------------------------------------------------
-- Local function LFIKATALDIGU
-- Brew cat insertion (no extra colon ":") or link to !!!FIXME!!! DEPRECATED
-- appendix 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 LFIKATPALDIGU
-- Brew cat insertion (no extra colon ":") or link to cat (with extra
-- colon ":") or link to page (appendix, other ns, even ns ZERO) from
-- 3 elements with optimization.
-- Input : * strprephyx -- ns prefix without colon, empty or
-- non-string if not desired ie ns ZERO
-- * strkataldnomo
-- * strhintvisi -- right part, empty or non-string if not desired
-- * numkattxtrakol -- ZERO for non-cat, ONE for cat insertion
-- (needed for optimization), TWO for extra
-- colon ie "colon rule" link to cat
local function lfikatpaldigu (strprephyx, strkataldnomo, strhintvisi, numkattxtrakol)
local strtigatipwiki = ''
if (type(strprephyx)~='string') then -- optional
strprephyx = ''
end--if
if (type(strhintvisi)~='string') then -- optional
strhintvisi = ''
end--if
if ((numkattxtrakol==1) and (strhintvisi==strkataldnomo)) then
strhintvisi = '' -- optimize: default is without ns prefix for cat:s
end--if
if (strprephyx~='') then
strkataldnomo = strprephyx .. ':' .. strkataldnomo -- now prefix plus name
end--if
if ((numkattxtrakol~=1) and (strhintvisi==strkataldnomo)) then
strhintvisi = '' -- optimize: default is with ns prefix if such is present
end--if
if (numkattxtrakol==2) then
strkataldnomo = ':' .. strkataldnomo -- ":Category"... apply "colon rule"
end--if
if (strhintvisi=='') then
strtigatipwiki = '[[' .. strkataldnomo .. ']]'
else
strtigatipwiki = '[[' .. strkataldnomo .. '|' .. strhintvisi .. ']]'
end--if
return strtigatipwiki
end--function lfikatpaldigu
------------------------------------------------------------------------
-- Local function LFIBREWCATHINT
-- Brew sorting hint/key for wiki category by lowering all letters and
-- removing junk chars other than known letters and numbers. All ASCII and
-- selected non-ASCII letters do count as such. Particularly ban spaces
-- and dashes. Controllably UTF8-aware.
-- Input : * strhinthink -- empty is useless but cannot
-- cause major harm
-- * strsignaro -- "ASCII" (default, empty string or type "nil"
-- will do too) "eo" "sv" NOPE "GENE"
-- * bookeepuk -- keep unknown non-ASCII (by default dropped
-- for sets other than "GENE", for NOPE "GENE"
-- always kept)
-- Output : * strhasiil -- risk of empty
-- Depends on functions : (restricted LFUCASEREST)
-- [U] lfulnutf8char lfutristletr lfucaserest
-- [G] lfgpokestring lfgtestnum lfgtestuc lfgtestlc
-- [E] mathdiv mathmod mathbitwrit
-- Simplified strategy:
-- * numbers unchanged
-- * ASCII lowercase unchanged
-- * ASCII uppercase lowered
-- * unknown non-ASCII dropped for sets other than "GENE" unless bookeepuk
-- * non-ASCII sent to case sub with attempt to lower
-- * everything else dropped
-- * broken stream aborts and gives empty result
local function lfibrewcathint (strhinthink, strsignaro, bookeepuk)
local strhasiil = ''
local strnew7char = ''
local numstrleon = 0
local numeindx = 1 -- ONE-based
local numczaar = 0
local numczanx = 0 -- pre-picked next char
local numettfyra = 0
numstrleon = string.len (strhinthink)
while true do -- outer genuine loop over source string
if (numeindx>numstrleon) then
break -- empty input is useless but cannot cause major harm
end--if
numczaar = string.byte (strhinthink,numeindx,numeindx)
numeindx = numeindx + 1 -- do INC here
numettfyra = lfulnutf8char (numczaar) -- 1...4 or ZERO on error
if (numettfyra==0) then
strhasiil = ''
break -- broken stream -> bugger all -- exit outer loop
end--if
numczanx = 0 -- preASSume none
if (numeindx<=numstrleon) then -- pick but do NOT INC
numczanx = string.byte (strhinthink,numeindx,numeindx)
end--if
while true do -- inner fake loop
if (numettfyra==1) then
if (lfgtestnum(numczaar) or lfgtestlc(numczaar)) then
strnew7char = string.char (numczaar)
break -- numbers and ASCII lowercase pass unchanged
end--if
if (lfgtestuc(numczaar)) then
strnew7char = string.char (numczaar+32) -- lower ASCII letter
break -- lower it
end--if
end--if (numettfyra==1) then
if ((numettfyra==2) and ((strsignaro=='eo') or (strsignaro=='sv') or (strsignaro=='GENE'))) then
strnew7char = string.char(numczaar,numczanx) -- preASSume unchanged
if ((not bookeepuk) and (strsignaro~='GENE')) then -- drop unknown
if (lfutristletr(strnew7char,strsignaro)==0) then -- no known letter
strnew7char = '' -- discard char
break
end--if
end--if
-- if (strsignaro=='GENE') then -- below: want lower, do ONE only
-- strnew7char = lfucasegene (strnew7char,false,false)
-- else
strnew7char = lfucaserest (strnew7char,false,false,strsignaro)
-- end--if
break -- done with lowercased or unchanged char
end--if ((numettfyra==2) and ...
strnew7char = '' -- anything else -> discard char
break -- finally to join mark
end--while -- inner fake loop -- join mark
strhasiil = strhasiil .. strnew7char -- ASCII char or UTF8 char or ""
numeindx = numeindx + numettfyra - 1 -- do ADD here
end--while -- outer genuine loop over source string
return strhasiil
end--function lfibrewcathint
------------------------------------------------------------------------
-- 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 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
------------------------------------------------------------------------
-- Local function LFIVARILINGVONOMO
-- Input : * strlang29name : such as "Ido" or "dana" or "samea suda"
-- * numtip29mon : 0 native -- 1 la (AJ SB) -- 2 aj -- 3 sf (root)
-- 4 av (AV real or surrogate) -- 5 pl (AJ and PL)
-- * boomaju
-- Depends on functions :
-- [U] lfulnutf8char lfucaserest
-- [G] lfgpokestring lfgtestuc lfgtestlc
-- [E] mathdiv mathmod mathbitwrit
-- incoming multiword SB such as "Malnova Volapuko" is bad, we
-- can't process such
-- note that for "numtip29mon" 1 ie "la" we will add the article to
-- native AJ only, never to native SB (but type 4 ie "av" can force AJ
-- and subsequently add "la")
-- note that we MUST NOT change the word class to AJ
-- for "numtip29mon" 4 ie "av" if multiword
-- for "numtip29mon" 5 ie "pl" we change the word class to AJ too
local function lfivarilingvonomo (strlang29name, numtip29mon, boomaju)
local strpluralizator = ''
local num29lon = 0
local num29plindex = 0
local nummychar = 0
local nummyches = 0
local booisnoun = false
local boomulwords = false
local booaddprepen = false
local booaddartla = false
if ((numtip29mon>=1) and (numtip29mon<=5)) then
num29lon = string.len (strlang29name)
nummychar = string.byte (strlang29name,num29lon,num29lon) -- last
booisnoun = (nummychar==111) -- "o"
boomulwords = (string.find (strlang29name, ' ', 1, true)~=nil) -- plain tx
booaddprepen = (numtip29mon==4) and boomulwords -- surrogate AV with "en"
booaddartla = (booisnoun==false) and ((numtip29mon==1) or booaddprepen)
if ((numtip29mon>=2) and (booaddprepen==false)) then
strlang29name = string.sub (strlang29name,1,-2) -- cut off last letter
strlang29name = lfucaserest (strlang29name,false,false,'eo') -- lower it
end--if
if (booaddartla) then
strlang29name = 'la ' .. strlang29name -- we will NOT pluralize this
end--if
if ((numtip29mon==2) or (numtip29mon==5)) then
strlang29name = strlang29name .. "a" -- AJ (pluralize later if needed)
end--if
if (numtip29mon==4) then
if (boomulwords) then
strlang29name = "en " .. strlang29name -- surrog AV from PP "en" + ...
else
strlang29name = strlang29name .. "e" -- AV
end--if
end--if
if (numtip29mon==5) then
if (boomulwords) then
strpluralizator = strlang29name
strlang29name = '' -- we will rebuild it
num29lon = string.len (strpluralizator)
num29plindex = 0 -- ZERO-based
while true do -- pluralize all words except the last one
if (num29plindex==num29lon) then
break
end--if
nummychar = string.byte (strpluralizator,(num29plindex+1),(num29plindex+1))
num29plindex = num29plindex + 1 -- ZERO-based
nummyches = 0
if (num29plindex~=num29lon) then
nummyches = string.byte (strpluralizator,(num29plindex+1),(num29plindex+1))
end--if
if ((nummychar==97) and (nummyches==32)) then
strlang29name = strlang29name .. 'aj '
num29plindex = num29plindex + 1 -- eaten 2 char:s, written 3
else
strlang29name = strlang29name .. string.char(nummychar) -- copy ch
end--if
end--while
end--if (boomulwords) then
strlang29name = strlang29name .. "j" -- pluralize last or only one AJ
end--if (numtip29mon==5) then
end--if ((numtip29mon>=1) and (numtip29mon<=5)) then
if (boomaju) then
strlang29name = lfucaserest (strlang29name,true,false,'eo') -- upper, one, eo
end--if
return strlang29name
end--function lfivarilingvonomo
------------------------------------------------------------------------
---- 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
-- Input : * numerar5code -- 1 ... 99 or 2 ... 99 (resistent against invalid
-- data type, giving "??" on such)
-- * boopeek5it -- 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 (numerar5code, boopeek5it)
local vardes4krip = 0
local numbottom6limit = 1
local stryt5sux = '#E'
if (boopeek5it) then
numbottom6limit = 2 -- #E01 is a valid code for submodule only
end--if
if (mathisintrange(numerar5code,numbottom6limit,99)) then
stryt5sux = stryt5sux .. lfnumto2digit(numerar5code)
if (boopeek5it) then
vardes4krip = contaberaroj[numerar5code] -- risk of type "nil"
if (type(vardes4krip)=='string') then
stryt5sux = stryt5sux .. ' ' .. vardes4krip
else
stryt5sux = stryt5sux .. ' ??' -- no text found
end--if
end--if (boopeek5it) then
else
stryt5sux = stryt5sux .. '??' -- no valid error code
end--if
return stryt5sux
end--function lfhconstructerar
------------------------------------------------------------------------
-- Local function LFHBREWERROR
-- Input : * numerar7code -- 2 ... 99
-- 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 (numerar7code)
local stryt7sux = ''
stryt7sux = constrlaxhu .. constrelabg .. lfhconstructerar (numerar7code,true) .. constrelaen .. constrlaxhu
return stryt7sux
end--function lfhbrewerror
------------------------------------------------------------------------
-- Local function LFHFILLSURRSTRTAB
-- Process (fill in, transcode) either 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). Items with a non-string
-- value are kept as-is. Optional filling in own name, and optional
-- transcoding of eo and NOPE 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 NOPE "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)
-- NOPE [I] lfikodsvsg (only if conv of sv blackslash-surrogates desired)
-- [G] lfgstringrange (via "lfifillinx")
-- [E] mathdiv mathmod (via "lfikodeosg" and NOPE "lfikodsvsg")
-- Depends on constants :
-- * table "contabtransluteo" inherently holey (via "lfikodeosg")
-- NOPE * table "contabtranslutsv" inherently holey (via "lfikodsvsg")
local function lfhfillsurrstrtab (varinkommen, varfyllo, strlingkod, bookeys)
local varkey = 0 -- &
local varnky = 0 -- & variable without type
local varele = 0 -- &
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 varkey,varele in pairs(varinkommen) do -- nothing done if table empty
if ((bookeys==true) and (type(varkey)=='string')) then
varnky = lfhfillsurrstrtab (varkey, false, strlingkod, nil) -- RECURSION
else
varnky = varkey
end--if
if ((type(varele)=='string') or (type(varele)=='table')) then
varele = lfhfillsurrstrtab (varele, varfyllo, strlingkod, bookeys) -- RECURSION
end--if
varutmatning[varnky] = varele -- 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 LFHTHREE3STEPS
-- Perform three steps on a string and return a table with 7 results
-- plus status code.
-- Input : * vstrkjng
-- Output : * table
-- * [0] ZERO success | 13 . :: // -- (( )) | 14 brackets
-- * [1] number of slashes
-- * [2] number of colons
-- * [3] number of pairs of brackets 0...2
-- * [4] content of zero:th pair of brackets (can be empty)
-- * [5] content of first pair of brackets (can be empty)
-- * [6] extra final stuff (can be empty)
-- * [7] remaining content (cannot be empty)
-- Depends on functions :
-- [I] lfisepbracket
-- * preliminary check:
-- * count slashes and colons
-- * reject the string with code 13 if it contains:
-- * dot
-- * double colon
-- * double slash
-- * double dash
-- * double arc bracket "((" or "))"
-- * double bracket separation:
-- * count pairs of arc brackets "("...")" with at least one char in between
-- * reject the string with code 14 if more than two pairs, or bracketing
-- broken in any way
-- * dissect the string into following elements:
-- * content of zero:th pair of brackets (leave emty "()" behind)
-- * content of first pair of brackets (leave emty "()" behind)
-- * remaining content (reject with code 14 if empty string here)
-- * extra final letter separation:
-- * if the last char is an ASCII uppercase letter and preceded by ") "
-- bracket and space then cut of the space and the letter keeping
-- the bracket
-- * if the last char is an uppercase letter and preceded by dash
-- in turn preceded by ASCII letter then cut of the dash and the letter
-- keeping the letter
local function lfhthree3steps (strkjng)
local numertko = 0
local numislashes = 0
local numicolons = 0
local numipairs = 0
local stribrazero = ''
local stribraone = ''
local stribraone = ''
local strifinal = ''
return {[0]=numertko,numislashes,numicolons,numipairs,stribrazero,stribraone,stribraone,strifinal}
end--function lfhthree3steps
------------------------------------------------------------------------
---- 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 newtabtypesofkat = {} -- converted from contabtypesofcats
local tablg78ysubt = {}
local tablg80lefty = {}
local tabonelang = {} -- subtable for one language
-- peeked stuff
local strpiklangcode = '' -- "en" privileged site language
local strpikkatns = '' -- "Category"
local strpikapxns = '' -- "Appendix"
local strpikparent = ''
-- general str
local strboxtext = ''
local strtump = ''
local strpagenam = '' -- "{{PAGENAME}}" o "pagenameoverridetestonly"
local strruangna = '' -- "{{NAMESPACENUMBER}}" o "nsnumberoverridetestonly"
local strkodbah = '' -- directly picked or translated from "strnambah"
local strnambah = '' -- language name (short)
local strnambauc = '' -- language name with uppercased begin letter
local strnambalc = '' -- language name with lowercased begin letter
local strnambala = '' -- language name (long) with "la " if needed
local strnambaaj = '' -- language name (force AJ)
local strlauxcatip = '' -- N K L
local strlauxcatnm = '' -- name of extra cat (exp or brewed from parent cat)
local strcol6q = '' -- subdomain, "-" same, "??" stolen
local strcol7q = '' -- status 2 digits
local straliawk = ''
local strenkonduko = '' -- begin of text with type by content
local straldonsh = '' -- link to appendix page (short)
local straldonlg = '' -- link to appendix page (long)
local striconbc = '' -- picked based on "G" or "H" or "U"
local strdescbc = '' -- picked based on "G" or "H" or "U"
local strtypeof = '' -- type of cat
local strvisgud = '' -- visible output on success
local strinvkat = '' -- invisible category part on success
local strviserr = '' -- visible error message on error
local strtrakat = '' -- invisible tracking categories on success or error
local strret = '' -- final result string
-- general num
local numerr = 0 -- 1 internal
local num2statcode = 0
local numlevel = 0 -- ASCII thus 48...52 or 69 for "D"
local numtamp = 0
-- general boo
local boohidden = false -- whether to hide the cat
local boolangcat = false
local bootaroexists = false
local boocodestolen = false
local bootimp = false
------------------------------------------------------------------------
---- MAIN [Z] ----
------------------------------------------------------------------------
---- GUARD AGAINST INTERNAL ERROR AGAIN ----
-- later reporting of #E01 may NOT depend on uncommentable strings
lfdtracemsg ('This is "kat", requested "detrc" report')
if (qbooguard) then
numerr = 1 -- #E01 internal
end--if
---- PEEK STUFF THAT IS NOT OVERRIDDEN ---- !!!FIXME!!! INCOMPLETE
-- this depends on "arxframent" if parent requested, but NEVER on "arx"
-- "strpikkatns" and "strpikindns" and "strpikapxns" do
-- NOT include a trailing ":" colon, and are intended for
-- "lfykattlaenk" and "lfyapxindlaenk" and "lfikatpaldigu"
strpiklangcode = constrpriv
strpikkatns = constrkatq
strpikapxns = constrapxq
strpikparent = constrkoll
if ((type(strpiklangcode)~='string') or (type(strpikkatns)~='string') or (type(strpikapxns)~='string')) then
numerr = 1 -- #E01 internal
end--if
lfdshowvar (strpiklangcode,'strpiklangcode','@Peeking from MW done')
lfdshowvar (strpikkatns,'strpikkatns')
lfdshowvar (strpikapxns,'strpikapxns')
lfdshowvar (strpikparent,'strpikparent')
lfdshowvar (numerr,'numerr','should be ZERO')
---- PROCESS MESSAGES, FILL IN ALWAYS, SURR ONLY IF NEEDED ----
-- placeholder "\@" "\\@" is replaced by augmented name of the caller
-- from "strpikparent" in any case, for example 'sxablono "test"' or
-- 'templat "test"'
-- only for some languages the surr-transcoding is subsequently performed
if (numerr==0) then
contaberaroj = lfhfillsurrstrtab (contaberaroj, strpikparent, strpiklangcode, nil)
contabboasting = lfhfillsurrstrtab (contabboasting, nil, strpiklangcode, nil) -- no filling
contabtypesofcats = lfhfillsurrstrtab (contabtypesofcats, nil, strpiklangcode, nil) -- nested, no filling
contabtracking = lfhfillsurrstrtab (contabtracking, nil, strpiklangcode, nil) -- no filling
contabdesc = lfhfillsurrstrtab (contabdesc, nil, strpiklangcode, nil) -- no filling
end--if
lfdshowvar (numerr,'numerr','@Messages processed')
---- CONVERT AND SORT TABLE ----
-- copy from contabtypesofcats to newtabtypesofkat
-- sortorder is from "ri" (earliest) -> "mi" -> "dr" -> to "sr" (last)
if (numerr==0) then
strtump = 'ri' -- source group
numtamp = 1 -- dest index
while true do
for k7k,v7v in pairs(contabtypesofcats) do
if (v7v[1]==strtump) then
v7v[1] = k7k -- replace
newtabtypesofkat[numtamp] = lfhfillsurrstrtab (v7v, nil, strpiklangcode) -- store modified subtable
numtamp = numtamp + 1
lfdshowvar (k7k,'k7k','stored')
end--if
end--for
if (strtump=='sr') then
break -- 4 iterations in outer loop done
end--if
if (strtump=='dr') then
strtump = 'sr'
end--if
if (strtump=='mi') then
strtump = 'dr'
end--if
if (strtump=='ri') then
strtump = 'mi'
end--if
end--while
lfdshowvar (numtamp,'numtamp','ONE too much, sorting done')
end--if
---- PICK TWO SUBTABLES T78 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]) -- from "loaddata-tbllingvoj"
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['T78']
if (type(vartymp)~='table') then -- important check
numerr = 2 -- #E02 malica
break -- to join mark
end--if
tablg78ysubt = vartymp -- y-index -> subtable (one for every langcode)
vartymp = qldingvoj['T80']
if (type(vartymp)~='table') then -- important check
numerr = 2 -- #E02 malica
break -- to join mark
end--if
tablg80lefty = vartymp -- left-most column -> y-index (langname to langcode)
break -- finally to join mark
end--while -- fake loop -- join mark
lfdshowvar (numerr,'numerr','@After attempt to seize tables T78 T80')
lfdshowvar (num2statcode,'num2statcode')
---- GET THE ARX (ONE OF TWO) ----
-- must be seized independently on "numerr" even if we already suck
-- 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 3 HIDDEN NAMED PARAMS ----
-- 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
-- "detrc=" must be seized independently on "numerr"
-- even if we already suck, but type "table" must be ensured above !!!
strpagenam = ''
if (numerr==0) then
vartymp = arxsomons['pagenameoverridetestonly']
if (type(vartymp)=='string') then
numtamp = string.len(vartymp)
if ((numtamp>=1) and (numtamp<=120)) then
strpagenam = vartymp -- empty is not legal
else
numerr = 1 -- #E01 internal
end--if
end--if
end--if
strruangna = ''
if (numerr==0) then
vartymp = arxsomons['nsnumberoverridetestonly']
if (type(vartymp)=='string') then
numtamp = string.len(vartymp)
if ((numtamp>=1) and (numtamp<=4)) then
strruangna = vartymp -- empty is not legal but ignore crime
end--if
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
lfdshowvar (numerr,'numerr','done with hidden params')
---- SEIZE THE PAGENAME FROM MW ----
-- 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
vartymp = mw.title.getCurrentTitle().text -- without namespace prefix
if (type(vartymp)=='string') then -- this can leave bhd "strpagenam" empty
numtamp = string.len(vartymp)
if ((numtamp>=1) and (numtamp<=120)) then
strpagenam = vartymp -- pagename here (empty is NOT legal)
else
numerr = 1 -- #E01 internal
end--if
end--if
end--if
if (numerr==0) then
if (strpagenam=='') then
numerr = 1 -- #E01 internal
end--if
end--if
lfdshowvar (numerr,'numerr','after seizure of pagename')
lfdshowvar (strpagenam,'strpagenam')
---- SEIZE THE NAMESPACE FROM MW AND CHECK IT ----
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
if ((numerr==0) and (strruangna~='14')) then
numerr = 10 -- #E10 ns
end--if
lfdshowvar (numerr,'numerr','after seizure of namespace')
lfdshowvar (strruangna,'strruangna')
---- DISSECT THE PAGENAME ---- !!!FIXME!!! DEPRECATED
-- the pagename comes in "strpagenam"
-- "contabtypesofcats" (string keys) has subtables (ONE-based keys)
-- * [1] parsing method (3 -> sepbracket | 4,5,6)
-- * [2] pattern for parsing method
-- * [3] reserved
-- * [4] (char) type by content G H U
-- * [5] (boo) categorize in lang
-- * [6] (char) categorize lang N K L (empty string to deactive)
-- * [7] name of extra cat
-- here we do NOT validate the language name in any way beyond length >= 2
-- things like "Tradukoj (**)" will pass here, will get caught below
-- "Tradukoj (Esperanto)" will pass here and will pass the validation
-- of language name too, this must be caught even later
-- things like "El la **" will pass here, will get caught below
-- things like "El la Ido" will pass here and will pass the validation
-- of language name too, this must be caught even later
-- output from here (risk for #E01 and #E06):
-- * strnambah or strkodbah (from pagename)
-- * numlevel (from pagename)
-- * strtypeof (from table "key", string with 4 char:s)
-- * boolangcat (from [5])
-- * boohidden (indirectly from [4])
-- * striconbc and strdescbc (indirectly from [4])
-- * strlauxcatip (from [6] N K L can be empty if none)
-- * strlauxcatnm (from [7] can be empty if none)
if (numerr==0) then
strtypeof = ''
do -- scope
local strdebin = '' -- from "lfisepbracket" can be needed
local strdebut = '' -- from "lfisepbracket" can be needed
local strau2tr = '' -- pattern from [2]
local strby4content = '' -- from [4] "G" or "H" or "U"
local numpanalength = 0
local numpars1met = 0
local numverlastch = 0
local numprelastch = 0
local boodebrako = false
local booparsdan = false
numpanalength = string.len(strpagenam)
numverlastch = string.byte(strpagenam,-1,-1)
if (numpanalength>=2) then
numprelastch = string.byte(strpagenam,-2,-2)
end--if
boodebrako, strdebin, strdebut = lfisepbracket (strpagenam, 2)
for k7k,v7v in pairs(contabtypesofcats) do
if ((type(k7k)~='string') or (type(v7v)~='table')) then
lfdtracemsg ('Aborting "for in pairs" due to broken internal table (k,v)')
numerr = 1 -- #E01 internal
break
end--if
lfdshowvar (k7k,'k7k','iterating over possible patterns')
booparsdan = false -- reset on every iter
numpars1met = v7v[1]
strau2tr = v7v[2] -- empty if not used
strby4content = v7v[4] -- G H U
if ((type(strau2tr)~='string') or (type(strby4content)~='string')) then
lfdtracemsg ('Aborting "for in pairs" due to broken internal table (pos 2,4)')
numerr = 1 -- #E01 internal
break
end--if
boohidden = (strby4content=='H')
striconbc = contabicon [strby4content]
strdescbc = contabdesc [strby4content]
if ((type(striconbc)~='string') or (type(strdescbc)~='string')) then
lfdtracemsg ('Aborting "for in pairs" due to broken table "GHU-icon-desc"')
numerr = 1 -- #E01 internal
break
end--if
boolangcat = v7v[5]
strlauxcatip = v7v[6] -- N K L empty if not desired
strlauxcatnm = v7v[7] -- empty if not used or brewed from parent cat
if (numpars1met==3) then -- based on lfisepbracket
booparsdan = true
lfdtracemsg ('Trying parsing method 3')
if (boodebrako and ((strau2tr..' ()')==strdebut)) then
strtypeof = k7k
strnambah = strdebin
lfdshowvar (strtypeof,'strtypeof','L&G we found h*m by method 3')
break
end--if
end--if
if (numpars1met==4) then -- "el"-type
booparsdan = true
lfdtracemsg ('Trying parsing method 4')
if ((numpanalength>=8) and (string.sub(strpagenam,1,6)=='El la ')) then
strtypeof = k7k
strnambah = string.sub(strpagenam,7,-1)
lfdshowvar (strtypeof,'strtypeof','L&G we found h*m by method 4 with "la"')
break
end--if
if ((numpanalength>=5) and (string.sub(strpagenam,1,3)=='El ')) then
strtypeof = k7k
strnambah = string.sub(strpagenam,4,-1)
lfdshowvar (strtypeof,'strtypeof','L&G we found h*m by method 4 without "la"')
break
end--if
end--if
if (numpars1met==5) then -- isto with level "Vikivortaristo mi-D"
booparsdan = true
lfdtracemsg ('Trying parsing method 5')
if (((numpanalength==19) or (numpanalength==20)) and (string.sub(strpagenam,1,15)=='Vikivortaristo ') and (numprelastch==45)) then
if (((numverlastch>=48) and (numverlastch<=52)) or (numverlastch==68)) then
strtypeof = k7k
if (numpanalength==19) then
strkodbah = string.sub(strpagenam,16,17) -- 2-letter code
else
strkodbah = string.sub(strpagenam,16,18) -- 3-letter code
end--if
numlevel = numverlastch -- ASCII
lfdshowvar (strtypeof,'strtypeof','L&G we found h*m by method 5')
break
end--if
end--if
end--if
if (numpars1met==6) then -- isto without level
booparsdan = true
lfdtracemsg ('Trying parsing method 6')
if (((numpanalength==17) or (numpanalength==18)) and (string.sub(strpagenam,1,15)=='Vikivortaristo ')) then
strtypeof = k7k
if (numpanalength==17) then
strkodbah = string.sub(strpagenam,16,17) -- 2-letter code
else
strkodbah = string.sub(strpagenam,16,18) -- 3-letter code
end--if
lfdshowvar (strtypeof,'strtypeof','L&G we found h*m by method 6')
break
end--if
end--if
if (not booparsdan) then
lfdtracemsg ('Aborting "for in pairs" due to unknown parsing method')
numerr = 1 -- #E01 internal
break
end--if
end--for
if (strtypeof=='') then -- NOT found
numerr = 6 -- #E06 no valid pattern
lfdtracemsg ('Exited "for in pairs" with pattern NOT found')
end--if
end--do scope
end--if
lfdshowvar (numerr,'numerr','after dissection')
lfdshowvar (boohidden,'boohidden')
lfdshowvar (strkodbah,'strkodbah','maybe lang code is here')
lfdshowvar (strnambah,'strnambah','maybe lang name is here')
---- REVERSE-QUERY NAME -> CODE IF NEEDED ----
if ((numerr==0) and (strkodbah=='')) then
strkodbah = tablg80lefty[strnambah]
if (type(strkodbah)~='string') then
numerr = 7 -- #E07 valid pattern but invalid language
end--if
end--if
lfdshowvar (numerr,'numerr','after reverse query via T80')
lfdshowvar (strkodbah,'strkodbah','maybe picked here')
---- ALWAYS PREPARE FOR FORWARD QUERIES ----
-- error when picking tabonelang should be impossible
-- if strkodbah comes from tablg80lefty
if (numerr==0) then
tabonelang = tablg78ysubt[strkodbah] -- get subtable from T78
if (type(tabonelang)~='table') then
numerr = 7 -- #E07 valid pattern but invalid language
tabonelang = {} -- guard against indexing error
end--if
end--if
---- PERFORM LAST STEP OF FORWARD QUERY IF NEEDED ----
if ((numerr==0) and (strnambah=='')) then
strnambah = tabonelang[0] -- /c0/
if (type(strnambah)~='string') then
numerr = 1 -- #E01 internal (should be impossible)
end--if
end--if
lfdshowvar (numerr,'numerr','after forward query via "tabonelang"')
lfdshowvar (strnambah,'strnambah','maybe picked here')
---- REASSIGN WORD CLASS AND LETTER CASE ----
if (numerr==0) then
strnambauc = lfucaserest (strnambah,true,false,'eo') -- uppercase
strnambalc = lfucaserest (strnambah,false,false,'eo') -- lowecase for the hint
strnambala = lfivarilingvonomo (strnambah,1,false) -- long with "la "
strnambaaj = lfivarilingvonomo (strnambah,2,false) -- adjective yes we can
end--if
lfdshowvar (strnambauc,'strnambauc')
lfdshowvar (strnambalc,'strnambalc')
lfdshowvar (strnambala,'strnambala')
lfdshowvar (strnambaaj,'strnambaaj')
---- CATCH SOME FAULTY PAGENAMES ----
-- incoming "strtypeof" and "strpagenam"
-- "Tradukoj (Esperanto)" is illegal
-- things like "El la Ido" or "El hispana" are illegal
if (numerr==0) then
while true do -- fake loop
if (strpagenam=='Tradukoj (Esperanto)') then
lfdtracemsg ('rejecting "Tradukoj (Esperanto)"')
numerr = 6 -- #E06 no valid pattern
break
end--if
strtump = "El " .. strnambala
if ((strtypeof=='elel') and (strpagenam~=strtump)) then
lfdtracemsg ('rejecting malformed "el"-type due to "' .. strpagenam .. '" <> "'.. strtump .. '"')
numerr = 6 -- #E06 no valid pattern
break
end--if
break -- finally to join mark
end--while -- fake loop -- join mark
end--if
---- PICK COLUMNS 6 AND 7 AND BREW LINK IF NEEDED ----
-- this gives "straliawk" raw link and "bootaroexists" and "boocodestolen"
if ((numerr==0) and (strtypeof=='varo')) then
strcol6q = tabonelang[6] -- subdomain ie non-standard code /c6/
if ((type(strcol6q)~='string') or (strcol6q=='-')) then
strcol6q = strkodbah -- then ASSume same
end--if
strcol7q = tabonelang[7] -- status 2 digits /c7/
if (type(strcol7q)~='string') then
strcol7q = '00' -- ASSume nope
end--if
boocodestolen = (strcol6q=='??')
if (not boocodestolen) then
bootaroexists = ((string.byte(strcol7q,2,2))==50) -- got a "2" there ??
straliawk = 'http://' .. strcol6q .. '.wiktionary.org' -- even if inexis
end--if
lfdtracemsg ('2 queries via T78 done')
lfdshowvar (straliawk,'straliawk')
lfdshowvar (bootaroexists,'bootaroexists')
lfdshowvar (boocodestolen,'boocodestolen')
end--if ((numerr==0) and (strtypeof=='varo')) then
---- PREBREW INTRO AND LINK TO APPENDIX PAGE ----
-- incoming "strdescbc" "strkodbah" "strnambah" "strnambauc" "strnambala"
-- string "strpikapxns" is appendix prefix and excludes the colon ":"
-- result "strenkonduko" will look like (indeed space at end)
-- "En aux sub cxi tiu kategorio trovigxas "
-- or
-- "En aux sub cxi tiu uzanta kategorio trovigxas "
-- result "straldonsh" will look like (no space at end)
-- "<b>[[Aldono:Dana|dana]]</b> (lingvokodo <code>-da-</code>)"
-- result "straldonlg" will look like (no space at end)
-- "<b>[[Aldono:Dana|la dana]]</b> (lingvokodo <code>-da-</code>)"
if (numerr==0) then
if (strdescbc~='') then
strdescbc = strdescbc .. ' ' -- below insert extra word incl space after
end--if
strenkonduko = contabboasting['g0'] .. ' ' .. strdescbc .. contabboasting['g1'] .. ' '
strtump = '</b> (' .. contabboasting['g2'] .. ' <code>-' .. strkodbah .. '-</code>)'
straldonsh = '<b>' .. lfikatpaldigu(strpikapxns,strnambauc,strnambah,0) .. strtump -- (short)
straldonlg = '<b>' .. lfikatpaldigu(strpikapxns,strnambauc,strnambala,0) .. strtump -- (long)
end--if (numerr==0) then
---- PREBREW TEXT ----
-- this is controlled by "strtypeof"
-- incoming also "striconbc" "strdescbc"
-- further "numlevel"
-- this is the latest occasion where #E01 can arise
if (numerr==0) then
bootimp = false
if (strtypeof=='elel') then -- "el"-type
strtump = lfikatpaldigu(strpikkatns,'Deveno ('..strnambah..')','',2) -- colon
strboxtext = strenkonduko .. contabboasting['elel0'] .. ' ' .. straldonlg .. '. ' .. contabboasting['elel1'] .. ' ' .. strtump .. '.'
bootimp = true
end--if
if (strtypeof=='stil') then -- stilo
strboxtext = strenkonduko .. contabboasting['stil0'] .. ' ' .. straldonsh .. ' ' .. contabboasting['stil1'] .. '.'
bootimp = true
end--if
if (strtypeof=='trad') then -- tradukoj
strboxtext = strenkonduko .. contabboasting['trad'] .. ' ' .. straldonsh .. '.'
bootimp = true
end--if
if (strtypeof=='varo') then -- vortaro
strboxtext = strenkonduko .. contabboasting[30] .. ' ' .. straldonsh .. '.'
if (strkodbah=='eo') then
strtump = contabboasting[31] .. '.'
else
if (bootaroexists) then
strtump = '[' .. straliawk .. ' ' .. contabboasting[32] .. ' ' .. strnambaaj .. ' ' .. contabboasting[34] .. ']'
else
strtump = contabboasting[33] .. ' ' .. strnambaaj .. ' ' .. contabboasting[34]
if (boocodestolen) then
strtump = strtump .. ', ' .. contabboasting[36] .. '.'
else
strtump = strtump .. '. ([' .. straliawk .. ' ' .. contabboasting[35] ..'])'
end--if
end--if (bootaroexists) else
end--if
strboxtext = strboxtext .. '<br><br><div style="text-align:center;">' .. strtump .. '</div>'
bootimp = true
end--if (strtypeof=='varo') then
if (strtypeof=='isnl') then
strboxtext = strenkonduko .. contabboasting['isnl'] .. ' ' .. straldonlg .. '.'
bootimp = true
end--if
if (strtypeof=='islv') then
strboxtext = strenkonduko .. contabboasting['islv0'] .. ' ' .. straldonlg .. ' ' .. contabboasting['islv1'] .. ' "' .. string.char(numlevel) .. '".'
strlauxcatnm = string.sub(strpagenam,1,-3) -- cut off 2 letters
bootimp = true -- "strlauxcatnm" is generated from parent cat
end--if
if (not bootimp) then
numerr = 1 -- #E01 internal
lfdshowvar (strtypeof,'strtypeof','inconsistent, failed to brew box text, #E01')
end--if
end--if (numerr==0) then
---- WHINE IF YOU MUST #E01 ----
-- reporting of this error #E01 must NOT depend on
-- uncommentable stuff such as "strpikparent" and "contaberaroj"
-- do NOT use sub "lfhbrewerror", report our name (NOT of template), in EN
if (numerr==1) then
strtump = '#E01 Internal error in module "kat".'
strviserr = constrlaxhu .. constrelabg .. strtump .. constrelaen .. constrlaxhu
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 "strpikparent"
if (numerr>1) then
strviserr = lfhbrewerror(numerr)
end--if
---- BREW THE VISIBLE BOX PART AROUND THE TEXT ----
-- incoming "striconbc" and "strboxtext"
if (numerr==0) then
strvisgud = contabhtml[0] .. contabhtml[3] .. striconbc .. contabhtml[4] .. strboxtext .. contabhtml[5]
end--if
---- BREW THE INVISIBLE CATEGORY PART ----
-- incoming:
-- * "boolangcat" and "strlauxcatip" and "strlauxcatnm"
-- * "strnambah" and "strnambauc" and "strnambalc"
-- * "numlevel"
-- * "boohidden"
-- string "strpikkatns" is cat prefix and excludes the colon ":"
-- brew "__HIDDENCAT__" if needed as well as up to 2 category insertions
if (numerr==0) then
do -- scope
local strkeysorthint = ''
local boobrewthatone = false
if (boolangcat) then -- cat insertion no hint
strinvkat = lfikatpaldigu(strpikkatns,strnambauc,'',1)
end--if
if (strlauxcatip=='N') then -- lang name
strkeysorthint = lfibrewcathint(strnambah,'eo',false) -- must clean up
boobrewthatone = true
end--if
if (strlauxcatip=='K') then -- lang code
strkeysorthint = strkodbah -- no cleanup needed
boobrewthatone = true
end--if
if (strlauxcatip=='L') then -- level
strkeysorthint = string.char(numlevel) -- cleanup needed for "D" only
boobrewthatone = true
end--if
if (boobrewthatone) then -- cat insertion custom hint
strinvkat = strinvkat .. lfikatpaldigu(strpikkatns,strlauxcatnm,strkeysorthint,1)
end--if
if (boohidden) then
strinvkat = '__HIDDENCAT__' .. strinvkat
end--if
end--do scope
end--if (numerr==0) then
---- BREW THE TRACKING CATEGORY PART ----
if (numerr==6) then
strtrakat = lfikataldigu(strpikkatns,contabtracking[0]) -- #E06
end--if
if (numerr==7) then
strtrakat = lfikataldigu(strpikkatns,contabtracking[1]) -- #E07
end--if
if ((numerr==5) or (numerr==10)) then
strtrakat = lfikataldigu(strpikkatns,contabtracking[2]) .. lfikataldigu(strpikkatns,contabtracking[3]) -- #E05 #E10
end--if
---- RETURN THE JUNK STRING ----
-- on #E02 and higher we risk partial results in "strvisgud" and "strinvkat"
lfdtracemsg ('Ready to return string glued together from 1 + 4 parts')
lfdshowvar (strvisgud,'strvisgud')
lfdshowvar (strinvkat,'strinvkat')
lfdshowvar (strviserr,'strviserr')
lfdshowvar (strtrakat,'strtrakat')
if (numerr==0) then
strret = strvisgud .. strinvkat
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