Modulo:mpiktbllki
Salti al navigilo
Salti al serĉilo
![]() | ||
Memtesto disponeblas sur la dokumentaĵa subpaĝo. |
- dependas de Modulo:loaddata-tbllingvoj
- ĈI TIU MODULO ESTAS ARKAIKIGITA tamen ankoraŭ uzata
--[===[
MODULE "MPIKTBLLKI" (pick from table lingvokodo al info) THIS MODULE IS DEPRECATED
"eo.wiktionary.org/wiki/Modulo:mpiktbllki" <!--2023-Jul-xx-->
"id.wiktionary.org/wiki/Modul:mpiktbllki"
Purpose: picks an element from a raw two-dimensional table, or more
precisely from "tbllingvoj" (EO) or "tblbahasa" (ID)
Utilo: ellegas elementon el kruda dudimensia tabelo, aux pli
precize el "tbllingvoj" (EO) aux "tblbahasa" (ID)
Manfaat: membaca elemen dari tabel berdimensi dua, ...
Syfte: laeser ut ett element fraan en tvaadimensionell tabell, ...
Used by templates / Uzata far sxablonoj /
Digunakan oleh templat / Anvaent av mallar:
- "Lingvo" "auxdo" "deveno3" "t" "ligald" ...
- "Modulo:mlili" "mfarado" ...
- "Modulo:mlawc" siavice uzata far sxablono "livs" (EO) /
"Modul:mlawc" digunakan oleh templat "bakk" (ID)
Required submodules / Bezonataj submoduloj / Submodul yang diperlukan:
- "mbllingvoj" in turn requiring template "tbllingvoj" (EO)
- "mtblbahasa" in turn requiring template "tblbahasa" (ID)
We do NOT need "mpiksubstrind" since we contain a copy of a part of its code.
Incoming: * 1 or 2 obligatory anonymous parameters :
* requested y-index (access code of the
language, 2 or 3 lowercase chars) (string indexing),
or /c0/ for reverse query, or /c1/ for extra query
* requested x-index (0...10) (numerical indexing),
or special value "L" (line) or "R" (reverse) or "X" (extra),
required for default "bin=0", optional for "bin=1" (only "R"
and "X" legal then)
* 5 optional named parameters :
* "bin=1" for binary output, "0" is error and "1" is success,
works for forward (only by y-index) and reverse and extra
query, default is "bin=0"
* "rel=0" for no removal of rl-lr-enclosement (for
non-latin scripts), or "1" to remove it, default is "rel=1",
only for ordinary x-indexes, not for "L" "R" "X", nor "bin=1"
* "alt=" alternative output string to replace "-" coming literally
from the source table (1...64 char:s, default is "-")
* "err=" alternative output string to replace the "=" error
message (1...64 char:s, default is "=") (this works even
for errors coming from anonymous parameters)
* "detrc=true" to create trace debug report
Returned: * one string
* for index number 0...10 the found element or "=" if
the element was not found (due to y or x) or an error occurred
* for special input value "L" the complete table line including
the y-index marker (but excessive whitespace reduced), or "="
if the y-index marker was not found or an error occurred
* for "bin=1" binary output either "1" if the
y-index marker was found (not checking the table line), or
"0" if the requested y-index was not found or an error occurred
* for special input value "R" or "X" the /cy/ found from /c0/ or
/c1/ by a reverse or extra query
The function of this module is governed by
the "Specification of the 2-dimensional table picking system".
* y-index markers are obligatory and
lowercase (numerical indexing and "-" not yet allowed) !!!FIXME!!!
* x-index markers are disallowed !!!FIXME!!!
Column numbering in the source table:
- numbering starts from ZERO
- /cy/ does not count (it has theoretically index "-1")
- note that there is no comma between /cy/ and /c0/
- "mpiktbllki" with special x-index "L" returns the complete table line
including the y-index marker /cy/, this means that unless the /cy/ part
is trimmed off, index ZERO fed into "mpiksubstrind" will return both
/cy/ and /c0/, and the indexes used by "mpiksubstrind" will NOT be
OFF-by-ONE in any case
y-index marker (row index marker) placed in the
table content area (here lowercase)
x-index marker (column index marker) placed in the
table content area (here prohibitied)
digit index marker (only digits) (here NOT supported)
lowercase index marker (lowercase letters and maybe a bit more)
incoming requested index (per spec may be evaluated to string indexing
or numerical indexing, but here hardcoded)
string indexing <--> lowercase index marker
numerical indexing <--> digit index marker or no index
marker and counting (here only counting)
General rules and specific limits (see spec):
- double square brackets "[[" and "]]" are reserved for y-index markers
and such may occur only at the beginning of line (here we assume this)
- usage of single square brackets "[" and "]" is not limited
- double round brackets "((" and "))" are reserved for x-index markers
(here we don't support x-index markers at all)
- usage of single round brackets "(" and ")" is not limited
- more than two subsequent brackets ie for
example "[[[" or ")))" are prohibited
- no comma "," following [[...]] and ((...)), inline whitespace
is recommended but not required
- index markers are optional, it's possible (and potentially useful) to mix
elements with index markers and elements without index markers, and it's
possible (but probaly less useful) to mix lines with index markers and
lines without index markers (here we require index markers for lines
and disallow them for elements)
- index markers must be 2 or 3 or 4 chars long and consist of either
only lowercase letters (lowercase index marker) or only digits
(digit index marker), it's possible (but maybe barely useful) to
mix the 2 types (here we don't support digit index markers at all,
and limit lowercase index markers to 2 or 3 chars)
- if digit index markers are used then they must match the index numbers for
both lines and columns, ie a digit index marker inside [[...]] and ((...))
is optional but cannot hold a value different from what it would be
anyway based on ZERO-based counting (here we don't support digit
index markers at all)
- if y-index markers are used then they must be sorted, with a privileged role
for 1 entry at the beginning and 1 entry at the end of the table that
are guaranteed to be found even if they are misplaced (here we
require y-index markers, sorting rule holds)
- redundant whitespace is not a problem as long as "maxwidth" is not exceeded
(this applies also to the beginning of the table) and no inline whitespace
(TAB or SPACE) follows EOL whitespace (ASCII 0...8 and 10...31),
this applies both to table lines and empty lines, ie an EOL
must be followed by either EOL or a table line (ie [[...]] or ((...))
or raw table element data)
- an empty table not containing any lines is valid as long as whitespace
rules are observed, this means EOL's are tolerable while inline whitespace
is not (here we require at least 1 line)
- a table line may not be empty, there must be at least 1 element
(note that allowing empty lines would cause inconsistencies between
lines with [[...]] and those without it)
- truncated table lines, ie lines shorter than other lines are tolerable, they
can end with element data or inline whitespace following element data, but
not with a comma ","
- a table element may not empty, dash "-" is the recommended filler for
dummy elements, or ((...)) can be used to "jump" over columns, even an
x-index marker ((...)) must be followed by at least one char of table
data (here we don't support x-index markers at all)
- a table element may not contain the string "=", if this string is found it
is translated to "-", the string "=" is reserved to indicate "not found or
error" (this rule holds even if alternative output string is requested)
Strategy:
- we support only lowercase y-indexing, not digit, the incoming
requested y-index string must be a valid language code (checked
by "lfivalidatelnkoadv", note that the table that we read from is
checked too, namely separately by module "mbllingvoj" or "mtblbahasa")
- the incoming requested x-index number must be 0 ... 10 (checked)
- we support only index marker for "y" and expect [[...]] in every line
- we support only counting for "x" and expect ((...)) not to occur
- we give a f**k in UTF8 and consider the table to be an array of octets
- for "y" indexing we apply a mixed strategy of linear forward and backward
search with step 2 and binary search
- for "y" indexing we begin with checking 0th entry, then last entry, then
continue with binary search, and switch back to linear search as soon as
the remaining size becomes dangerously low
- for "x" indexing we perform a linear forward search with step 1
- we give a f**k in closing "]]" and compare only opening "[["
and 2 or 3 chars
Special rule about enclosing of elements written with
non-latin scripts (rl-lr-enclosement):
- non-ASCII, non-latin and even RTL (right-to-left) scripts are permitted
in the table
- a table element longer than 2 Octet:s may be enclosed in "rl " and " lr"
strings on both sides, this is useful since many editors would otherwise
break the element order if an RTL script is used
- by default the enclosing strings are stripped off, but an optional
parameter "rel=0" can disable this for forward requests with ordinary
x-indexes (0...10), not valid for special value "L"
Usage examples with results / Ekzemploj de uzo
kun rezultoj / Contoh penggunaan dengan hasil:
(assuming that the huge table seized via "mw.loadData" contains the
line "[[id]] indonezia , Q9240 , bahasa Indonesia , 1 , id , i
nd , - , 22 , Indonezia lingvo , Kategori:Bahasa Esperanto , 100" at
the top, as well as lines for y-index "hy" with "rl ......... lr " and for
y-index "sv" with "[[sv]]sveda" (missing space, but works nevertheless),
but no line for "zzz", x-indexes: c0:nama c1:Q c2:autonym c3:sta c4:id
c5:ind c6:subdomain c7:avail c8:pedia-art c9:ali-kat c10:jumlah)
{{hr3}} <!-------------------------------->
* #T00 {mpiktbllki|ek} (bad use: obligatory params missing, 0 given)
* expected result: "="
* actual result: "{{#invoke:mpiktbllki|ek}}"
::* #T01 {mpiktbllki|ek|eo} (bad use: obligatory params missing, only 1 given and no "bin=1")
::* expected result: "="
::* actual result: "{{#invoke:mpiktbllki|ek|eo}}"
* #T02 {mpiktbllki|ek|err=fatal error} (bad use: obligatory params missing, 0 given, "err=" param used)
* expected result: "fatal error"
* actual result: "{{#invoke:mpiktbllki|ek|err=fatal error}}"
::* #T03 {mpiktbllki|ek|id|0} (simplest example, /c0/, ZERO'th entry by y-index)
::* expected result: "indonezia"
::* actual result: "{{#invoke:mpiktbllki|ek|id|0}}"
* #T04 {mpiktbllki|ek|sv|0} (simplest example, /c0/, later entry by y-index)
* expected result: "sveda"
* actual result: "{{#invoke:mpiktbllki|ek|sv|0}}"
{{hr3}} <!-------------------------------->
* #T10 {mpiktbllki|ek|hy|2} (/c2/ autonym, strip rl lr by default)
* expected result: .......
* actual result: "{{#invoke:mpiktbllki|ek|hy|2}}"
::* #T11 {mpiktbllki|ek|hy|2|rel=0} (/c2/ autonym, keep rl lr per "rel=0")
::* expected result: "rl "......." lr"
::* actual result: "{{#invoke:mpiktbllki|ek|hy|2|rel=0}}"
* #T12 {mpiktbllki|ek|hy|2|rel=1} (/c2/ autonym, strip rl lr per redundant "rel=1")
* expected result: .......
* actual result: "{{#invoke:mpiktbllki|ek|hy|2|rel=1}}"
::* #T13 {mpiktbllki|ek|hy|9} (/c9/ ali-kat, strip rl lr by default)
::* expected result: .......
::* actual result: "{{#invoke:mpiktbllki|ek|hy|9}}"
* #T14 {mpiktbllki|ek|hy|9|rel=0} (/c9/ ali-kat, keep rl lr per "rel=0")
* expected result: "rl "............" lr"
* actual result: "{{#invoke:mpiktbllki|ek|hy|9|rel=0}}"
::* #T15 {mpiktbllki|ek|hy|9|rel=1} (/c9/ ali-kat, strip rl lr per redundant "rel=1")
::* expected result: ............
::* actual result: "{{#invoke:mpiktbllki|ek|hy|9|rel=1}}"
{{hr3}} <!-------------------------------->
* #T20 {mpiktbllki|ek|id|3} (/c3/ status)
* expected result: "1"
* actual result: "{{#invoke:mpiktbllki|ek|id|3}}"
::* #T21 {mpiktbllki|ek|id|5} (/c5/ 3-letter ISO 639-3)
::* expected result: "ind"
::* actual result: "{{#invoke:mpiktbllki|ek|id|5}}"
* #T22 {mpiktbllki|ek|id|6} (/c6/ subdomain, keep found "-")
* expected result: "-"
* actual result: "{{#invoke:mpiktbllki|ek|id|6}}"
::* #T23 {mpiktbllki|ek|id|6|rel=1|alt=N/A} (/c6/ subdomain, replace found "-" by "N/A")
::* expected result: "N/A"
::* actual result: "{{#invoke:mpiktbllki|ek|id|6|rel=1|alt=N/A}}"
* #T24 {mpiktbllki|ek|id|10} (/c10/ jumlah)
* expected result: "100" (likely to deviate in practice)
* actual result: "{{#invoke:mpiktbllki|ek|id|10}}"
::* #T25 {#invoke:mpiktbllki|ek|zzz|3} (/c3/ but unknown y-index "zzz")
::* expected result: "="
::* actual result: "{{#invoke:mpiktbllki|ek|zzz|3}}"
* #T26 {#invoke:mpiktbllki|ek|zzz|3|err=bugger} (/c3/ but unknown y-index "zzz", "err=" param used)
* expected result: "bugger"
* actual result: "{{#invoke:mpiktbllki|ek|zzz|3|err=bugger}}"
{{hr3}} <!-------------------------------->
* #T30 {#invoke:mpiktbllki|ek|id|11} (invalid x-index "11", NOT found, max is decimal "10")
* expected result: "="
* actual result: "{{#invoke:mpiktbllki|ek|id|11}}"
::* #T31 {#invoke:mpiktbllki|ek|id|A} (invalid x-index "A", NOT found, max is decimal "10")
::* expected result: "="
::* actual result: "{{#invoke:mpiktbllki|ek|id|A}}"
* #T32 {#invoke:mpiktbllki|ek|id|A|rel=1} (invalid x-index "A", "rel=" has no effect)
* expected result: "="
* actual result: "{{#invoke:mpiktbllki|ek|id|A|rel=1}}"
::* #T33 {#invoke:mpiktbllki|ek|id|A|err=bugger} (invalid x-index "A", "err=" param)
::* expected result: "bugger"
::* actual result: "{{#invoke:mpiktbllki|ek|id|A|err=bugger}}"
{{hr3}} <!-------------------------------->
* #T40 {mpiktbllki|ek|grc|bin=1} (binary request, only y-index, assuming that "grc" exists)
* expected result: "1"
* actual result: "{{#invoke:mpiktbllki|ek|grc|bin=1}}"
::* #T41 {mpiktbllki|ek|xxx|bin=1} (binary request, only y-index, assuming that "xxx" does not exist)
::* expected result: "0"
::* actual result: "{{#invoke:mpiktbllki|ek|xxx|bin=1}}"
* #T42 {mpiktbllki|ek|id|L} (complete line, remove excessive whitespace)
* expected result: <nowiki> "[[id]] indonezia , Q9240 , rl bahasa Indo
nesia lr , 1 , id , ind , - , - , Ind
onezia lingvo , Kategori:Bahasa Esperanto , 100" </nowiki> (likely to deviate in practice)
* actual result via debu: "{{debu|{{#invoke:mpiktbllki|ek|id|L}}|outctl=0020}}"
::* #T43 {mpiktbllki|ek|xxx|L} (complete line, assuming that "xxx" does not exist)
::* expected result: "="
::* actual result: "{{#invoke:mpiktbllki|ek|xxx|L}}"
* #T44 {mpiktbllki|ek|xxx|L|detrc=true} (complete line, assuming that "xxx" does not exist, "detrc=true")
* expected result: long text followed by the short shameful verdict "="
* actual result: "{{#invoke:mpiktbllki|ek|xxx|L|detrc=true}}"
{{hr3}} <!-------------------------------->
* #T50 {mpiktbllki|ek|sveda|R} (reverse query, assuming that "sv" <-> "sveda" exists)
* expected result: "sv"
* actual result: "{{#invoke:mpiktbllki|ek|sveda|R}}"
::* #T51 {mpiktbllki|ek|Sveda|R|err=nope} (reverse query, assuming that "sv" <-> "sveda" exists, but wrong case, NOT found)
::* expected result: "nope"
::* actual result: "{{#invoke:mpiktbllki|ek|Sveda|R|err=nope}}"
* #T52 {mpiktbllki|ek|sveda|R|bin=1} (reverse query, binary, assuming that "sv" <-> "sveda" exists, found)
* expected result: "1"
* actual result: "{{#invoke:mpiktbllki|ek|sveda|R|bin=1}}"
::* #T53 {mpiktbllki|ek|Sveda|R|bin=1} (reverse query, binary, assuming that "sv" <-> "sveda" exists, but wrong case, NOT found)
::* expected result: "0"
::* actual result: "{{#invoke:mpiktbllki|ek|Sveda|R|bin=1}}"
{{hr3}} <!-------------------------------->
* #T60 {mpiktbllki|ek|Q9240|X} (extra query, assuming that "id" <-> "Q9240" exists, found)
* expected result: "id"
* actual result: "{{#invoke:mpiktbllki|ek|Q9240|X}}"
{{hr3}} <!-------------------------------->
* note that test #T42 depends on "debu"
* note that test #T42 cannot be reasonably executed on the docs subpage without help of "pate" or "debu"
{{hr3}} <!-------------------------------->
Note that output from this module when sent to screen directly as wikitext
will be subject to partial wiki parsing and full HTML parsing. This will
result in "[[id]" turned into a wikilink and in whitespace reduction. It
is not possible to call a module between "<pre>". In order to test this
module more thoroughly the output can be fed into another module ("debu"
or "pate") that analyzes the string and diplays ASCII codes or similar.
]===]
local exporttable = {}
------------------------------------------------------------------------
---- CONSTANTS [O] ----
------------------------------------------------------------------------
-- uncommentable EO vs ID constant strings (core site-related features)
local construsmo = "Modulo:loaddata-tbllingvoj" -- EO
-- local construsmo = "Modul:mtblbahasa" -- ID
-- constant table translating requested x-indexes and defining maximum
-- valid indexes 0...10 covering totally 10 columns /c0/.../c10/
local contabrxi = {[0]=0,1,2,3,4,5,6,7,8,9,10}
-- constant table -- ban list -- add obviously invalid access codes (2-letter or 3-letter) only
-- length of the list is NOT stored anywhere, the processing stops
-- when type "nil" is encountered, used by "lfivalidatelnkoadv" only
-- "en.wiktionary.org/wiki/Wiktionary:Language_treatment" excluded languages
-- "en.wikipedia.org/wiki/Spurious_languages"
-- "iso639-3.sil.org/code/art" only valid in ISO 639-2
-- "iso639-3.sil.org/code/zxx" "No linguistic content"
local contabisbanned = {}
contabisbanned = {'by','dc','ll','jp','art','deu','eng','epo','fra','gem','ger','ido','lat','por','rus','spa','swe','tup','zxx'} -- 1...20
-- constants to control behaviour from source AKA semi-hardcoded parameters
local conbookodlng = false -- "true" to allow long codes like "zh-min-nan"
local conboomiddig = false -- "true" to allow middle digit "s7a"
------------------------------------------------------------------------
---- SPECIAL STUFF OUTSIDE MAIN [B] ----
------------------------------------------------------------------------
-- SPECIAL VAR:S --
local qtbllingbaha = {} -- from submodule type "table" but metaized up to 11 e
local qbooguard = false -- only for the guard test, pass to other var ASAP
local qboodetrc = true -- from "detrc=true" but default is "true" !!!
local qstrtrace = "" -- for main & sub:s, debug report request by "detrc="
-- GUARD AGAINST INTERNAL ERROR & ONE IMPOR VIA LOADDATA HUGE SRC TABLE --
if (type(construsmo)~="string") then
qbooguard = true
else
qtbllingbaha = mw.loadData(construsmo) -- can crash here despite guarding ??
if (type(qtbllingbaha)~='table') then
qbooguard = true
end--if
end--if
------------------------------------------------------------------------
---- DEBUG FUNCTIONS [D] ----
------------------------------------------------------------------------
-- Local function LFTRACEMSG
-- for variables the other sub "lfdshowvar" is preferable but in exceptional
-- cases it can be justified to send text containing variables to this sub
-- enhances upvalue "qstrtrace" (may NOT be type "nil" on entry)
-- uses upvalue "qboodetrc"
local function lftracemsg (strbigcrap)
if (qboodetrc) then
qstrtrace = qstrtrace .. "<br>" .. strbigcrap .. '.'
end--if
end--function lftracemsg
------------------------------------------------------------------------
---- NUMBER CONVERSION FUNCTIONS [N] ----
------------------------------------------------------------------------
-- Local function LFDEC1DIGIT
-- Convert 1 decimal digit to integer 0...9 (255 if invalid).
local function lfdec1digit (num1digit)
num1digit = num1digit - 48 -- may become invalid
if ((num1digit<0) or (num1digit>9)) then
num1digit = 255
end--if
return num1digit
end--function lfdec1digit
------------------------------------------------------------------------
-- Local function LFNSTR12DIG2INT
-- Convert string with either 1 or 2 decimal ASCII digit:s
-- to integer 0...99 (255 if invalid).
-- Depends on functions :
-- [N] lfdec1digit
local function lfnstr12dig2int (strmasuk)
local numleeng = 0
local numletf = 255 -- preASSume guilt
local numrigt = 0
numleeng = string.len (strmasuk)
if ((numleeng==1) or (numleeng==2)) then
numletf = string.byte (strmasuk,1,1)
numletf = lfdec1digit (numletf) -- 255 if invalid, ZERO would be valid
end--if
if ((numletf~=255) and (numleeng==2)) then
numrigt = string.byte (strmasuk,2,2)
numrigt = lfdec1digit (numrigt) -- 255 if invalid, ZERO would be valid
if (numrigt==255) then
numletf = 255 -- 255 is invalid, note that ZERO would be valid
else
numletf = numletf * 10 + numrigt -- valid integer number 0...99 now
end--if
end--if
return numletf
end--function lfnstr12dig2int
------------------------------------------------------------------------
---- LOW LEVEL STRING FUNCTIONS [G] ----
------------------------------------------------------------------------
-- 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 lowercase letter, return bool
local function lfgtestlc (numcode)
local boolowerc = false
boolowerc = ((numcode>=97) and (numcode<=122))
return boolowerc
end--function lfgtestlc
------------------------------------------------------------------------
-- Local function LFCOUNTNDG
-- Count occurrences of non-digits (from a customizable set) in a string.
-- Tolerable char:s that do not count are:
-- * digits "0"..."9"
-- * maybe apo for (trictl=1) or (trictl=2)
-- * maybe space for (trictl=2)
-- Depends on functions :
-- [G] lfgtestnum
local function lfcountndg (strzzz,trictl)
local numjrezalt = 0 -- number of non-digits
local numcair = 0
local numjukuran = 0
local numjindxe = 0 -- ZERO-based
numjukuran = string.len(strzzz)
while true do
if (numjindxe==numjukuran) then
break
end--if
numcair = string.byte(strzzz,(numjindxe+1),(numjindxe+1))
if ((numcair==39) and (trictl~=0)) then
numcair = 48 -- apo OK
end--if
if ((numcair==32) and (trictl==2)) then
numcair = 48 -- space OK
end--if
if (not lfgtestnum(numcair)) then
numjrezalt = numjrezalt + 1
end--if
numjindxe = numjindxe + 1
end--while
return numjrezalt
end--function lfcountndg
------------------------------------------------------------------------
---- HIGH LEVEL STRING FUNCTIONS [I] ----
------------------------------------------------------------------------
-- Local function LFIVALIDATELNKOADV
-- Advanced test whether a string (intended to be a language code) is valid
-- containing only 2 or 3 lowercase letters, or 2...10 char:s and with some
-- dashes, or maybe a digit in middle position or maybe instead equals to "-"
-- or "??" and maybe additionally is not included on the ban list.
-- Input : * strqooq -- string (empty is useless and returns
-- "true" ie "bad" but cannot cause any major harm)
-- * booyesdsh -- "true" to allow special code dash "-"
-- * booyesqst -- "true" to allow special code doublequest "??"
-- * booloonkg -- "true" to allow long codes such as "zh-min-nan"
-- * boodigit -- "true" to allow digit in middle position
-- * boonoban -- (inverted) "true" to skip test against ban table
-- Output : * booisvaladv -- true if string is valid
-- Depends on functions :
-- [G] lfgtestnum lfgtestlc
-- Depends on constants :
-- * table "contabisbanned"
-- Incoming empty string is safe but type "nil" is NOT.
-- Digit is tolerable only ("and" applies):
-- * if boodigit is "true"
-- * if length is 3 char:s
-- * in middle position
-- Dashes are tolerable (except in special code "-") only ("and" applies):
-- * if length is at least 4 char:s (if this is permitted at all)
-- * in inner positions
-- * NOT adjacent
-- * maximally TWO totally
-- There may be maximally 3 adjacent letters, this makes at least ONE dash
-- obligatory for length 4...7, and TWO dashes for length 8...10.
local function lfivalidatelnkoadv (strqooq, booyesdsh, booyesqst, booloonkg, boodigit, boonoban)
local varomongkosong = 0 -- for check against the ban list
local numchiiar = 0
local numukurran = 0
local numindeex = 0 -- ZERO-based -- two loops
local numadjlet = 0 -- number of adjacent letters (max 3)
local numadjdsh = 0 -- number of adjacent dashes (max 1)
local numtotdsh = 0 -- total number of dashes (max 2)
local booislclc = false
local booisdigi = false
local booisdash = false
local booisvaladv = true -- preASSume innocence -- later final verdict here
while true do -- fake (outer) loop
if (strqooq=="-") then
booisvaladv = booyesdsh
break -- to join mark -- good or bad
end--if
if (strqooq=="??") then
booisvaladv = booyesqst
break -- to join mark -- good or bad
end--if
numukurran = string.len (strqooq)
if ((numukurran<2) or (numukurran>10)) then
booisvaladv = false
break -- to join mark -- evil
end--if
if (not booloonkg and (numukurran>3)) then
booisvaladv = false
break -- to join mark -- evil
end--if
numindeex = 0
while true do -- inner genuine loop over char:s
if (numindeex>=numukurran) then
break -- done -- good
end--if
numchiiar = string.byte (strqooq,(numindeex+1),(numindeex+1))
booisdash = (numchiiar==45)
booisdigi = lfgtestnum(numchiiar)
booislclc = lfgtestlc(numchiiar)
if (not (booislclc or booisdigi or booisdash)) then
booisvaladv = false
break -- to join mark -- inherently bad char
end--if
if (booislclc) then
numadjlet = numadjlet + 1
else
numadjlet = 0
end--if
if (booisdigi and ((numukurran~=3) or (numindeex~=1) or (not boodigit))) then
booisvaladv = false
break -- to join mark -- illegal digit
end--if
if (booisdash) then
if ((numukurran<4) or (numindeex==0) or ((numindeex+1)==numukurran)) then
booisvaladv = false
break -- to join mark -- illegal dash
end--if
numadjdsh = numadjdsh + 1
numtotdsh = numtotdsh + 1 -- total
else
numadjdsh = 0 -- do NOT zeroize the total !!!
end--if
if ((numadjlet>3) or (numadjdsh>1) or (numtotdsh>2)) then
booisvaladv = false
break -- to join mark -- evil
end--if
numindeex = numindeex + 1 -- ZERO-based
end--while -- inner genuine loop over char:s
if (not boonoban) then -- if "yesban" then
numindeex = 0
while true do -- lower inner genuine loop
varomongkosong = contabisbanned[numindeex+1] -- number of elem unknown
if (type(varomongkosong)~="string") then
break -- abort inner loop (then outer fake loop) due to end of table
end--if
numukurran = string.len (varomongkosong)
if ((numukurran<2) or (numukurran>3)) then
break -- abort inner loop (then outer fake loop) due to faulty table
end--if
if (strqooq==varomongkosong) then
booisvaladv = false
break -- abort inner loop (then outer fake loop) due to violation
end--if
numindeex = numindeex + 1 -- ZERO-based
end--while -- lower inner genuine loop
end--if (not boonoban) then
break -- finally to join mark
end--while -- fake loop -- join mark
return booisvaladv
end--function lfivalidatelnkoadv
------------------------------------------------------------------------
-- Local function LFHRLSTRIP
-- Strip "rl .. lr" if it is present and string length is at least 8 octet:s.
local function lfhrlstrip (strrlinut)
local numsoct = 0
local numsodt = 0
local numsoet = 0
local numsoft = 0
local numsogt = 0
local numsoht = 0
local numlaengd = 0
numlaengd = string.len(strrlinut)
if (numlaengd>=8) then -- at least 2 Octet:s length "rl .. lr" after strip
numsoct = string.byte(strrlinut,1,1)
numsodt = string.byte(strrlinut,2,2)
numsoet = string.byte(strrlinut,3,3)
numsoft = string.byte(strrlinut,(numlaengd-2),(numlaengd-2))
numsogt = string.byte(strrlinut,(numlaengd-1),(numlaengd-1))
numsoht = string.byte(strrlinut,(numlaengd ),(numlaengd ))
if ((numsoct==114) and (numsodt==108) and (numsoet==32) and (numsoft==32) and (numsogt==108) and (numsoht==114)) then
strrlinut = string.sub(strrlinut,4,(numlaengd-3)) -- stri off 3+3 char:s
end--if
end--if
return strrlinut
end--function lfhrlstrip
------------------------------------------------------------------------
-- Local function LFHPICKCSV
-- This is done in 3 steps:
-- * skip possible unsuitable elements
-- * skip possible whitespace preceding the searched element
-- * copy the searched element (takes a char from previous step)
-- this is a copy of module "mpiksubstrind" with minimal modifications
local function lfhpickcsv (strcsvline, numxindex)
local strelemento = ''
local numypos = 1 -- ONE-based
local numlymyt = 0
local numocct = 0
local bootymp = false
local boospc = false -- flag for whitespace reduction feature
local boouch = false -- flag for found useful char when skipping element
numlymyt = string.len(strcsvline)
while true do -- iterate through elements in order to skip them
if (numxindex==0) then -- nothing to skip anymore
bootymp = true
break -- exit the outer loop, nothing to skip anymore
end--if
numxindex = numxindex - 1
bootymp = false
boouch = false
while true do -- iterate through whspc & chars mix looking for comma
if (numypos>=numlymyt) then
break -- exit the inner loop, NOT found, give up
end--if
numypos = numypos + 1
numocct = string.byte (strcsvline,numypos,numypos)
if ((numocct<32) and (numocct~=9)) then
break -- EOL: exit the inner loop, NOT found, give up
end--if
if ((numocct>32) and (numocct~=44)) then
boouch = true -- found a valid char (empty field is an error)
end--if
if (numocct==44) then
if (boouch) then
bootymp = true -- field was not empty
end--if
break -- exit the inner loop, found a comma, this is good or bad
end--if
end--while
if (not bootymp) then
break -- exit the outer loop, NOT found or empty field, give up
end--if
end--while
if (bootymp) then
bootymp = false
while true do -- iterate through chars skipping whitespace
if (numypos>=numlymyt) then
break -- exit the loop, NOT found, give up
end--if
numypos = numypos + 1
numocct = string.byte (strcsvline,numypos,numypos)
if ((numocct<32) and (numocct~=9)) then
break -- EOL: exit the loop, NOT found, give up
end--if
if (numocct>32) then
if (numocct==44) then
break -- exit loop, found comma, give up according to rules
end--if
bootymp = true
break -- exit the loop, found valid char, start copying now
end--if
end--while
end--if
if (bootymp) then
while true do -- iterate through chars copying the found element
if ((numocct==32) or (numocct==9)) then
boospc=true
else
if (boospc) then
strelemento = strelemento .. string.char (32,numocct)
boospc = false
else
strelemento = strelemento .. string.char (numocct)
end--if
end--if
if (numypos>=numlymyt) then -- "strelemento" was preassigned to empty
break -- done
end--if
numypos = numypos + 1
numocct = string.byte (strcsvline,numypos,numypos)
if ((numocct<32) and (numocct~=9)) then
break -- EOL: exit the loop, done
end--if
if (numocct==44) then
break -- comma: exit the loop, done
end--if
end--while
end--if
if (not bootymp) then
strelemento = ''
end--if
return strelemento
end--function lfhpickcsv
------------------------------------------------------------------------
---- VARIABLES [R] ----
------------------------------------------------------------------------
function exporttable.ek (arxframent)
-- general unknown type
local vartmp = 0 -- variable without type
-- special type "args"
local arxourown = 0 -- metaized "args" from our own "frame" (NOT caller's)
-- general str (cool "qstrtrace" declared separately outside main)
local strcy = '' -- for reverse query only, is NOT equal "str1anon"
local strkomline = ''
local strret = '' -- output string
local strtump = ''
-- stuff from "args" (cool "qboodetrc" declared separately outside main)
local str1anon = '' -- y-index from args[1]
local num2anon = 255 -- x-index from args[2] (0...10 111 177 233 237)
local boobin = false
local boorel = true -- flag from "rel=1" for stripping rl-lr-enclosement
local stralt = "-" -- alternative string to replace "-" literal fr table
local sterr = "=" -- default or alterna string to replace "=" on error
-- stuff from incoming table
local num0statcode = 0
local num1lenfullo = 0
-- local num2lenstrip = 0
-- local num3errposit = 0
-- local num4lineslin = 0
-- local str5errorstr = ''
-- local str6errorstr = ''
-- local str7errorstr = ''
-- local tab10enume = {} -- obligatory but we don't use it here
local tab11forward = {} -- obligatory
local tab12reverse = {} -- optional
local tab13extra = {} -- optional
-- general num
local numoct = 0 -- temp
local numlong = 0 -- temp for parameter evaluation
-- general boo
local booerr = false -- overall error flag
local bootimp = false -- temp
------------------------------------------------------------------------
---- MAIN [Z] ----
------------------------------------------------------------------------
---- GUARD AGAINST INTERNAL ERROR AGAIN ----
booerr = qbooguard
lftracemsg ('This is "mpiktbllki", requested "detrc" report')
lftracemsg ('Const "conbookodlng" is "' .. tostring(conbookodlng) .. '"')
lftracemsg ('Const "conboomiddig" is "' .. tostring(conboomiddig) .. '"')
lftracemsg ('Var "booerr" is "' .. tostring(booerr) .. '" so far')
---- GATHER LESS THAN 11 ITEMS FROM THE HUGE TABLE AND PRECHECK ----
-- we do NOT have "nummaxwidth" yet !!!FIXME!!!
-- spec allows 32 ... 8'000'000 but here we restrict to 320...1'000'000
while true do -- fake loop
if (booerr) then
break -- to join mark
end--if
num0statcode = qtbllingbaha[2]
if (num0statcode~=0) then
lftracemsg ("Submodule failed with error code " .. tostring (num0statcode))
booerr = true
break -- to join mark
end--if
num1lenfullo = qtbllingbaha[3]
if ((num1lenfullo>=320) and (num1lenfullo<=1000000)) then
lftracemsg ("Passed 320...1'000'000 check with length " .. tostring (num1lenfullo))
else
lftracemsg ("Failed 320...1'000'000 check with length " .. tostring (num1lenfullo))
booerr = true
break -- to join mark
end--if
tab11forward = qtbllingbaha['T77'] -- ultimately obligatory
if (type(tab11forward)~='table') then -- important check
lftracemsg ("Submodule failed to deliver obligatory [T77]")
booerr = true
break -- to join mark
end--if
tab12reverse = qtbllingbaha['T80'] -- optional
if (type(tab12reverse)~='table') then -- important check
tab12reverse = {} -- replace by empty table
lftracemsg ("Submodule failed to deliver optional [T80] reverse")
end--if
tab13extra = qtbllingbaha['T81-1'] -- optional
if (type(tab13extra)~='table') then -- important check
tab13extra = {} -- replace by empty table
lftracemsg ("Submodule failed to deliver optional [T81-1] extra")
end--if
break -- finally to join mark
end--while -- fake loop -- join mark
---- SEIZE 1 OR 2 ANONYMOUS PARAMS (1 OBLIGATORY PLUS 1 OPTINOAL) ----
-- y-index string from arxourown[1] is "str1anon"
-- here y-index is checked very preliminarily only
-- x-index string or special value from arxourown[2] is integer "num2anon"
-- (0...10, special 111, 177, 233, 237, invalid 255)
-- here we access "contabrxi" (x-translation)
arxourown = arxframent.args -- "args" from our own "frame"
str1anon = '' -- preassume not given (but it's obligatory)
num2anon = 255 -- preassume not given (maybe can live without it)
if (not booerr) then
vartmp = arxourown[1] -- requested y-index
if (type(vartmp)=='string') then
numlong = string.len (vartmp)
if ((numlong>0) and (numlong<100)) then
str1anon = vartmp -- preliminarily accepted
else
lftracemsg ('Requested y-index is blatantly invalid')
booerr = true
end--if
else
lftracemsg ('No y-index')
booerr = true
end--if
end--if
if (not booerr) then
vartmp = arxourown[2] -- x-index or special
if (type(vartmp)=='string') then
numlong = string.len (vartmp)
if ((numlong>0) and (numlong<100)) then
strtump = vartmp -- preliminarily accepted
if (numlong==1) then
numoct = string.byte (strtump,1,1)
if (numoct==76) then
num2anon = 177 -- special "L" (complete line)
end--if
if (numoct==82) then
num2anon = 233 -- special "R" (reverse query)
end--if
if (numoct==88) then
num2anon = 237 -- special "X" (extra query)
end--if
end--if
if ((num2anon==255) and ((numlong==1) or (numlong==2))) then
numoct = lfnstr12dig2int (strtump) -- 255 if invalid
vartmp = contabrxi [numoct] -- risk of type "nil"
lftracemsg ('Translated requested x-index from "' .. strtump .. '" to "' .. tostring(vartmp) .. '"')
if (type(vartmp)=="number") then
num2anon = vartmp -- otherwise keep the preassigned 255
end--if
end--if
if (num2anon==255) then
lftracemsg ('Requested x-index "' .. strtump .. '" is invalid') -- NOT "vartmp" !!!
booerr = true
end--if
else
lftracemsg ('Requested x-index is blatantly invalid')
booerr = true
end--if
else
lftracemsg ('No x-index')
end--if
end--if
---- SEIZE 3 OF 5 NAMED AND OPTIONAL PARAMETERS ----
if (not booerr) then
vartmp = arxourown["bin"] or "0" -- default is "false"
boobin = (vartmp=="1")
bootimp = (vartmp=="0")
if (not (boobin or bootimp)) then
lftracemsg ('Invalid parameter "bin="')
booerr = true
end--if
if (boobin) then
lftracemsg ('Parameter "bin=1" seized') -- silent for "bin=0"
end--if
end--if
if (not booerr) then
vartmp = arxourown["rel"] or "1" -- default is "true"
boorel = (vartmp=="1")
bootimp = (vartmp=="0")
if (not (boorel or bootimp)) then
lftracemsg ('Invalid parameter "rel="')
booerr = true
end--if
if (not boorel) then
lftracemsg ('Parameter "rel=0" seized') -- silent for "rel=1"
end--if
end--if
if (not booerr) then
vartmp = arxourown["alt"] -- 1...64 char:s alt string no default
if (type(vartmp)=='string') then
numlong = string.len (vartmp)
if ((numlong<1) or (numlong>64)) then
lftracemsg ('Invalid parameter "alt="')
booerr = true
else
lftracemsg ('Parameter "alt=" seized')
stralt = vartmp -- default was "-"
end--if
end--if
end--if
---- CHECK PARAM CONSISTENCY ----
-- here we access "conbookodlng" and "conboomiddig"
if ((not booerr) and boobin) then -- "bin=1" here
if (num2anon==255) then
num2anon = 111 -- y-index only, parameter x-index not given
end--if
if ((num2anon~=111) and (num2anon~=233) and (num2anon~=237)) then
lftracemsg ('Forward search and "bin=1" exclude ordinary x-index and "L"')
booerr = true
end--if
end--if
if (not booerr) then
if ((not boobin) and (num2anon==255)) then
lftracemsg ('Without "bin=1" an x-index is required')
booerr = true
end--if
end--if
if (not booerr) then
if (num2anon>200) then -- must be done after 255->111 conversion
numlong = string.len (str1anon) -- reverse or extra query
if ((numlong<2) or (numlong>48)) then
lftracemsg ("Requested y-index has invalid length for reverse or extra query")
booerr = true -- not valid
end--if
else
if (not lfivalidatelnkoadv(str1anon,false,false,conbookodlng,conboomiddig,false)) then
lftracemsg ("Requested y-index is invalid for forward query, need language code")
booerr = true -- not valid language code
end--if
end--if
end--if
---- SEIZE NAMED PARAMETER "ERR" EVEN IF WE ALREADY SUCK ----
-- try to pick named param "err=" even if we already have "booerr==true"
-- 1...64 char:s alternative string to replace "="
vartmp = arxourown["err"] -- can be type "nil"
if (type(vartmp)=='string') then
numlong = string.len (vartmp)
if ((numlong<1) or (numlong>64)) then
lftracemsg ('Alterna string "err=" has invalid length')
booerr = true -- damn -- maybe redundant -- keep "sterr" as "="
else
sterr = vartmp -- was preassigned to "="
lftracemsg ('Alterna string "err=" seized')
end--if
end--if
---- SEIZE NAMED PARAMETER "DETRC" EVEN IF WE ALREADY SUCK ----
-- try to pick named param "detrc=" even if we already have an error
-- so far have collected to "qstrtrace" unconditionally, maybe shut up now
if (arxourown["detrc"]=="true") then
lftracemsg ('Param "detrc=true" seized')
else
qboodetrc = false -- was preassigned to "true"
qstrtrace = '' -- shut up now
end--if
lftracemsg ('All params done, "booerr" is "' .. tostring(booerr) .. '" so far')
---- PERFORM FORWARD OR REVERSE QUERY AS REQUESTED ----
-- this delivers either "strkomline" (forward, even "L") or
-- "strcy" (types "R" and "X")
if (not booerr) then
if (num2anon<200) then -- even for "L"
strkomline = tab11forward [str1anon] or "" -- protect against type "nil"
if (strkomline=='') then
lftracemsg ('Forward search for "' .. str1anon .. '" resulted in no hit')
booerr = true
else
lftracemsg ('Forward search for "' .. str1anon .. '" resulted in len=' .. tostring(string.len(strkomline)))
end--if
end--if
if (num2anon==233) then
strcy = tab12reverse [str1anon] or "" -- protect against type "nil"
if (strcy=='') then
lftracemsg ('Reverse search for "' .. str1anon .. '" resulted in no hit')
booerr = true
else
lftracemsg ('Reverse search for "' .. str1anon .. '" resulted in len=' .. tostring(string.len(strcy)))
end--if
end--if
if (num2anon==237) then
strcy = tab13extra [str1anon] or "" -- protect against type "nil"
if (strcy=='') then
lftracemsg ('Extra search for "' .. str1anon .. '" resulted in no hit')
booerr = true
else
lftracemsg ('Extra search for "' .. str1anon .. '" resulted in len=' .. tostring(string.len(strcy)))
end--if
end--if
end--if
---- RETURN ONE ELEMENT PICKED ACCORDING TO X-INDEX NUMBER ----
-- for forward query excessive whitespace already reduced in submodule
-- "num2anon" can be 0...10 whereas values > 100 are reserved:
-- * 111 forward search y-only query per "bin=1" while no "R" no "X"
-- * 177 complete line per "L"
if (num2anon<100) then
if (not booerr) then
do
local numa = 0
local numb = 0
numa = string.len(str1anon) + 5 -- ONE-based position after "]]"
numb = string.len(strkomline)
if (numa>numb) then
lftracemsg ('Failed to discard /cy/')
booerr = true -- should impossible to occur unless submodule broken
else
strkomline = string.sub(strkomline,numa,numb) -- discard /cy/ part
lftracemsg ('Discarded /cy/ before x-pick')
strret = lfhpickcsv (strkomline,num2anon) -- pick
lftracemsg ('After x-pick got "' .. strret .. '"')
booerr = (strret=='')
end--if
end--do
end--if
if (not booerr) then
if (boorel) then -- default is "true"
strret = lfhrlstrip (strret) -- strip
end--if
if (strret=='-') then
strret = stralt -- do this BEFORE "=" -> "-"
end--if
if (strret=='=') then
strret = '-' -- string "=" is prohibited, punishment is conversion to "-"
end--if
end--if
end--if
---- RETURN COMPLETE LINE OR RESULT OF REVERSE OR EXTRA QUERY ----
-- excessive whitespace from forward query already reduced in submodule
if ((not booerr) and (num2anon==177)) then -- x-index was "L"
strret = strkomline
end--if
if ((not booerr) and (num2anon>200)) then -- x-index was "R" or "X"
strret = strcy
end--if
---- RETURN BINARY DIGIT OR CARE ABOUT ERRORS ----
if (boobin) then -- "bin=1"
if (booerr) then
strret = "0" -- y-index NOT found or error
else
strret = "1" -- y-index found
end--if
else
if (booerr) then
strret = sterr -- string "strret" was preassigned to empty
end--if
end--if
---- RETURN THE JUNK STRING ----
if (qboodetrc) then
strret = "<br>" .. qstrtrace .. "<br><br>" .. strret
end--if
return strret
end--function exporttable.ek
---- RETURN THE JUNK LUA TABLE ----
return exporttable