diff options
Diffstat (limited to 'Master/texmf-dist/tex/luatex/luatexja/ltj-base.lua')
-rw-r--r-- | Master/texmf-dist/tex/luatex/luatexja/ltj-base.lua | 443 |
1 files changed, 443 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/luatex/luatexja/ltj-base.lua b/Master/texmf-dist/tex/luatex/luatexja/ltj-base.lua new file mode 100644 index 00000000000..3d23d5f602f --- /dev/null +++ b/Master/texmf-dist/tex/luatex/luatexja/ltj-base.lua @@ -0,0 +1,443 @@ +-- +-- luatexja/base.lua +-- +luatexbase.provides_module({ + name = 'luatexja.base', + date = '2011/04/01', + version = '0.1', + 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 + +local cat_lp = luatexbase.catcodetables['latex-package'] + +-------------------- + +public_name = 'luatexja' +public_version = 'alpha' + +-------------------- Fully-expandable error messaging +do +--! LaTeX 形式のエラーメッセージ(\PackageError 等)を +--! Lua 関数の呼び出しで行う. + + local LF = "\n" + local err_break = "" + local err_main = "" + local err_help = "" + + local function message_cont(str, c) + return str:gsub(err_break, LF .. c) + end + local function into_lines(str) + return str:gsub(err_break, LF):explode(LF) + end + + function _error_set_break(str) + err_break = str + end + + function _error_set_message(msgcont, main, help) + err_main = message_cont(main, msgcont) + err_help = into_lines(help) + end + + function _error_show(escchar) + local escapechar = tex.escapechar + local newlinechar = tex.newlinechar + local errorcontextlines = tex.errorcontextlines + if not escchar then tex.escapechar = -1 end + tex.newlinechar = 10 + tex.errorcontextlines = -1 + tex.error(err_main, err_help) + tex.escapechar = escapechar + tex.newlinechar = newlinechar + tex.errorcontextlines = errorcontextlines + end + + local message_a = "Type H <return> for immediate help" + + function generic_error(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) + local mainc = message_cont(main, msgcont) + local br = warn and "\n" or "" + local out = warn and "term and log" or "log" + local on_line = line and (" on input line "..tex.inputlineno) or "" + local newlinechar = tex.newlinechar + tex.newlinechar = -1 + texio.write_nl(out, br..main..on_line.."."..br) + tex.newlinechar = newlinechar + end + + function generic_warning(msgcont, main) + _generic_warn_info(msgcont, main, true, true) + end + function generic_warning_no_line(msgcont, main) + _generic_warn_info(msgcont, main, true, false) + end + function generic_info(msgcont, main) + _generic_warn_info(msgcont, main, false, true) + end + function generic_info_no_line(msgcont, main) + _generic_warn_info(msgcont, main, false, false) + end + + function package_error(pkgname, main, help) + generic_error("("..pkgname.." ", + "Package "..pkgname.." Error: "..main, + "See the "..pkgname.." package documentation for explanation.", + help) + end + function package_warning(pkgname, main) + generic_warning("("..pkgname.." ", + "Package "..pkgname.." Warning: "..main) + end + function package_warning_no_line(pkgname, main) + generic_warning_no_line("("..pkgname.." ", + "Package "..pkgname.." Warning: "..main) + end + function package_info(pkgname, main) + generic_info("("..pkgname.." ", + "Package "..pkgname.." Info: "..main) + end + function package_info_no_line(pkgname, main) + generic_info_no_line("("..pkgname.." ", + "Package "..pkgname.." Info: "..main) + end + + function ltj_error(main, help) + package_error(public_name, main, help) + end + function ltj_warning_no_line(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 + table.insert(lines, arg[1]) + table.remove(arg, 1) + end + for _, cnk in ipairs(arg) do + local ls = cnk:explode("\n") + if ls[#ls] == "" then + table.remove(ls, #ls) + end + for _, l in ipairs(ls) do + table.insert(lines, l) + end + end + return tex.print(unpack(lines)) + end + +end +-------------------- Handling of TeX values +do + + local glue_spec_id = node.id("glue_spec") + + local function copy_skip(s1, s2) + if not s1 then + s1 = node.new(glue_spec_id) + end + s1.width = s2.width or 0 + s1.stretch = s2.stretch or 0 + s1.stretch_order = s2.stretch_order or 0 + s1.shrink = s2.shrink or 0 + s1.shrink_order = s2.shrink_order or 0 + return s1 + end + +--! ixbase.to_dimen() と同じ + function to_dimen(val) + if val == nil then + return 0 + elseif type(val) == "number" then + return val + else + return tex.sp(tostring(val)) + end + end + + local function parse_dimen(val) + val = tostring(val):lower() + local r, fil = val:match("([-.%d]+)fi(l*)") + if r then + val, fil = r.."pt", fil:len() + 1 + else + fil = 0 + end + return tex.sp(val), fil + end + +--! ixbase.to_skip() と同じ + function to_skip(val) + if type(val) == "userdata" then + return val + end + local res = node.new(glue_spec_id) + if val == nil then + res.width = 0 + elseif type(val) == "number" then + res.width = val + elseif type(val) == "table" then + copy_skip(res, val) + else + local t = tostring(val):lower():explode() + local w, p, m = t[1], t[3], t[5] + if t[2] == "minus" then + 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]) + end + if t[5] then + res.shrink, res.shrink_order = parse_dimen(t[5]) + end + end + return res + end + + 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 + +end +-------------------- Virtual table for LaTeX counters +do + +--! ixbase.counter と同じ + counter = {} + local mt_counter = {} + setmetatable(counter, mt_counter) + + function mt_counter.__index(tbl, key) + return tex.count['c@'..key] + end + function mt_counter.__newindex(tbl, key, val) + tex.count['c@'..key] = val + end + +--! 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 +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) +end + +-------------------- all done +-- EOF |