X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=src%2Fltj-base.lua;h=e66a196aee6681b519a3530a442b03c427d7a528;hb=aaee6f5d2ec4639dc1f7bf4ee0e7c5111a70d6ce;hp=47518a5ec815de4ab5d831970da9440349b8774e;hpb=20b1439219d2cff779afa1513c473d2d286b7296;p=luatex-ja%2Fluatexja.git diff --git a/src/ltj-base.lua b/src/ltj-base.lua index 47518a5..e66a196 100644 --- a/src/ltj-base.lua +++ b/src/ltj-base.lua @@ -1,14 +1,6 @@ -- --- luatexja/base.lua +-- luatexja/ltj-base.lua -- -luatexbase.provides_module({ - name = 'luatexja.base', - date = '2013/12/22', - description = '', -}) -module('luatexja.base', package.seeall) -local err, warn, info, log = luatexbase.errwarinf(_NAME) - local ltb = luatexbase local tostring = tostring local node, table, tex, token = node, table, tex, token @@ -16,11 +8,24 @@ local node, table, tex, token = node, table, tex, token local cat_lp = luatexbase.catcodetables['latex-package'] -------------------- +local ltjb = {} +luatexja.base = ltjb + +local public_name = 'luatexja' +local public_version = 'alpha' +ltjb.public_name = public_name +ltjb.public_version = public_version -public_name = 'luatexja' -public_version = 'alpha' -------------------- Fully-expandable error messaging +local _error_set_break, _error_set_message, _error_show +local generic_error, _generic_warn_info +local generic_warning, generic_warning_no_line +local generic_info, generic_info_no_line +local package_error, package_warning, package_warning_no_line +local package_info, package_info_no_line +local ltj_error, ltj_warning_no_line + do --! LaTeX 形式のエラーメッセージ(\PackageError 等)を --! Lua 関数の呼び出しで行う. @@ -37,16 +42,16 @@ do return str:gsub(err_break, LF):explode(LF) end - function _error_set_break(str) + _error_set_break = function (str) err_break = str end - function _error_set_message(msgcont, main, help) + _error_set_message = function (msgcont, main, help) err_main = message_cont(main, msgcont) err_help = into_lines(help) end - function _error_show(escchar) + _error_show = function (escchar) local escapechar = tex.escapechar local newlinechar = tex.newlinechar local errorcontextlines = tex.errorcontextlines @@ -61,13 +66,13 @@ do local message_a = "Type H for immediate help" - function generic_error(msgcont, main, ref, help) + generic_error = function (msgcont, main, ref, help) local mainref = main..".\n\n"..ref.."\n"..message_a _error_set_message(msgcont, mainref, help) _error_show(true) end - function _generic_warn_info(msgcont, main, warn, line) + _generic_warn_info = function (msgcont, main, warn, line) local mainc = message_cont(main, msgcont) local br = warn and "\n" or "" local out = warn and "term and log" or "log" @@ -78,78 +83,76 @@ do tex.newlinechar = newlinechar end - function generic_warning(msgcont, main) + generic_warning = function (msgcont, main) _generic_warn_info(msgcont, main, true, true) end - function generic_warning_no_line(msgcont, main) + generic_warning_no_line = function (msgcont, main) _generic_warn_info(msgcont, main, true, false) end - function generic_info(msgcont, main) + generic_info = function (msgcont, main) _generic_warn_info(msgcont, main, false, true) end - function generic_info_no_line(msgcont, main) + generic_info_no_line = function (msgcont, main) _generic_warn_info(msgcont, main, false, false) end - function package_error(pkgname, main, help) + package_error = function (pkgname, main, help) generic_error("("..pkgname.." ", "Package "..pkgname.." Error: "..main, "See the "..pkgname.." package documentation for explanation.", help) end - function package_warning(pkgname, main) + package_warning = function (pkgname, main) generic_warning("("..pkgname.." ", "Package "..pkgname.." Warning: "..main) end - function package_warning_no_line(pkgname, main) + package_warning_no_line = function (pkgname, main) generic_warning_no_line("("..pkgname.." ", "Package "..pkgname.." Warning: "..main) end - function package_info(pkgname, main) + package_info = function (pkgname, main) generic_info("("..pkgname.." ", "Package "..pkgname.." Info: "..main) end - function package_info_no_line(pkgname, main) + package_info_no_line = function (pkgname, main) generic_info_no_line("("..pkgname.." ", "Package "..pkgname.." Info: "..main) end - function ltj_error(main, help) + ltj_error = function (main, help) package_error(public_name, main, help) end - function ltj_warning_no_line(main) + ltj_warning_no_line = function (main) package_warning_no_line(public_name, main, help) end end -------------------- TeX stream I/O -do - --! ixbase.print() と同じ - --- Extension to tex.print(). Each argument string may contain - -- newline characters, in which case the string is output (to - -- TeX input stream) as multiple lines. - -- @param ... (string) string to output - function mprint(...) - local arg = {...} - local lines = {} - if type(arg[1]) == "number" then +--- Extension to tex.print(). Each argument string may contain +-- newline characters, in which case the string is output (to +-- TeX input stream) as multiple lines. +-- @param ... (string) string to output +local function mprint(...) + local arg = {...} + local lines = {} + if type(arg[1]) == "number" then table.insert(lines, arg[1]) table.remove(arg, 1) - end - for _, cnk in ipairs(arg) do + end + for _, cnk in ipairs(arg) do local ls = cnk:explode("\n") if ls[#ls] == "" then - table.remove(ls, #ls) + table.remove(ls, #ls) end for _, l in ipairs(ls) do - table.insert(lines, l) + table.insert(lines, l) end - end - return tex.print(unpack(lines)) - end - + end + return tex.print(unpack(lines)) end +ltjb.mprint = mprint + -------------------- Handling of TeX values do @@ -168,7 +171,7 @@ do end --! ixbase.to_dimen() と同じ - function to_dimen(val) + local function to_dimen(val) if val == nil then return 0 elseif type(val) == "number" then @@ -190,7 +193,7 @@ do end --! ixbase.to_skip() と同じ - function to_skip(val) + local function to_skip(val) if type(val) == "userdata" then return val end @@ -208,26 +211,30 @@ do p, m = nil, t[3] end res.width = tex.sp(t[1]) - if t[3] then - res.stretch, res.stretch_order = parse_dimen(t[3]) + if p then + res.stretch, res.stretch_order = parse_dimen(p) end - if t[5] then - res.shrink, res.shrink_order = parse_dimen(t[5]) + if m then + res.shrink, res.shrink_order = parse_dimen(m) end end return res end - function dump_skip(s) + local function dump_skip(s) print(("%s+%s<%s>-%s<%s>"):format( s.width or 0, s.stretch or 0, s.stretch_order or 0, s.shrink or 0, s.shrink_order or 0)) end + ltjb.to_dimen = to_dimen + ltjb.dump_skip = dump_skip + ltjb.to_skip = to_skip end + -------------------- Virtual table for LaTeX counters +-- not used in current LuaTeX-ja do - --! ixbase.counter と同じ counter = {} local mt_counter = {} @@ -239,206 +246,29 @@ do function mt_counter.__newindex(tbl, key, val) tex.count['c@'..key] = val end + ltjb.counter = counter --! ixbase.length は tex.skip と全く同じなので不要. - end --------------------- Number handling in TeX source -do - - local tok_escape = token.create("ltj@@q@escape") - local tok_num = token.create("ltj@@q@escapenum") - local c_id_assign_int = token.command_id("assign_int") - local c_id_char_given = token.command_id("char_given") - - local function error_scan() - _M.package_error("luatexja", - "Missing number of a permitted form, treated as zero", - "A number should have been here; I inserted '0'.") - end - - local function get_expd_next() - local next = token.get_next() - while token.is_expandable(next) do - token.expand(next) - next = token.get_next() - end - return next - end - - local function grab_decimal(next, res) - table.insert(res, next) - while true do - next = get_expd_next() - if not (next[1] == 12 and 0x30 <= next[2] and next[2] <= 0x39) then - break - end - table.insert(res, next) - end - if next[1] == 10 then next = nil end - return true, next - end - - local function grab_hexa(next, res) - local ok = false - table.insert(res, next) - while true do - next = get_expd_next() - if not ((next[1] == 12 and (0x30 <= next[2] and next[2] <= 0x39)) or - ((next[1] == 12 or next[1] == 11) and - (0x41 <= next[2] and next[2] <= 0x46))) then - break - end - ok = true - table.insert(res, next) - end - if next[1] == 10 then next = nil end - return ok, next - end - - local function grab_octal(next, res) - local ok = false - table.insert(res, next) - while true do - next = get_expd_next() - if not (next[1] == 12 and (0x30 <= next[2] and next[2] <= 0x37)) then - break - end - ok = true - table.insert(res, next) - end - if next[1] == 10 then next = nil end - return ok, next - end - - local function grab_charnum(next, res) - table.insert(res, next) - next = token.get_next() - table.insert(res, next) - next = get_expd_next() - if next[1] == 10 then next = nil end - return true, next - end - - local function scan_with(delay, scanner) - local function proc() - if delay ~= 0 then - if delay > 0 then delay = delay - 1 end - return token.get_next() - else - local cont, back = scanner() - if not cont then - ltb.remove_from_callback("token_filter", "ltj@grab@num") - end - return back - end - end - ltb.add_to_callback("token_filter", proc, "ltj@grab@num", 1) - end - - function scan_brace() - scan_with(1, function() - local next = token.get_next() - if next[1] == 1 then - return false, { tok_escape, next } - elseif next[1] == 10 then - return true, { next } - else - return false, { next } - end - end) - end - - function scan_number() - scan_with(1, function() - local next = get_expd_next() - local res, ok = { tok_num }, false - while true do - if next[1] == 12 and (next[2] == 0x2B or next[2] == 0x2D) then - table.insert(res, next) - elseif next[1] ~= 10 then - break - end - next = get_expd_next() - end - if next[1] == 12 and 0x30 <= next[2] and next[2] <= 0x39 then - ok, next = grab_decimal(next, res) - elseif next[1] == 12 and next[2] == 0x22 then - ok, next = grab_hexa(next, res) - elseif next[1] == 12 and next[2] == 0x27 then - ok, next = grab_octal(next, res) - elseif next[1] == 12 and next[2] == 0x60 then - ok, next = grab_charnum(next, res) - elseif next[1] == c_id_assign_int or next[1] == c_id_char_given then - table.insert(res, next) - ok, next = true, nil - end - if ok then - table.insert(res, tok_num) - else - error_scan() - res = { tok_escape } - end - if next then table.insert(res, next) end - return false, res - end) - end -end --------------------- TeX register allocation +-------------------- common error message do - local cmod_base_count = token.create('ltj@@count@zero')[2] - local cmod_base_attr = token.create('ltj@@attr@zero')[2] - local cmod_base_dimen = token.create('ltj@@dimen@zero')[2] - local cmod_base_skip = token.create('ltj@@skip@zero')[2] - - function const_number(name) - if name:sub(1, 1) == '\\' then name = name:sub(2) end - return token.create(name)[2] - end - - function count_number(name) - if name:sub(1, 1) == '\\' then name = name:sub(2) end - return token.create(name)[2] - cmod_base_count - end - - function attribute_number(name) - if name:sub(1, 1) == '\\' then name = name:sub(2) end - return token.create(name)[2] - cmod_base_attr - end - - function dimen_number(name) - if name:sub(1, 1) == '\\' then name = name:sub(2) end - return token.create(name)[2] - cmod_base_dimen - end - - function skip_number(name) - if name:sub(1, 1) == '\\' then name = name:sub(2) end - return token.create(name)[2] - cmod_base_skip - end - -end --------------------- mock of debug logger - -if not _M.debug or _M.debug == _G.debug then - local function no_op() end - debug = no_op - package_debug = no_op - show_term = no_op - show_log = no_op - function debug_logger() - return no_op - end -end - --------------------- getting next token -cstemp = nil -function get_cs(s) - cstemp = token.csname_name(token.get_next()) - tex.sprint(cat_lp,'\\' .. s) + local function in_unicode(c, admit_math) + local low = admit_math and -1 or 0 + if type(c)~='number' or c0x10FFFF then + local s = 'A character number must be between ' .. tostring(low) + .. ' and 0x10ffff.\n' + .. (admit_math and "(-1 is used for denoting `math boundary')\n" or '') + .. 'So I changed this one to zero.' + package_error('luatexja', + 'bad character code (' .. tostring(c) .. ')', s) + c=0 + end + return c + end + ltjb.in_unicode = in_unicode end - -------------------- cache management -- load_cache (filename, outdate) -- * filename: without suffix '.lua' @@ -452,10 +282,17 @@ end require('lualibs-lpeg') -- string.split require('lualibs-os') -- os.type + do - local path = kpse.expand_var("$TEXMFVAR;$TEXMFSYSVAR;$TEXMFCACHE") + local kpse_var_value = kpse.var_value + local path, pathtmp = kpse_var_value("TEXMFVAR") + pathtmp = kpse_var_value("TEXMFSYSVAR") + if pathtmp then path = (path and path .. ';' or '') .. pathtmp end + pathtmp = kpse_var_value("TEXMFCACHE") + if pathtmp then path = (path and path .. ';' or '') .. pathtmp end + if os.type~='windows' then path = string.gsub(path, ':', ';') end - path = string.split(path, ';') + path = table.unique(string.split(path, ';')) local cache_dir = '/luatexja' local find_file = kpse.find_file @@ -471,9 +308,9 @@ do if lfs.isdir(testpath) then savepath = testpath; break end end - function save_cache_luc(filename, t) + save_cache_luc = function (filename, t, serialized) local fullpath = savepath .. '/' .. filename .. luc_suffix - local s = serialize(t, 'return', false) + local s = serialized or serialize(t, 'return', false) if s then local sa = load(s) local f = io.open(fullpath, 'wb') @@ -485,24 +322,28 @@ do end end - function save_cache(filename, t) + save_cache = function (filename, t) local fullpath = savepath .. '/' .. filename .. '.lua' - tofile(fullpath, t, 'return', false) - texio.write('(save cache: ' .. fullpath .. ')') - save_cache_luc(filename, t) + local s = serialize(t, 'return', false) + if s then + local f = io.open(fullpath, 'w') + if f then + f:write(s) + texio.write('(save cache: ' .. fullpath .. ')') + end + f:close() + save_cache_luc(filename, t, s) + end end - local function luc_load (n) - texio.write('(load cache: ' .. n .. ')') - local f = loadfile(n, 'b'); return f - end - local function load_cache_a (filename, outdate, loader) + local function load_cache_a (filename, outdate) local result for _,v in pairs(path) do local fn = join(v, cache_dir, filename) if isreadable(fn) then - result = loader(fn) - if result then result = result(); break end + texio.write('(load cache: ' .. fn .. ')') + result = loadfile(fn) + result = result and result(); break end end if (not result) or outdate(result) then @@ -511,17 +352,91 @@ do return result end end - function load_cache (filename, outdate) - local r = load_cache_a(filename .. luc_suffix, outdate, luc_load) + + load_cache = function (filename, outdate) + local r = load_cache_a(filename .. luc_suffix, outdate) if r then return r else - local r = load_cache_a(filename .. '.lua', outdate, loadfile) + local r = load_cache_a(filename .. '.lua', outdate) if r then save_cache_luc(filename, r) end -- update the precompiled cache return r end end + ltjb.load_cache = load_cache + ltjb.save_cache_luc = save_cache_luc + ltjb.save_cache = save_cache +end + +---- +do + local tex_set_attr, tex_get_attr = tex.setattribute, tex.getattribute + function ltjb.ensure_tex_attr(a, v) + if tex_get_attr(a)~=v then + tex_set_attr(a, v) + end + end +end +---- + +ltjb._error_set_break = _error_set_break +ltjb._error_set_message = _error_set_message +ltjb._error_show = _error_show +ltjb._generic_warn_info = _generic_warn_info + +ltjb.package_error = package_error +ltjb.package_warning = package_warning +ltjb.package_warning_no_line = package_warning_no_line +ltjb.package_info = package_info +ltjb.package_info_no_line = package_info_no_line + +ltjb.generic_error = generic_error +ltjb.generic_warning = generic_warning +ltjb.generic_warning_no_line = generic_warning_no_line +ltjb.generic_info = generic_info +ltjb.generic_info_no_line = generic_info_no_line + +ltjb.ltj_warning_no_line = ltj_warning_no_line +ltjb.ltj_error = ltj_error + +---- deterministic version of luatexbase.add_to_callback +function ltjb.add_to_callback(name,fun,description,priority) + local priority= priority + if priority==nil then + priority=#luatexbase.callback_descriptions(name)+1 + end + if(luatexbase.callbacktypes[name] == 3 and + priority == 1 and + #luatexbase.callback_descriptions(name)==1) then + luatexbase.module_warning("luatexbase", + "resetting exclusive callback: " .. name) + luatexbase.reset_callback(name) + end + local saved_callback={},ff,dd + for k,v in ipairs(luatexbase.callback_descriptions(name)) do + if k >= priority then + ff,dd= luatexbase.remove_from_callback(name, v) + saved_callback[#saved_callback+1]={ff,dd} + end + end + luatexbase.base_add_to_callback(name,fun,description) + for _,v in ipairs(saved_callback) do + luatexbase.base_add_to_callback(name,v[1],v[2]) + end + return +end + +-------------------- mock of debug logger +if not ltjb.out_debug then + local function no_op() end + ltjb.start_time_measure = no_op + ltjb.stop_time_measure = no_op + ltjb.out_debug = no_op + ltjb.package_debug = no_op + ltjb.debug_logger = function() return no_op end + ltjb.show_term = no_op + ltjb.show_log = no_op end -------------------- all done