模組:Var
local p={}
local lib_arg={}
local lib_str=mw.ustring
local yesno = require('Module:Yesno')
local main_template_name = "變數"
local module_call ="#invoke:Var"
local soft_subst_main = "Softsubst"
local messages,_L,lib_es,lib_tc,command_list = {
magic_space = '\127'..string.char( 0xC2, 0xA0 ),
strip_mark = "\127'\"`UNIQ--%s-%s-QINU`\"'\127",
strip_mark_pattern = "\127'\"`UNIQ%%-%%-%s%%-%s%%-QINU`\"'\127",
arg_global = '_arg_process',
cant_subst = '替換引用階段無法存取變數',
cat_subst_not_done = "未完成替換引用的頁面",
not_support_strip_warning_cmt = "<!--可能需要手動調整的擴展標籤-->",
not_support_strip_warning = "[[Template:softsubst]]警告:欲顯示替換引用原碼的模板中包含了擴展標籤,可能導致結果不準確,或替換引用失敗。",
do_subst = '<p class="notice metadata" id="spoiler" style="font-size: small">以下内容為[[WP:Subst|替換引用]]後的預期內容,請自行拷貝原始碼完成替換引用。</p><div style="clear: both; overflow: auto; border: 1px solid #cccccc; padding: 4px; text-align: left; background: transparency;">',
remove_hide_strip_mark = "<span%s+style%s*=%s*[\"\']%s*display%s*:%s*none%s*;?%s*[\"\']%s*>[^<]+UNIQ%-%-nowiki[^<]+<%s*/%s*span%s*>",
var_undefine = '變數 "%s" 未定義。',
NullPointerException = '[[NullPointerException|空指標]]錯誤'},{p=p},require("Module:EditState"),
require("Module:TrackingCategory"),{'none',
set = {'set', '設定', '設置'},
get = {'get', '取值','取', '取得'},
getconst = {'getconst'},
ref = {'ref', '取址'},
refget = {'refget', 'refgetname'},
hide = {'hide', '隱藏'},
subst = {'subst'},
call = {'call', 'callconst', '呼叫', '執行', '運行'},
hist = {'hist', '歷史'},
delete = {'del', 'delete', '刪除'},
new = {'new'},
};
local notsupport_strip = false
local no_color = false
local printf = lib_str.format
local sub = lib_str.sub
local gsub = lib_str.gsub
local trim = mw.text.trim
local split = mw.text.split
local function _test_cmd(cmd_names, test)
local result, trim_test = false, trim(lib_str.lower(test))
for i=1,#cmd_names do result = result or (trim_test == cmd_names[i]) end
return result
end
local function addWarning(msg)
return mw.addWarning(require('Module:Error').error{[1] = msg})
end
local function codeNowikiWithColor(frame, code_lang, text)
if no_color then return frame:extensionTag('nowiki',text) end
return frame:extensionTag('syntaxhighlight',text, {inline='', lang=code_lang})
end
local strip_code_color_map = {}
local ignore_strip_code = {
indicator = true,
h=true,
item=true
}
local function strip_code_color(frame, strip_code)
local strip_type = strip_code:lower()
if ignore_strip_code[strip_type] == true then return {'',''} end
if no_color then return {messages.not_support_strip_warning_cmt .. '<' .. strip_type .. '>', '</' .. strip_type .. '>'} end
local result = strip_code_color_map[strip_type]
if result then return result else
strip_code_color_map[strip_type] = {
codeNowikiWithColor(frame, 'xml', messages.not_support_strip_warning_cmt .. '<' .. strip_type .. '>'),
codeNowikiWithColor(frame, 'xml', '</' .. strip_type .. '>')
}
end
return strip_code_color_map[strip_type]
end
local function no_color_check(frame, text)
if no_color then return frame:extensionTag('pre',text) end
return text
end
local function out_new_line()
if no_color then return '\n' end
return tostring(mw.html.create( 'br' ))
end
local subst_pattern = "%s*[Ss][Uu][Bb][Ss][Tt]%s*:%s*"
local safesubst_pattern = "%s*[Ss][Aa][Ff][Ee][Ss][Uu][Bb][Ss][Tt]%s*:%s*"
local msg_pattern = "%s*[Mm][Ss][Gg]%s*:%s*"
local msgnw_pattern = "%s*[Mm][Ss][Gg][Nn][Ww]%s*:%s*"
--區域變數結尾
local _jsonEncode =require('Module:EncoderUtil')._jsonEncode
--函數本體
function p.Varfunc(frame, from_meta_table)
local args, working_frame = p._arg_process(frame)
if mw.isSubsting() then return
require('Module:Template invocation').invocation(string.format("%s|%s",module_call,'softSubst_msg'), args)
end
local command = args['1'] or args[1] or ''
if _test_cmd(command_list.set, command) or _test_cmd(command_list.new, command) or _test_cmd(command_list.delete, command) then
local m_mode = 'VAR'
if _test_cmd(command_list.delete, command) then m_mode = 'DELETE'
elseif _test_cmd(command_list.new, command) then m_mode = 'NEW' end
local call_args = {}
for key,val in pairs(args) do
local checker = tonumber(key)
if checker ~= 1 then call_args[key] = val end
end
return p.makeVar(call_args, m_mode, from_meta_table)
elseif _test_cmd(command_list.get, command) then
return p.getVar({args['2'] or args[2] or '', args['3'] or args[3],default=args.default}, 'value', false ,from_meta_table)
elseif _test_cmd(command_list.ref, command) then
return p.getVar({args['2'] or args[2] or ''}, 'addr', false ,from_meta_table)
elseif _test_cmd(command_list.getconst, command) then
return p.getVar({args['2'] or args[2] or ''}, 'value', true, from_meta_table)
elseif _test_cmd(command_list.refget, command) then
local addr = args['2'] or args[2] or ''
local result = p._getRefVarObj('VAR', addr)
local remappingTable = {refget = 'value', refgetname = 'name'}
if result then
if result[remappingTable[command]] then return result[remappingTable[command]] end
end
return mw.getCurrentFrame():expandTemplate{ title = 'Error', args = { messages.NullPointerException } }
elseif _test_cmd(command_list.hide, command) then
if trim(args['2'] or args[2] or '')~= '' then
working_frame:extensionTag('ref', args['2'] or args[2] or '', {group = 'UINQ-VARDEF-BLOCK-QINU'})
working_frame:extensionTag('references', '', {group = 'UINQ-VARDEF-BLOCK-QINU'})
end
return ''
elseif _test_cmd(command_list.subst, command) then
return p._softSubst({args['2'] or args[2] or ''})
elseif _test_cmd(command_list.call, command) then
return p.callVar(p._seek_arg(args, 1), command == 'callconst')
elseif _test_cmd(command_list.hist, command) then
return p.getVarHist(p._seek_arg(args, 1), from_meta_table)
end
return ''
end
p.Var={
set=function(i)local j=p._seek_arg(i,-1,true);for k,l in pairs(i)do j[k]=j[k]or l end j[1]='set';return p.Varfunc(j,true)end,
new=function(i)local j=p._seek_arg(i,-1,true);for k,l in pairs(i)do j[k]=j[k]or l end j[1]='new';return p.Varfunc(j,true)end,
delete=function(i)local j=p._seek_arg(i,-1,true);for k,l in pairs(i)do j[k]=j[k]or l end j[1]='delete';return p.Varfunc(j,true)end,
get=function(i)local j=p._seek_arg(i,-1,true);j[1]='get';return p.Varfunc(j,true)end,
getconst=function(i)local j=p._seek_arg(i,-1,true);j[1]='getconst';return p.Varfunc(j,true)end,
hist=function(i)local j=p._seek_arg(i,-1,true);j[1]='hist';return p.Varfunc(j,true)end,
call=function(i)local j=p._seek_arg(i,-1,true);j[1]='call';return p.Varfunc(j,true)end,
refget=function(i)local j=p._seek_arg(i,-1,true);j[1]='refget';return p.Varfunc(j,true)end,
refgetname=function(i)local j=p._seek_arg(i,-1,true);j[1]='refgetname';return p.Varfunc(j,true)end,
ref=function(i)local j=p._seek_arg(i,-1,true);j[1]='ref';return p.Varfunc(j,true)end,
vars=function(const)
local arg_table = p._getVars("VAR", const)
local restlt = {}
for key,val in pairs(arg_table) do
local get_result, check_json = mw.ustring.gsub(arg_table[key].value, "^%$JSON%$", '')
if check_json > 0 then
restlt[key] = mw.text.jsonDecode(get_result)
else
restlt[key] = get_result
end
end
return restlt
end
}
p.Var=setmetatable(p.Var, {
__index = function(t, k) return t.get({k})end,
__newindex = function(t, k, v)
local stored = t.set({[k]=v})
p.Varfunc({'hide',stored})
end
})
function p.makeVar(frame, mode, from_meta_table)
local varMode = mode or 'VAR'
if varMode == 'NEW' then varMode = 'VAR' end
if trim(varMode) == '' then varMode = 'VAR' end
local args, working_frame = p._arg_process(frame)
local out_text = function(out_mode,name,value)
return printf(messages.magic_space .. "$%s_DEF %s=%s" .. messages.magic_space, out_mode, name, value)
end
local body = ''
local new_body = ''
for key,val in pairs(args) do
local store_value = val
if from_meta_table == true then
if type(store_value)~=type('string')then store_value="$JSON$".._jsonEncode(store_value)end
end
if mode == 'DELETE' then body = body..out_text(varMode,store_value,store_value)..';'
else
if mode == 'NEW' then new_body = new_body..out_text('DELETE',key,key)..';' end
body = body..out_text(varMode,key,store_value)..';'
end
end
if mode == 'NEW' then new_body = working_frame:extensionTag('nowiki', new_body) end
body = new_body .. working_frame:extensionTag('nowiki', body)
return mw.text.tag( 'span', {style="display:none;"}, body )
end
function p.softSubst(frame)
local args, working_frame = p._arg_process(frame)
if mw.isSubsting() then return require('Module:Template invocation').invocation(soft_subst_main, args)end
local template_title = trim(args['1'] or args['1'] or '')
if template_title == '' then return '' end
return p.softSubst_msg(p._seek_arg(args, 1), template_title,
yesno(args['no cat']or args['no_cat']or args.nocat or args.NoCat or args.noCat or false))
end
local function check_is_main_doc(working_frame)
local checker = mw.ustring.lower(working_frame:preprocess( "{{BASEPAGENAME}}" ))
if checker == mw.ustring.lower(main_template_name) or
checker == mw.ustring.lower(soft_subst_main) or checker == 'var' then return true end
return false
end
function p.softSubst_msg(frame, template_title, without_cat)
local template_dis = template_title or main_template_name
local args, working_frame = p._arg_process(frame)
if mw.isSubsting() then return require('Module:Template invocation').invocation(string.format("%s|%s",module_call,'softSubst_msg'), args)end
local result = require('Module:Template invocation').invocation(template_dis, args)
if lib_es.isPreview() then
local pre_result = working_frame:preprocess(result)
if #(split(gsub(pre_result,'\r\n','\n'),'\n')) > 50 then no_color = true end
result = p._softSubst({working_frame:preprocess(result)})
if template_title == nil then
result = working_frame:expandTemplate{ title = 'Error', args = { messages.cant_subst } } .. result
end
if notsupport_strip==true then result = '<p>{{Error|' .. messages.not_support_strip_warning .. '}}</p>' .. result end
else
if (check_is_main_doc(working_frame) == false) and (not without_cat) then lib_tc.append(messages.cat_subst_not_done) end
end
if notsupport_strip==true then addWarning( messages.not_support_strip_warning ) end
return working_frame:preprocess(result)
end
function p._softSubst(frame)
local softSubst_data, softSubst_warp = 'arg_global', string.char(0x70)
if type(softSubst_data) ~= type({'table'}) then
--find method between global scope or local scope
softSubst_data = {(_G[softSubst_warp] or _L[softSubst_warp])[messages[softSubst_data]](frame)}
end
local without_cat = yesno(softSubst_data['no cat']or softSubst_data['no_cat']or softSubst_data['nocat']or softSubst_data['NoCat']or softSubst_data['noCat']or false)
--decode method
local first_data, second_data, third_data = softSubst_data['1'] or softSubst_data[1], softSubst_data['2'] or softSubst_data[2], (_G[softSubst_warp] or _L[softSubst_warp])["_code_getter_wiki"]
--2nd layer decode
first_data = first_data['1'] or first_data[1] or ''
--second_data = second_data['2'] or second_data[2] or ''
--third_data = third_data['3'] or third_data[3] or ''
if lib_es.isPreview() ~= true and (not without_cat) then
if (check_is_main_doc(second_data) == false) then lib_tc.append(messages.cat_subst_not_done) end
end
local fourth_data = function(msg_data)
local msg_data_list, result_code = split(msg_data, '\n'), ''
for i=1,#msg_data_list do result_code = result_code .. third_data(second_data, msg_data_list[i]) end
if no_color then result_code = no_color_check(second_data, result_code) end
return result_code
end
--foreach method do
if trim(first_data)~= '' then return
mw.clone(messages.do_subst) .. fourth_data(gsub(
gsub(first_data, messages.remove_hide_strip_mark, '')
, '\r\n', '\n')) .. '</div>'
end
return ''
end
function p.callVar(frame, const)
local args, working_frame = p._arg_process(frame)
local vars = p._getVars('VAR', const)
local var_name = args[1]or args['1']or''
local get_value = vars[var_name]
if tonumber(var_name) and not get_value then get_value = vars[tonumber(var_name)] end
if get_value then
local func_name = trim(mw.clone(get_value.value),"|\t\r\n\f ")
func_name = gsub(func_name,subst_pattern,'')
func_name = gsub(func_name,safesubst_pattern,'')
func_name = gsub(func_name,msg_pattern,'')
func_name = gsub(func_name,msgnw_pattern,'')
local tail_index = (lib_str.find(func_name,'|')or(lib_str.len(func_name)+1))-1
command_tail = sub(func_name,tail_index + 1,-1)
func_name = sub(func_name,1,tail_index)
local final_func_name = ''
--template:
local template_name = mw.title.new( func_name, 'Template' )
if template_name and template_name.exists then
final_func_name = template_name.fullText
if template_name.namespace == 0 then final_func_name = ':' .. final_func_name end
end
--int:
local template_split = split(func_name, ':') or {func_name}
if final_func_name=='' then
local check_mw = func_name
if #template_split > 1 and (sub(template_split[1],1,3) == 'int' or
(lib_str.find(template_split[1],"[Mm]edia[Ww]iki"))) then
check_mw = table.concat( template_split, ':', 2, #template_split )
end
if mw.message.new(check_mw):exists() then
final_func_name = 'int:' .. check_mw
end
end
--#...:
local fix_cs = false
if final_func_name=='' then
if xpcall(function()mw.getCurrentFrame():callParserFunction( func_name, func_name )end, function()end)
== true then
final_func_name = func_name
fix_cs = true
local parser_tail_check = sub(trim(final_func_name),-1)
if parser_tail_check ~= ':' and parser_tail_check ~= '|' then final_func_name = final_func_name .. ':' end
end
end
--may be magic word
if final_func_name=='' then
local checker, check_text = xpcall(function()
return mw.getCurrentFrame():preprocess( printf("{{%s}}", func_name) )
end, function()end)
local test_name = (template_name or { prefixedText = func_name }).prefixedText
if not lib_str.find(check_text or '', printf("^{{%s}}$", test_name) ) and
not lib_str.find(check_text or '', printf("^%%[%%[:%s%%]%%]$", test_name) ) then
final_func_name = func_name
end
end
if trim(final_func_name) ~= '' then
local num_args = p._seek_arg(args, 1)
local str_args = require('Module:Template invocation').invocation(final_func_name..command_tail, num_args)
if fix_cs == true and trim(command_tail) == '' and
sub(trim(final_func_name),-1) == ':' then
str_args = gsub(str_args, "^({{)%s*(" .. final_func_name .. ")|", "%1%2")
end
return working_frame:preprocess(str_args)
end
local max_arg = 0
local num_args = {}
for key,value in pairs( args ) do
local arg_id = tonumber(key or '')
if arg_id then
if arg_id > max_arg then max_arg = arg_id end
num_args[arg_id] = value
end
end
local call_args = {}
local get_obj = function(obj)return mw.text.jsonDecode(obj)end
if max_arg > 1 then
for i = 2,max_arg do
if num_args[i] then
local try_to_get_obj = mw.clone(num_args[i])
if not xpcall( function() --try
try_to_get_obj = get_obj(num_args[i])
end, function(msg)return msg end ) then --catch
call_args[i-1] = num_args[i]
else --finally
call_args[i-1] = try_to_get_obj
end
else call_args[i-1] = '' end
end
end
local func_path = split(func_name,'%.') or { [1]=func_name }
local func_body = mw[func_path[1]] or p[func_path[1]] or _G[func_path[1]]
if lib_str.find(func_path[1],':') then
func_body = require(func_path[1]) or func_body
end
if func_body then
local old_obj = func_body
for i=2,#func_path do
func_body = func_body[func_path[i]]
if func_body then
old_obj = func_body
else
return ''
end
end
local func_type = type( func_body )
local times = 10
for ti = 1,times do
if func_type == type(nil) then
return ''
elseif func_type == type(0) then
return '' .. func_body
elseif func_type == type(true) then
if func_body then return '1' end
return ''
elseif func_type == type(type) then
if max_arg > 1 then
func_body = func_body(unpack(call_args))
if func_body == nil then func_body = call_args[1] end
else func_body = func_body() end
elseif func_type == type("string") then
return func_body
elseif func_type == type({}) then
return _jsonEncode(func_body)
end
func_type = type( func_body )
end
end
return func_name
end
if trim(var_name) ~= '' then
return working_frame:expandTemplate{ title = 'Error', args = { printf(messages.var_undefine, var_name) } }
end
return ''
end
function p._arg_process(frame)
local args, working_frame
if frame == mw.getCurrentFrame() then
-- We're being called via #invoke. The args are passed through to the module
-- from the template page, so use the args that were passed into the template.
if lib_arg.getArgs == nil then lib_arg = require('Module:Arguments') end
args = lib_arg.getArgs(frame, {
parentFirst=true,
trim = false,
removeBlanks = false
})
working_frame = frame
else
-- We're being called from another module or from the debug console, so assume
-- the args are passed in directly.
args = frame
working_frame = mw.getCurrentFrame()
if type(args) ~= type({}) then args = {frame} end
end
return args, working_frame
end
function p.getVar(frame, get_mode, const, from_meta_table)
local to_get_mode = get_mode or 'value'
local args, working_frame = p._arg_process(frame)
local vars = p._getVars('VAR', const)
local var_name = args[1]or args['1']or''
local get_value = vars[var_name]
if tonumber(var_name) and not get_value then get_value = vars[tonumber(var_name)] end
if get_value then
local get_result, check_json = mw.ustring.gsub(get_value[to_get_mode], "^%$JSON%$", '')
if check_json > 0 and from_meta_table == true then
return mw.text.jsonDecode(get_result)
end
return get_result
end
if trim(var_name) ~= '' then
if args[2]or args['2'] or args.default then return args[2]or args['2']or args.default end
if from_meta_table == true then return error(printf(messages.var_undefine, var_name)) end
return working_frame:expandTemplate{ title = 'Error', args = { printf(messages.var_undefine, var_name) } }
end
return ''
end
function p.getVarHist(frame, from_meta_table)
local args, working_frame = p._arg_process(frame)
local vars = p._getVars('VAR')
local var_name = args[1]or args['1']or''
local get_value = vars[var_name]
if tonumber(var_name) and not get_value then get_value = vars[tonumber(var_name)] end
if get_value then
local formats = args[2]or args['2']or'$'
local seps = args[3]or args['3']or', '
local hists = split(get_value.hist,'$\127;\127^')
local body = ''
if from_meta_table == true then
local get_result, check_json = {}, -1
for i=1,#hists do
get_result[i], check_json = mw.ustring.gsub(hists[i], "^%$JSON%$", '')
if check_json > 0 then
get_result[i] = mw.text.jsonDecode(get_result[i])
end
end
return get_result
end
for i=1,#hists do
if i>1 then body = body .. seps end
body = body .. gsub(formats, '%$', hists[i])
end
return body
end
if trim(var_name) ~= '' then
if from_meta_table == true then return error(printf(messages.var_undefine, var_name)) end
return working_frame:expandTemplate{ title = 'Error', args = { printf(messages.var_undefine, var_name) } }
end
return ''
end
function p._getRefVarObj(VarMode, addr)
local addr_path = split(addr,':')
if #addr_path == 2 then
local strip_id, addr_loc = addr_path[1], addr_path[2]
strip_id = tonumber(strip_id)
addr_loc = tonumber(addr_loc)
if strip_id and addr_loc then
local try_get = mw.text.unstripNoWiki( p._stripMark('nowiki', string.format( "%08X", strip_id )) )
local in_index, arg_data = 1, nil
gsub(try_get, messages.magic_space .. "%$" .. VarMode .. "_DEF%s+([^=]+)=([^" .. messages.magic_space .. ']*)',
function(f_key, f_value)
local key, value = f_key, f_value
key = trim(key)
if in_index == addr_loc then
arg_data = {
name=key,
value=value,
addr=string.format( "%d:%d", strip_id, in_index )
} end
in_index = in_index + 1
end)
return arg_data
end
end
return nil
end
function p._seek_arg(input_args_list, offset, enable_minus)
local num_args = {}
if enable_minus~=true and offset <= 1 then offset = 1 end
for key,value in pairs(input_args_list) do
local num = tonumber(key) or 0
local stored = false
if num then
if num > offset then
num_args[num - offset] = value
stored = true
end
if num >= 1 and num <= offset then stored = true end
end
if stored ~= true then num_args[key] = value end
end
return num_args
end
function p._code_getter_wiki(working_frame, input_code)
local current_text, code_lang = input_code, "moin"
local flag1 = lib_str.find(current_text, "<%s*/?%s*[A-Za-z]")
local flag2 = lib_str.find(current_text, "[A-Za-z\"']%s*/?%s*>")
if flag1 or flag2 then code_lang = "html" end
local body = ''
local strip_to_remove = split(current_text,'\127')
for i=1,#strip_to_remove do
local current_strip = strip_to_remove[i]
if lib_str.find(current_strip,"'\"`UNIQ%-%-") then
if lib_str.find(current_strip, "nowiki") then
local try_unstrip = '\127' .. current_strip .. '\127'
try_unstrip = mw.text.unstripNoWiki( try_unstrip )
if lib_str.find(try_unstrip,"'\"`UNIQ%-%-") then
--不存在的strip entity
body = body .. '\127' .. current_strip .. '\127'
else
try_unstrip = mw.text.decode(try_unstrip)
try_unstrip = printf("<nowiki>%s</nowiki>",table.concat( split(try_unstrip,"nowiki"),'</nowiki>nowiki<nowiki>'))
body = body .. codeNowikiWithColor(working_frame, 'xml', try_unstrip)
end
else
--保留原始strip符號令解析器自動替換
local strip_type = ''
gsub(current_strip, "UNIQ%-%-([%dA-Za-z]+)%-", function(in_str)strip_type=in_str end)
local out_strip_text = '\127' .. current_strip .. '\127'
if strip_type ~= '' then
local strip_code_color_data = strip_code_color(working_frame, strip_type)
out_strip_text = strip_code_color_data[1] .. out_strip_text ..strip_code_color_data[2]
end
body = body .. out_strip_text
notsupport_strip = true
end
elseif trim(current_strip) ~= '' then
local avoid_t = split(current_strip, '%-{') or {avoid_t}
for a_i = 1,#avoid_t do
local a_ic = avoid_t[a_i]
if a_i ~= 1 then a_ic = '{' .. a_ic end
if a_i ~= #avoid_t then a_ic = a_ic .. '-' end
body = body .. codeNowikiWithColor(working_frame, code_lang, a_ic)
end
end
end
return body .. out_new_line()
end
function p._getVars(VarMode, const)
local frame = mw.getCurrentFrame()
local mark_get_mark, max_id = frame:extensionTag( 'nowiki', 'nowiki' ), ''
gsub(mark_get_mark, 'nowiki%-([0-9A-Za-z]+)%-', function(id)max_id = id end)
local max_id_num, body = tonumber(max_id, 16), ''
local symbol_table = {}
for i=1,max_id_num do
local try_get = mw.text.unstripNoWiki( p._stripMark('nowiki', string.format( "%08X", i-1 )) )
local in_index = 1
gsub(try_get, messages.magic_space .. "%$([A-Z]+)_DEF%s+([^=]+)=([^" .. messages.magic_space .. ']*)',
function(sub_mode, f_key, f_value)--VarMode
local key, value = f_key, f_value
key = trim(key)
if key ~= '' then
local it if const == true then it = symbol_table[key] end
local old = symbol_table[key]
if sub_mode == 'DELETE' then symbol_table[key] = nil
elseif sub_mode == VarMode then
symbol_table[key] = it or {
name=key,
value=value,
hist=((old or {}).hist and ( (old or {}).hist .. '$\127;\127^' ) or '') .. value,
addr=string.format( "%d:%d", (i-1), in_index )
}end
end
in_index = in_index + 1
end)
end
return symbol_table
end
function p._stripMark(mark_name, mark_id)
return printf(messages.strip_mark, mark_name, mark_id)
end
return p