diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/trac-deb.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/trac-deb.lua | 283 |
1 files changed, 159 insertions, 124 deletions
diff --git a/Master/texmf-dist/tex/context/base/trac-deb.lua b/Master/texmf-dist/tex/context/base/trac-deb.lua index 97753f3e921..87434a13d9d 100644 --- a/Master/texmf-dist/tex/context/base/trac-deb.lua +++ b/Master/texmf-dist/tex/context/base/trac-deb.lua @@ -6,182 +6,217 @@ if not modules then modules = { } end modules ['trac-deb'] = { license = "see context related readme files" } -if not lmx then lmx = { } end -if not lmx.variables then lmx.variables = { } end +local lpeg = lpeg +local lpegmatch = lpeg.match +local format, concat, match = string.format, table.concat, string.match +local tonumber, tostring = tonumber, tostring +local texdimen, textoks, texcount = tex.dimen, tex.toks, tex.count -lmx.htmfile = function(name) return environment.jobname .. "-status.html" end -lmx.lmxfile = function(name) return resolvers.find_file(name,'tex') end +-- maybe tracers -> tracers.tex (and tracers.lua for current debugger) -if not tracers then tracers = { } end -if not tracers.list then tracers.list = { } end -if not tracers.strings then tracers.strings = { } end +local report_system = logs.reporter("system","tex") -tracers.strings.undefined = "undefined" +tracers = tracers or { } +local tracers = tracers -local splitter = lpeg.splitat(":") -local lpegmatch = lpeg.match +tracers.lists = { } +local lists = tracers.lists -function tracers.split(csname) - return lpegmatch(splitter,csname) -end +tracers.strings = { } +local strings = tracers.strings + +strings.undefined = "undefined" + +lists.scratch = { + 0, 2, 4, 6, 8 +} + +lists.internals = { + 'p:hsize', 'p:parindent', 'p:leftskip','p:rightskip', + 'p:vsize', 'p:parskip', 'p:baselineskip', 'p:lineskip', 'p:topskip' +} + +lists.context = { + 'd:lineheight', + 'c:realpageno', 'c:userpageno', 'c:pageno', 'c:subpageno' +} + +local types = { + ['d'] = tracers.dimen, + ['c'] = tracers.count, + ['t'] = tracers.toks, + ['p'] = tracers.primitive +} + +local splitboth = lpeg.splitat(":") +local splittype = lpeg.firstofsplit(":") +local splitname = lpeg.secondofsplit(":") function tracers.type(csname) - tag, name = tracers.split(csname) - if tag then return tag else return nil end + return lpegmatch(splittype,csname) end function tracers.name(csname) - tag, name = tracers.split(csname) - if tag then return name else return csname end + return lpegmatch(splitname,csname) or csname end function tracers.cs(csname) - tag, name = tracers.split(csname) - if tracers.types[tag] then - return tracers.types[tag](name) + local tag, name = lpegmatch(splitboth,csname) + if name and types[tag] then + return types[tag](name) else return tracers.primitive(csname) end end function tracers.dimen(name) - return (tex.dimen[name] and number.topoints(tex.dimen[name])) or tracers.strings.undefined + local d = texdimen[name] + return d and number.topoints(d) or strings.undefined end function tracers.count(name) - return tex.count[name] or tracers.strings.undefined + return texcount[name] or strings.undefined end -function tracers.toks(name) - return (tex.toks[name] and string.limit(tex.toks[name],40)) or tracers.strings.undefined +function tracers.toks(name,limit) + local t = textoks[name] + return t and string.limit(t,tonumber(limit) or 40) or strings.undefined end function tracers.primitive(name) - return tex[name] or tracers.strings.undefined + return tex[name] or strings.undefined end -tracers.types = { - ['d'] = tracers.dimen, - ['c'] = tracers.count, - ['t'] = tracers.toks, - ['p'] = tracers.primitive -} - function tracers.knownlist(name) - return tracers.list[name] and #tracers.list[name] > 0 + local l = lists[name] + return l and #l > 0 +end + +function tracers.showlines(filename,linenumber,offset,errorstr) + local data = io.loaddata(filename) + local lines = data and string.splitlines(data) + if lines and #lines > 0 then + -- this does not work yet as we cannot access the last lua error + -- table.print(status.list()) + -- this will be a plugin sequence + local what, where = match(errorstr,"LuaTeX error <main (%a+) instance>:(%d+)") + if what and where then + -- lua error: linenumber points to last line + local start, stop = "\\start" .. what .. "code", "\\stop" .. what .. "code" + if lines[linenumber] == start then + local n = linenumber + for i=n,1,-1 do + if lines[i] == start then + local n = i + tonumber(where) + if n <= linenumber then + linenumber = n + end + end + end + end + end + offset = tonumber(offset) or 10 + linenumber = tonumber(linenumber) or 10 + local start = math.max(linenumber - offset,1) + local stop = math.min(linenumber + offset,#lines) + if stop > #lines then + return "<linenumber past end of file>" + else + local result, fmt = { }, "%" .. #tostring(stop) .. "d %s %s" + for n=start,stop do + result[#result+1] = format(fmt,n,n == linenumber and ">>" or " ",lines[n]) + end + return concat(result,"\n") + end + else + return "<empty file>" + end +end + +function tracers.printerror(offset) + local filename, linenumber = status.filename, tonumber(status.linenumber) or 0 + if not filename then + report_system("error not related to input file: %s ...",status.lasterrorstring) + elseif type(filename) == "number" then + report_system("error on line %s of filehandle %s: %s ...",linenumber,filename,status.lasterrorstring) + else + -- currently we still get the error message printed to the log/console so we + -- add a bit of spacing around our variant + texio.write_nl("\n") + local errorstr = status.lasterrorstring or "?" + report_system("error on line %s in file %s: %s ...\n",linenumber,filename,errorstr) -- lua error? + texio.write_nl(tracers.showlines(filename,linenumber,offset,errorstr),"\n") + end end -function tracers.showdebuginfo() +directives.register("system.errorcontext", function(v) + if v then + callback.register('show_error_hook', function() tracers.printerror(v) end) + else + callback.register('show_error_hook', nil) + end +end) + +-- this might move + +lmx = lmx or { } + +lmx.htmfile = function(name) return environment.jobname .. "-status.html" end +lmx.lmxfile = function(name) return resolvers.findfile(name,'tex') end + +function lmx.showdebuginfo(lmxname) local variables = { ['title'] = 'ConTeXt Debug Information', ['color-background-one'] = lmx.get('color-background-green'), ['color-background-two'] = lmx.get('color-background-blue'), } - lmx.show('context-debug.lmx',variables) + if lmxname == false then + return variables + else + lmx.show(lmxname or 'context-debug.lmx',variables) + end end -function tracers.showerror() - local filename = status.filename - local linenumber = tonumber(status.linenumber or "0") +function lmx.showerror(lmxname) + local filename, linenumber, errorcontext = status.filename, tonumber(status.linenumber) or 0, "" + if not filename then + filename, errorcontext = 'unknown', 'error in filename' + elseif type(filename) == "number" then + filename, errorcontext = format("<read %s>",filename), 'unknown error' + else + errorcontext = tracers.showlines(filename,linenumber,offset) + end local variables = { ['title'] = 'ConTeXt Error Information', ['errormessage'] = status.lasterrorstring, - ['linenumber'] = status.linenumber, + ['linenumber'] = linenumber, ['color-background-one'] = lmx.get('color-background-yellow'), ['color-background-two'] = lmx.get('color-background-purple'), + ['filename'] = filename, + ['errorcontext'] = errorcontext, } - if not filename then - variables.filename, variables.errorcontext = 'unknown', 'error in filename' - elseif type(filename) == "number" then - variables.filename, variables.errorcontext = "<read " .. filename .. ">", 'unknown error' - elseif io.exists(filename) then - -- todo: use an input opener so that we also catch utf16 an reencoding - lines = io.lines(filename) - if lines then - local context = { } - n, m = 1, linenumber - b, e = m-10, m+10 - s = string.len(tostring(e)) - for line in lines do - if n > e then - break - elseif n > b then - if n == m then - context[#context+1] = string.format("%" .. s .. "d",n) .. " >> " .. line - else - context[#context+1] = string.format("%" .. s .. "d",n) .. " " .. line - end - end - n = n + 1 - end - variables.filename, variables.errorcontext = filename, table.concat(context,"\n") - else - variables.filename, variables.errorcontext = filename, "" - end + if lmxname == false then + return variables else - variables.filename, variables.errorcontext = filename, 'file not found' + lmx.show(lmxname or 'context-error.lmx',variables) end - lmx.show('context-error.lmx',variables) end -function tracers.overloaderror() - callback.register('show_error_hook', tracers.showerror) +function lmx.overloaderror() + callback.register('show_error_hook', function() lmx.showerror() end) -- prevents arguments being passed end -tracers.list['scratch'] = { - 0, 2, 4, 6, 8 -} - -tracers.list['internals'] = { - 'p:hsize', 'p:parindent', 'p:leftskip','p:rightskip', - 'p:vsize', 'p:parskip', 'p:baselineskip', 'p:lineskip', 'p:topskip' -} - -tracers.list['context'] = { - 'd:lineheight', - 'c:realpageno', 'c:pageno', 'c:subpageno' -} +directives.register("system.showerror", lmx.overloaderror) --- dumping the hash +local debugger = utilities.debugger --- \starttext --- \ctxlua{tracers.dump_hash()} --- \stoptext - -local saved = { } - -function tracers.save_hash() - saved = tex.hashtokens() -end - -function tracers.dump_hash(filename,delta) - filename = filename or tex.jobname .. "-hash.log" - local list = { } - local hash = tex.hashtokens() - local command_name = token.command_name - for name, token in next, hash do - if not delta or not saved[name] then - -- token: cmd, chr, csid -- combination cmd,chr determines name - local kind = command_name(token) - local dk = list[kind] - if not dk then - -- a bit funny names but this sorts better (easier to study) - dk = { names = { }, found = 0, code = token[1] } - list[kind] = dk - end - dk.names[name] = { token[2], token[3] } - dk.found = dk.found + 1 - end - end - io.savedata(filename,table.serialize(list,true)) -end - -function tracers.register_dump_hash(delta) - if delta then - tracers.save_hash() - end - main.register_stop_actions(1,function() tracers.dump_hash(nil,true) end) -- at front +local function trace_calls(n) + debugger.enable() + luatex.registerstopactions(function() + debugger.disable() + debugger.savestats(tex.jobname .. "-luacalls.log",tonumber(n)) + end) + trace_calls = function() end end -directives.register("system.dumphash", function() tracers.register_dump_hash(false) end) -directives.register("system.dumpdelta", function() tracers.register_dump_hash(true ) end) +directives.register("system.tracecalls", function(n) trace_calls(n) end) -- indirect is needed for nilling |