X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=src%2Fltj-base.lua;h=495f185fed2a1e1edc2f350b382b7f7cd07c4071;hb=a693b63eadfcabe5f4f513a4cc90302f2360b18b;hp=d45a376ee90aa35edf2876f9ffe3790b6ec0f8e3;hpb=73f9bd4e6731b99d784f7d736692d51411ba3884;p=luatex-ja%2Fluatexja.git diff --git a/src/ltj-base.lua b/src/ltj-base.lua index d45a376..495f185 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 = '2011/11/18', - 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,23 @@ local node, table, tex, token = node, table, tex, token local cat_lp = luatexbase.catcodetables['latex-package'] -------------------- +luatexja.base = {} + +local public_name = 'luatexja' +local public_version = 'alpha' +luatexja.base.public_name = public_name +luatexja.base.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 +41,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 +65,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 +82,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 +luatexja.base.mprint = mprint + -------------------- Handling of TeX values do @@ -168,7 +170,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 +192,7 @@ do end --! ixbase.to_skip() と同じ - function to_skip(val) + local function to_skip(val) if type(val) == "userdata" then return val end @@ -218,16 +220,20 @@ do 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 + luatexja.base.to_dimen = to_dimen + luatexja.base.dump_skip = dump_skip + luatexja.base.to_skip = to_skip end + -------------------- Virtual table for LaTeX counters +-- not used in current LuaTeX-ja do - --! ixbase.counter と同じ counter = {} local mt_counter = {} @@ -239,10 +245,11 @@ do function mt_counter.__newindex(tbl, key, val) tex.count['c@'..key] = val end + luatexja.base.counter = counter --! ixbase.length は tex.skip と全く同じなので不要. - end + -------------------- Number handling in TeX source do @@ -252,7 +259,7 @@ do local c_id_char_given = token.command_id("char_given") local function error_scan() - _M.package_error("luatexja", + package_error("luatexja", "Missing number of a permitted form, treated as zero", "A number should have been here; I inserted '0'.") end @@ -336,7 +343,7 @@ do ltb.add_to_callback("token_filter", proc, "ltj@grab@num", 1) end - function scan_brace() + local function scan_brace() scan_with(1, function() local next = token.get_next() if next[1] == 1 then @@ -349,7 +356,7 @@ do end) end - function scan_number() + local function scan_number() scan_with(1, function() local next = get_expd_next() local res, ok = { tok_num }, false @@ -384,43 +391,53 @@ do end) end + luatexja.base.scan_brace = scan_brace + luatexja.base.scan_number = scan_number end + -------------------- TeX register allocation +-- not used in current LuaTeX-ja + 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) + local 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) + local 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) + local 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) + local 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) + local function skip_number(name) if name:sub(1, 1) == '\\' then name = name:sub(2) end return token.create(name)[2] - cmod_base_skip end + luatexja.base.const_number = const_number + luatexja.base.count_number = count_number + luatexja.base.attribute_number = attribute_number + luatexja.base.dimen_number = dimen_number + luatexja.base.skip_number = skip_number end --------------------- mock of debug logger -if not _M.debug or _M.debug == _G.debug then +-------------------- mock of debug logger +if not debug or debug == _G.debug then local function no_op() end debug = no_op package_debug = no_op @@ -432,11 +449,156 @@ if not _M.debug or _M.debug == _G.debug then end -------------------- getting next token -cstemp = nil -function get_cs(s) +local cstemp = nil +local function get_cs(s) cstemp = token.csname_name(token.get_next()) tex.sprint(cat_lp,'\\' .. s) end +luatexja.base.get_cs = get_cs + +-------------------- common error message +do + 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 + luatexja.base.in_unicode = in_unicode +end + +-------------------- cache management +-- load_cache (filename, outdate) +-- * filename: without suffix '.lua' +-- * outdate(t): return true iff the cache is outdated +-- * return value: non-nil iff the cache is up-to-date +-- save_cache (filename, t): no return value +-- save_cache_luc (filename, t): no return value +-- save_cache always calls save_cache_luc. +-- But sometimes we want to create only the precompiled cache, +-- when its 'text' version is already present in LuaTeX-ja distribution. + +require('lualibs-lpeg') -- string.split +require('lualibs-os') -- os.type + +do + 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 = table.unique(string.split(path, ';')) + + local cache_dir = '/luatexja' + local find_file = kpse.find_file + local join, isreadable = file.join, file.isreadable + local tofile, serialize = table.tofile, table.serialize + local luc_suffix = jit and '.lub' or '.luc' + + -- determine save path + local savepath = '' + for _,v in pairs(path) do + local testpath = join(v, cache_dir) + if not lfs.isdir(testpath) then dir.mkdirs(testpath) end + if lfs.isdir(testpath) then savepath = testpath; break end + end + + save_cache_luc = function (filename, t, serialized) + local fullpath = savepath .. '/' .. filename .. luc_suffix + local s = serialized or serialize(t, 'return', false) + if s then + local sa = load(s) + local f = io.open(fullpath, 'wb') + if f and sa then + f:write(string.dump(sa, true)) + texio.write('(save cache: ' .. fullpath .. ')') + end + f:close() + end + end + + save_cache = function (filename, t) + local fullpath = savepath .. '/' .. filename .. '.lua' + 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 load_cache_a (filename, outdate) + local result + for _,v in pairs(path) do + local fn = join(v, cache_dir, filename) + if isreadable(fn) then + texio.write('(load cache: ' .. fn .. ')') + result = loadfile(fn) + result = result and result(); break + end + end + if (not result) or outdate(result) then + return nil + else + return result + end + end + + 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) + if r then save_cache_luc(filename, r) end -- update the precompiled cache + return r + end + end + + luatexja.base.load_cache = load_cache + luatexja.base.save_cache_luc = save_cache_luc + luatexja.base.save_cache = save_cache +end + +luatexja.base._error_set_break = _error_set_break +luatexja.base._error_set_message = _error_set_message +luatexja.base._error_show = _error_show +luatexja.base._generic_warn_info = _generic_warn_info + +luatexja.base.package_error = package_error +luatexja.base.package_warning = package_warning +luatexja.base.package_warning_no_line = package_warning_no_line +luatexja.base.package_info = package_info +luatexja.base.package_info_no_line = package_info_no_line + +luatexja.base.generic_error = generic_error +luatexja.base.generic_warning = generic_warning +luatexja.base.generic_warning_no_line = generic_warning_no_line +luatexja.base.generic_info = generic_info +luatexja.base.generic_info_no_line = generic_info_no_line + +luatexja.base.ltj_warning_no_line = ltj_warning_no_line +luatexja.base.ltj_error = ltj_error + +luatexja.base.debug = debug +luatexja.base.package_debug = package_debug +luatexja.base.debug_logger = debug_logger +luatexja.base.show_term = show_term +luatexja.base.show_log = show_log -------------------- all done -- EOF