This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
jesusthekiller's profile picture

[Incactive for now] Debugging - Debug apps like a boss

Started by jesusthekiller, 15 April 2013 - 01:38 AM
jesusthekiller #1
Posted 15 April 2013 - 03:38 AM
Debugging

Debug your apps like a boss

I've quickly wrote this app after seeing this thread - I've thought this idea can be developed a bit more :)/>


What is does:
It basically logs apps and saves it to "debug_files/<app name>.log".

How to use:
	Usage:
	- debug run <program full path> [args]
	  Logs are saves in debug_files/<program name>.log
	- debug log <program name>
	  Prints a log
	- debug restore
	  Use if program was terminated or to manually restore write &amp; print functions

Where to get it:
  1. pastebin get 9YSN2Mht debug
  2. Code:
Spoiler

local args = {...}

--[[
	Backup for old functions
]]--

local fOld = {
	term = {
		write = term.write,
		clear = term.clear,
		setCursorPos = term.setCursorPos,
		clearLine = term.clearLine,
	},
	print = print,
	write = write,
	read = read,
}


local function addlog(t, i)
	if i == false then fLog.write(t)
	else fLog.write(t.."\n") end
	fLog.flush()
end

local function openlog()
	fLog = fs.open(debug_path, "w") -- Global...
end

local function closelog()
	fLog.close()
	fLog = nil
end

local function restore()
	term.write = fOld.term.write
	term.clear = fOld.term.clear
	term.setCursorPos = fOld.term.setCursorPos
	term.clearLine = fOld.term.clearLine
	print = fOld.print
	write = fOld.write
	closelog()
	debug_path = nil
	fs.delete("debug_files/.launch")
	print("\n\n\nDebbuging finished!")
end

local function mkfunc()
	-- Open log
	openlog()
	
	--[[
		All global override functions go here.
	]]--
	function term.writeNew(t)
		addlog(t)
		return fOld.term.write(t)
	end
	
	term.write = term.writeNew
	
	function read(t)
		term.write = fOld.term.write
		
		local r
		
		if t == nil then
			r = fOld.read()
		else
			r = fOld.read(t)
		end
		
		term.write = term.writeNew
		addlog("[read("..tostring(t)..") = "..tostring(r).."]")
		return r
	end
	
	function print(t)
		local r = fOld.print(t)
		addlog("[print("..tostring(t)..") = "..tostring(r).."]")
		return r
	end
	
	function write(t)
		local r = fOld.write(t)
		addlog("[write("..tostring(t)..") = "..tostring(r).."]")
		return r
	end
	
	function term.clear()
		local r = fOld.term.clear()
		addlog("[term.clear() = "..tostring(r).."]")
		return r
	end
	
	function term.setCursorPos(a, B)/>/>/>/>/>/>/>/>
		local r = fOld.term.setCursorPos(a, B)/>/>/>/>/>/>/>/>
		addlog("[term.setCursorPos("..tostring(a)..", "..tostring(B)/>/>/>/>/>/>/>/>..") = "..tostring(r).."]")
		return r
	end
	
	function term.clearLine()
		local r = fOld.term.clearLine()
		addlog("[term.clearLine() = "..tostring(r).."]")
		return r
	end
end


if args[1] == "run" then
	debug_path = "debug_files/"..args[2]..".log" --Globalize args[2]
	
	term.clear()
	term.setCursorPos(1, 1)
	print("Debugging "..args[2]..".\n\nDo not terminate program, if you do, run \"debug restore\" to restore functions.\n\nPress any key to continue")
	
	local e = nil
	while(e ~= "char") do e = os.pullEvent("char") end --Wait for key
	
	term.clear()
	term.setCursorPos(1, 1)
	
	if(not fs.exists("debug_files")) then fs.makeDir("debug_files") end -- Check &amp; make "debug" dir
	
	mkfunc()
	
	local l = fs.open("debug_files/.launch", "w") -- Open temp launch file
	local s = "shell.run(\""..args[2].."\""-- Temp string
	
	for i = 3, #args do
		s = s..", \""..args[i].."\""
	end
	
	s = s..")"
	
	l.write(s)
	l.close()
	
	shell.run("debug_files/.launch") --Run app
	
	restore() -- Restore old functions
	return
end

if args[1] == "log" then
	if(not fs.exists("debug_files/"..args[2]..".log")) then print("No such file!") return end
	local f = fs.open("debug_files/"..args[2]..".log", "r") -- Open and print
	print(f.readAll())
	f.close()
	return
end

if args[1] == "restore" then
	restore() -- Restore
	return
end

print([[
	Usage:
	- debug run <program full path> [args]
	  Logs are saves in debug_files/<program name>.log
	- debug log <program name>
	  Prints a log
	- debug restore
	  Use if program was terminated or to manually restore write &amp; print functions
	  
	Debug by jesysthekiller, idea from urielsalis
	Version 1.1
]])
Changelog:
Spoiler
  • 1.0: Initial release
  • 1.1: Logging part of term.*, read, write, print


License:
SpoilerTHIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. Copy of this license.
jesusthekiller #2
Posted 16 April 2013 - 09:49 PM
Noone likes it? D:
theoriginalbit #3
Posted 16 April 2013 - 10:21 PM
Well I hope you made it better than urielsalis' one, it was riddled with bugs and problems.

Also all your functions that have this

local logf = fs.open(debug_path, "a")
logf.write(t.."\n")
logf.close()
you should just do this at the top of your program

local fLog = fs.open(debug_path, "a")
then do this when you want to add stuff to it

fLog.write(var..'\n')
fLog.flush()
that way it removes the constant opening and closing of the file each time write and print is used.

EDIT: Also you are better doign a term.write override than print and write, since they both use term.write

EDIT 2: Also by looking at the code, it seems to only log what is printed by the program, nothing more, to debug I want to know what all the functions I called are, not just the write and print calls since its rare that my problems are there…

Another problem if i do this

print(false)
your code will error saying attempt to concat boolean and string.
and this would also cause problems

print('This', ' is a multi', ' arg example')
would only print 'This'
your function should be

function print( ... )
jesusthekiller #4
Posted 17 April 2013 - 02:19 AM
Thanks for help! I'll improve it when I'll get home
jesusthekiller #5
Posted 17 April 2013 - 03:54 AM
Working on it, will make it real debugging software :3
jesusthekiller #6
Posted 17 April 2013 - 05:55 AM
Update 1.1 is out, added part of term API, logging read too.

Planning to log every function out there.
FuuuAInfiniteLoop(F.A.I.L) #7
Posted 17 April 2013 - 06:45 AM
Update 1.1 is out, added part of term API, logging read too.

Planning to log every function out there.
You can get all the functions if you do a recursive ipairs to the "_G" variable(without "")
theoriginalbit #8
Posted 17 April 2013 - 07:00 AM
-snip oops-
jesusthekiller #9
Posted 17 April 2013 - 07:34 AM
Update 1.1 is out, added part of term API, logging read too.

Planning to log every function out there.
You can get all the functions if you do a recursive ipairs to the "_G" variable(without "")
I'm not so advanced :P/> Gonna look it up.
Espen #10
Posted 17 April 2013 - 10:49 AM
You can get all the functions if you do a recursive ipairs to the "_G" variable(without "")
I'm not so advanced :P/> Gonna look it up.
Here's an example snippet:
-- Get parameters passed to program
local tArgs = { ... }
if #tArgs < 1 then
  print( "Usage:\n\t\t" .. shell.getRunningProgram() .. " [TABLE-/API-NAME]" )
  return
end

-- Get screen size (x is not needed)
local _, maxY = term.getSize()

-- Initialize line counter
local iLine = 1

-- Loop through all keys and values of the passed table
for k, v in pairs( _G[ tArgs[1] ] ) do
  -- Print "type : name"
  print( type(v) .. " : " .. k )

  -- If counter reaches screen height, pause until ENTER
  iLine = iLine + 1
  if iLine >= maxY - 1 then
    iLine = 1 -- Reset line counter
    read()  -- Pause, so to speak
  end
end
Bubba #11
Posted 17 April 2013 - 10:57 AM
Update 1.1 is out, added part of term API, logging read too.

Planning to log every function out there.
You can get all the functions if you do a recursive ipairs to the "_G" variable(without "")

Just a small correction: don't use ipairs. ipairs only does sequential order and will not give you anything for the _G table.
Espen #12
Posted 17 April 2013 - 12:15 PM
Just a small correction: don't use ipairs. ipairs only does sequential order and will not give you anything for the _G table.

What's much more important is that ipairs iterates through the table until it first encounters a non-integer index. only over integer indices. (edit: see theoriginalbit's second-next post)
That means with a table like this …
local tbl = { "apple", "orange", "banana", person = "peter", color = "red" }

… you'll only get this if you use ipairs
[1] -> "apple"
[2] -> "orange"
[3] -> "banana"

… whereas with pairs you'll get all of them:
[1] -> "apple"
[2] -> "orange"
[3] -> "banana"
["person"] -> "peter"
["color"] -> "red"
Edited on 17 April 2013 - 08:15 PM
Bubba #13
Posted 17 April 2013 - 12:19 PM
Just a small correction: don't use ipairs. ipairs only does sequential order and will not give you anything for the _G table.

What's much more important is that ipairs iterates through the table until it first encounters a non-integer index.
That means with a table like this …
local tbl = { "apple", "orange", "banana", person = "peter", color = "red" }

… you'll only get this if you use ipairs
[1] -> "apple"
[2] -> "orange"
[3] -> "banana"

… whereas with pairs you'll get all of them:
[1] -> "apple"
[2] -> "orange"
[3] -> "banana"
["person"] -> "peter"
["color"] -> "red"

Yup. So for the _G table, being COMPLETELY non-integer, you will get nothing.

Besides, I try to avoid ipairs where possible as it is rather antiquated in terms of performance in actual Lua (at least I believe I remember seeing a post about that somewhere). At least, that is my memory of it. It might not be performance but rather that it is being removed. Can't remember which.
FuuuAInfiniteLoop(F.A.I.L) #14
Posted 17 April 2013 - 12:28 PM
Update 1.1 is out, added part of term API, logging read too.

Planning to log every function out there.
You can get all the functions if you do a recursive ipairs to the "_G" variable(without "")

Just a small correction: don't use ipairs. ipairs only does sequential order and will not give you anything for the _G table.
Typo erros i meant pairs :)/> ialways confuse them

The list that i have(cause i was planning on making a new lang)
Spoiler->redstone->setBundledOutput
->redstone->getBundledInput
->redstone->testBundledInput
->redstone->getInput
->redstone->getBundledOutput
->redstone->getSides
->redstone->setOutput
->redstone->getOutput
->gps->locate
->keys->getName
->printError
->peripheral->call
->peripheral->getMethods
->peripheral->getType
->peripheral->isPresent
->peripheral->wrap
->assert
->getfenv
->bit->bxor
->bit->bor
->bit->blshift
->bit->blogic_rshift
->bit->brshift
->bit->band
->bit->bnot
->rawset
->tonumber
->loadstring
->error
->disk->setLabel
->disk->getLabel
->disk->hasAudio
->disk->eject
->disk->hasData
->disk->playAudio
->disk->getAudioTitle
->disk->isPresent
->disk->getDiskID
->disk->stopAudio
->disk->getMountPath
->disk->getSerial
->type
->coroutine->status
->coroutine->resume
->coroutine->create
->coroutine->yield
->coroutine->wrap
->coroutine->running
->tostring
->next
->unpack
->colours->combine
->colours->subtract
->colours->test
->pcall
->sleep
->loadfile
->math->deg
->math->fmod
->math->random
->math->asin
->math->max
->math->modf
->math->log10
->math->floor
->math->cosh
->math->ldexp
->math->log
->math->pow
->math->randomseed
->math->frexp
->math->abs
->math->tanh
->math->acos
->math->atan2
->math->tan
->math->min
->math->ceil
->math->sinh
->math->sqrt
->math->rad
->math->sin
->math->exp
->math->cos
->math->atan
->pairs
->fs->combine
->fs->isReadOnly
->fs->getSize
->fs->move
->fs->exists
->fs->copy
->fs->getFreeSpace
->fs->makeDir
->fs->delete
->fs->open
->fs->list
->fs->getDrive
->fs->getName
->fs->isDir
->rawget
->__inext
->read
->rednet->open
->rednet->isOpen
->rednet->announce
->rednet->close
->rednet->send
->rednet->broadcast
->rednet->run
->rednet->receive
->ipairs
->xpcall
->os->computerID
->os->pullEventRaw
->os->queueEvent
->os->version
->os->getComputerID
->os->getComputerLabel
->os->shutdown
->os->sleep
->os->unloadAPI
->os->pullEvent
->os->setAlarm
->os->computerLabel
->os->clock
->os->reboot
->os->time
->os->setComputerLabel
->os->startTimer
->os->loadAPI
->os->run
->help->setPath
->help->topics
->help->lookup
->help->path
->io->write
->io->read
->io->type
->io->open
->rawequal
->setfenv
->rs->setBundledOutput
->rs->getBundledInput
->rs->testBundledInput
->rs->getInput
->rs->getBundledOutput
->rs->getSides
->rs->setOutput
->rs->getOutput
->string->len
->string->find
->string->gmatch
->string->byte
->string->dump
->string->reverse
->string->upper
->string->format
->string->rep
->string->lower
->string->sub
->string->gsub
->string->match
->string->char
->write
->setmetatable
->print
->parallel->waitForAll
->parallel->waitForAny
->getmetatable
->table->maxn
->table->foreachi
->table->concat
->table->remove
->table->insert
->table->foreach
->table->sort
->table->getn
->textutils->pagedPrint
->textutils->unserialize
->textutils->formatTime
->textutils->pagedTabulate
->textutils->serialize
->textutils->slowWrite
->textutils->urlEncode
->textutils->tabulate
->textutils->slowPrint
->dofile
->term->scroll
->term->redirect
->term->setCursorPos
->term->write
->term->clear
->term->setTextColor
->term->isColor
->term->setBackgroundColour
->term->setTextColour
->term->isColour
->term->clearLine
->term->getSize
->term->native->write
->term->native->setBackgroundColor
->term->native->getCursorPos
->term->native->clear
->term->native->getSize
->term->native->setBackgroundColour
->term->native->setTextColor
->term->native->scroll
->term->native->setCursorPos
->term->native->isColour
->term->native->setTextColour
->term->native->setCursorBlink
->term->native->isColor
->term->native->clearLine
->term->getCursorPos
->term->restore
->term->setBackgroundColor
->term->setCursorBlink
->colors->combine
->colors->subtract
->colors->test
->vector->new
->select
->paintutils->drawPixel
->paintutils->drawLine
->paintutils->drawImage
->paintutils->loadImage
Bubba #15
Posted 17 April 2013 - 12:30 PM
What on earth is __inext?
theoriginalbit #16
Posted 17 April 2013 - 06:19 PM
What on earth is __inext?
Its for iterators/user with the next function iirc.
theoriginalbit #17
Posted 17 April 2013 - 06:24 PM
What's much more important is that ipairs iterates through the table until it first encounters a non-integer index.
It will continue beyond the key value, it just wont print any of them. So

local tbl = { "apple", "orange", person = "peter", color = "red", "banana" }
would still just output

[1] -> "apple"
[2] -> "orange"
[3] -> "banana"

EDIT: Whoops. Thought i hit edit, sorry for the double post.

EDIT 2:
The list that i have(cause i was planning on making a new lang)
Spoiler->redstone->setBundledOutput
->redstone->getBundledInput
->redstone->testBundledInput
->redstone->getInput
->redstone->getBundledOutput
->redstone->getSides
->redstone->setOutput
->redstone->getOutput
->gps->locate
->keys->getName
->printError
->peripheral->call
->peripheral->getMethods
->peripheral->getType
->peripheral->isPresent
->peripheral->wrap
->assert
->getfenv
->bit->bxor
->bit->bor
->bit->blshift
->bit->blogic_rshift
->bit->brshift
->bit->band
->bit->bnot
->rawset
->tonumber
->loadstring
->error
->disk->setLabel
->disk->getLabel
->disk->hasAudio
->disk->eject
->disk->hasData
->disk->playAudio
->disk->getAudioTitle
->disk->isPresent
->disk->getDiskID
->disk->stopAudio
->disk->getMountPath
->disk->getSerial
->type
->coroutine->status
->coroutine->resume
->coroutine->create
->coroutine->yield
->coroutine->wrap
->coroutine->running
->tostring
->next
->unpack
->colours->combine
->colours->subtract
->colours->test
->pcall
->sleep
->loadfile
->math->deg
->math->fmod
->math->random
->math->asin
->math->max
->math->modf
->math->log10
->math->floor
->math->cosh
->math->ldexp
->math->log
->math->pow
->math->randomseed
->math->frexp
->math->abs
->math->tanh
->math->acos
->math->atan2
->math->tan
->math->min
->math->ceil
->math->sinh
->math->sqrt
->math->rad
->math->sin
->math->exp
->math->cos
->math->atan
->pairs
->fs->combine
->fs->isReadOnly
->fs->getSize
->fs->move
->fs->exists
->fs->copy
->fs->getFreeSpace
->fs->makeDir
->fs->delete
->fs->open
->fs->list
->fs->getDrive
->fs->getName
->fs->isDir
->rawget
->__inext
->read
->rednet->open
->rednet->isOpen
->rednet->announce
->rednet->close
->rednet->send
->rednet->broadcast
->rednet->run
->rednet->receive
->ipairs
->xpcall
->os->computerID
->os->pullEventRaw
->os->queueEvent
->os->version
->os->getComputerID
->os->getComputerLabel
->os->shutdown
->os->sleep
->os->unloadAPI
->os->pullEvent
->os->setAlarm
->os->computerLabel
->os->clock
->os->reboot
->os->time
->os->setComputerLabel
->os->startTimer
->os->loadAPI
->os->run
->help->setPath
->help->topics
->help->lookup
->help->path
->io->write
->io->read
->io->type
->io->open
->rawequal
->setfenv
->rs->setBundledOutput
->rs->getBundledInput
->rs->testBundledInput
->rs->getInput
->rs->getBundledOutput
->rs->getSides
->rs->setOutput
->rs->getOutput
->string->len
->string->find
->string->gmatch
->string->byte
->string->dump
->string->reverse
->string->upper
->string->format
->string->rep
->string->lower
->string->sub
->string->gsub
->string->match
->string->char
->write
->setmetatable
->print
->parallel->waitForAll
->parallel->waitForAny
->getmetatable
->table->maxn
->table->foreachi
->table->concat
->table->remove
->table->insert
->table->foreach
->table->sort
->table->getn
->textutils->pagedPrint
->textutils->unserialize
->textutils->formatTime
->textutils->pagedTabulate
->textutils->serialize
->textutils->slowWrite
->textutils->urlEncode
->textutils->tabulate
->textutils->slowPrint
->dofile
->term->scroll
->term->redirect
->term->setCursorPos
->term->write
->term->clear
->term->setTextColor
->term->isColor
->term->setBackgroundColour
->term->setTextColour
->term->isColour
->term->clearLine
->term->getSize
->term->native->write
->term->native->setBackgroundColor
->term->native->getCursorPos
->term->native->clear
->term->native->getSize
->term->native->setBackgroundColour
->term->native->setTextColor
->term->native->scroll
->term->native->setCursorPos
->term->native->isColour
->term->native->setTextColour
->term->native->setCursorBlink
->term->native->isColor
->term->native->clearLine
->term->getCursorPos
->term->restore
->term->setBackgroundColor
->term->setCursorBlink
->colors->combine
->colors->subtract
->colors->test
->vector->new
->select
->paintutils->drawPixel
->paintutils->drawLine
->paintutils->drawImage
->paintutils->loadImage
Here is the list that I gathered of all the functions and variables in _G (except the table '_G' of course) back a while ago for GravityScore for the Sublime Text 2 plugin.
http://pastebin.com/XLpmeYmR
Espen #18
Posted 17 April 2013 - 10:09 PM
It will continue beyond the key value, it just wont print any of them.
You're absolutely correct, a lapsus on my part.
Thx for rectifying. :)/>
jesusthekiller #19
Posted 19 April 2013 - 09:02 AM
Project inactive for now - I have better things to do ;)/>

I'll continue coding after finishing my uOS and Pacman