rufus-lua-win 5.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +69 -0
- data/Rakefile +1 -0
- data/lib/rufus/lua/win.rb +18 -0
- data/lib/rufus/lua/win/version.rb +7 -0
- data/rufus-lua-win.gemspec +23 -0
- data/vendor/lua/bin/liblua.dll +0 -0
- data/vendor/lua/lib/lua/LuaXml.lua +119 -0
- data/vendor/lua/lib/lua/alien.lua +250 -0
- data/vendor/lua/lib/lua/alien/core.dll +0 -0
- data/vendor/lua/lib/lua/alien/struct.dll +0 -0
- data/vendor/lua/lib/lua/base.lua +536 -0
- data/vendor/lua/lib/lua/bin.lua +20 -0
- data/vendor/lua/lib/lua/bit.dll +0 -0
- data/vendor/lua/lib/lua/cdlua.dll +0 -0
- data/vendor/lua/lib/lua/cdluacontextplus.dll +0 -0
- data/vendor/lua/lib/lua/cdluagl.dll +0 -0
- data/vendor/lua/lib/lua/cdluaim.dll +0 -0
- data/vendor/lua/lib/lua/cdluapdf.dll +0 -0
- data/vendor/lua/lib/lua/copas.lua +543 -0
- data/vendor/lua/lib/lua/coxpcall.lua +57 -0
- data/vendor/lua/lib/lua/date.lua +745 -0
- data/vendor/lua/lib/lua/debug_ext.lua +84 -0
- data/vendor/lua/lib/lua/debug_init.lua +2 -0
- data/vendor/lua/lib/lua/des56.dll +0 -0
- data/vendor/lua/lib/lua/dist/config.lua +109 -0
- data/vendor/lua/lib/lua/dist/constraints.lua +271 -0
- data/vendor/lua/lib/lua/dist/depends.lua +601 -0
- data/vendor/lua/lib/lua/dist/git.lua +307 -0
- data/vendor/lua/lib/lua/dist/init.lua +278 -0
- data/vendor/lua/lib/lua/dist/manifest.lua +225 -0
- data/vendor/lua/lib/lua/dist/package.lua +583 -0
- data/vendor/lua/lib/lua/dist/sys.lua +367 -0
- data/vendor/lua/lib/lua/dist/utils.lua +130 -0
- data/vendor/lua/lib/lua/ex.dll +0 -0
- data/vendor/lua/lib/lua/fstable.lua +116 -0
- data/vendor/lua/lib/lua/getopt.lua +273 -0
- data/vendor/lua/lib/lua/git.lua +5 -0
- data/vendor/lua/lib/lua/git/core.dll +0 -0
- data/vendor/lua/lib/lua/git/objects.lua +121 -0
- data/vendor/lua/lib/lua/git/pack.lua +316 -0
- data/vendor/lua/lib/lua/git/protocol.lua +188 -0
- data/vendor/lua/lib/lua/git/repo.lua +283 -0
- data/vendor/lua/lib/lua/git/util.lua +233 -0
- data/vendor/lua/lib/lua/gzio.dll +0 -0
- data/vendor/lua/lib/lua/gzip.lua +81 -0
- data/vendor/lua/lib/lua/iconv.dll +0 -0
- data/vendor/lua/lib/lua/imlua.dll +0 -0
- data/vendor/lua/lib/lua/imlua_fftw.dll +0 -0
- data/vendor/lua/lib/lua/imlua_jp2.dll +0 -0
- data/vendor/lua/lib/lua/imlua_process.dll +0 -0
- data/vendor/lua/lib/lua/imlua_process_omp.dll +0 -0
- data/vendor/lua/lib/lua/io_ext.lua +115 -0
- data/vendor/lua/lib/lua/iuplua.dll +0 -0
- data/vendor/lua/lib/lua/iuplua_mglplot.dll +0 -0
- data/vendor/lua/lib/lua/iuplua_pplot.dll +0 -0
- data/vendor/lua/lib/lua/iupluacd.dll +0 -0
- data/vendor/lua/lib/lua/iupluacontrols.dll +0 -0
- data/vendor/lua/lib/lua/iupluagl.dll +0 -0
- data/vendor/lua/lib/lua/iupluaim.dll +0 -0
- data/vendor/lua/lib/lua/iupluaimglib.dll +0 -0
- data/vendor/lua/lib/lua/iupluatuio.dll +0 -0
- data/vendor/lua/lib/lua/lanes-keeper.lua +302 -0
- data/vendor/lua/lib/lua/lanes.lua +591 -0
- data/vendor/lua/lib/lua/lanes/core.dll +0 -0
- data/vendor/lua/lib/lua/lcs.lua +55 -0
- data/vendor/lua/lib/lua/lemock.lua +659 -0
- data/vendor/lua/lib/lua/lfs.dll +0 -0
- data/vendor/lua/lib/lua/list.lua +375 -0
- data/vendor/lua/lib/lua/logging.lua +189 -0
- data/vendor/lua/lib/lua/logging/console.lua +22 -0
- data/vendor/lua/lib/lua/logging/email.lua +44 -0
- data/vendor/lua/lib/lua/logging/file.lua +55 -0
- data/vendor/lua/lib/lua/logging/rolling_file.lua +81 -0
- data/vendor/lua/lib/lua/logging/socket.lua +35 -0
- data/vendor/lua/lib/lua/logging/sql.lua +64 -0
- data/vendor/lua/lib/lua/loop/base.lua +68 -0
- data/vendor/lua/lib/lua/loop/cached.lua +312 -0
- data/vendor/lua/lib/lua/loop/collection/MapWithArrayOfKeys.lua +64 -0
- data/vendor/lua/lib/lua/loop/collection/ObjectCache.lua +39 -0
- data/vendor/lua/lib/lua/loop/collection/OrderedSet.lua +164 -0
- data/vendor/lua/lib/lua/loop/collection/PriorityQueue.lua +86 -0
- data/vendor/lua/lib/lua/loop/collection/UnorderedArray.lua +32 -0
- data/vendor/lua/lib/lua/loop/collection/UnorderedArraySet.lua +56 -0
- data/vendor/lua/lib/lua/loop/compiler/Arguments.lua +108 -0
- data/vendor/lua/lib/lua/loop/compiler/Conditional.lua +50 -0
- data/vendor/lua/lib/lua/loop/compiler/Expression.lua +215 -0
- data/vendor/lua/lib/lua/loop/component/base.lua +221 -0
- data/vendor/lua/lib/lua/loop/component/contained.lua +71 -0
- data/vendor/lua/lib/lua/loop/component/dynamic.lua +223 -0
- data/vendor/lua/lib/lua/loop/component/intercepted.lua +354 -0
- data/vendor/lua/lib/lua/loop/component/wrapped.lua +195 -0
- data/vendor/lua/lib/lua/loop/debug/Inspector.lua +521 -0
- data/vendor/lua/lib/lua/loop/debug/Matcher.lua +192 -0
- data/vendor/lua/lib/lua/loop/debug/Verbose.lua +266 -0
- data/vendor/lua/lib/lua/loop/debug/Viewer.lua +200 -0
- data/vendor/lua/lib/lua/loop/multiple.lua +105 -0
- data/vendor/lua/lib/lua/loop/object/Exception.lua +57 -0
- data/vendor/lua/lib/lua/loop/object/Publisher.lua +43 -0
- data/vendor/lua/lib/lua/loop/object/Wrapper.lua +39 -0
- data/vendor/lua/lib/lua/loop/scoped.lua +585 -0
- data/vendor/lua/lib/lua/loop/serial/FileStream.lua +48 -0
- data/vendor/lua/lib/lua/loop/serial/Serializer.lua +291 -0
- data/vendor/lua/lib/lua/loop/serial/SocketStream.lua +51 -0
- data/vendor/lua/lib/lua/loop/serial/StringStream.lua +47 -0
- data/vendor/lua/lib/lua/loop/simple.lua +75 -0
- data/vendor/lua/lib/lua/loop/table.lua +71 -0
- data/vendor/lua/lib/lua/loop/thread/CoSocket.lua +416 -0
- data/vendor/lua/lib/lua/loop/thread/IOScheduler.lua +170 -0
- data/vendor/lua/lib/lua/loop/thread/Scheduler.lua +327 -0
- data/vendor/lua/lib/lua/loop/thread/SocketScheduler.lua +88 -0
- data/vendor/lua/lib/lua/loop/thread/Timer.lua +54 -0
- data/vendor/lua/lib/lua/lpeg.dll +0 -0
- data/vendor/lua/lib/lua/ltn12.lua +292 -0
- data/vendor/lua/lib/lua/luaXML_lib.dll +0 -0
- data/vendor/lua/lib/lua/luacurl.dll +0 -0
- data/vendor/lua/lib/lua/luadoc/config.lua +34 -0
- data/vendor/lua/lib/lua/luadoc/doclet/debug.lua +46 -0
- data/vendor/lua/lib/lua/luadoc/doclet/formatter.lua +84 -0
- data/vendor/lua/lib/lua/luadoc/doclet/html.lua +289 -0
- data/vendor/lua/lib/lua/luadoc/doclet/html/file.lp +113 -0
- data/vendor/lua/lib/lua/luadoc/doclet/html/function.lp +64 -0
- data/vendor/lua/lib/lua/luadoc/doclet/html/index.lp +70 -0
- data/vendor/lua/lib/lua/luadoc/doclet/html/luadoc.css +286 -0
- data/vendor/lua/lib/lua/luadoc/doclet/html/menu.lp +55 -0
- data/vendor/lua/lib/lua/luadoc/doclet/html/module.lp +109 -0
- data/vendor/lua/lib/lua/luadoc/doclet/html/table.lp +15 -0
- data/vendor/lua/lib/lua/luadoc/doclet/raw.lua +12 -0
- data/vendor/lua/lib/lua/luadoc/init.lua +58 -0
- data/vendor/lua/lib/lua/luadoc/lp.lua +130 -0
- data/vendor/lua/lib/lua/luadoc/taglet/standard.lua +495 -0
- data/vendor/lua/lib/lua/luadoc/taglet/standard/tags.lua +171 -0
- data/vendor/lua/lib/lua/luadoc/util.lua +233 -0
- data/vendor/lua/lib/lua/luagl.dll +0 -0
- data/vendor/lua/lib/lua/luaglu.dll +0 -0
- data/vendor/lua/lib/lua/luaidl.lua +113 -0
- data/vendor/lua/lib/lua/luaidl/lex.lua +793 -0
- data/vendor/lua/lib/lua/luaidl/pre.lua +149 -0
- data/vendor/lua/lib/lua/luaidl/sin.lua +3631 -0
- data/vendor/lua/lib/lua/luarocks/add.lua +108 -0
- data/vendor/lua/lib/lua/luarocks/admin_remove.lua +87 -0
- data/vendor/lua/lib/lua/luarocks/build.lua +330 -0
- data/vendor/lua/lib/lua/luarocks/build/builtin.lua +253 -0
- data/vendor/lua/lib/lua/luarocks/build/cmake.lua +54 -0
- data/vendor/lua/lib/lua/luarocks/build/command.lua +32 -0
- data/vendor/lua/lib/lua/luarocks/build/make.lua +92 -0
- data/vendor/lua/lib/lua/luarocks/cache.lua +85 -0
- data/vendor/lua/lib/lua/luarocks/cfg.lua +449 -0
- data/vendor/lua/lib/lua/luarocks/command_line.lua +163 -0
- data/vendor/lua/lib/lua/luarocks/deps.lua +654 -0
- data/vendor/lua/lib/lua/luarocks/dir.lua +69 -0
- data/vendor/lua/lib/lua/luarocks/download.lua +90 -0
- data/vendor/lua/lib/lua/luarocks/fetch.lua +321 -0
- data/vendor/lua/lib/lua/luarocks/fetch/cvs.lua +44 -0
- data/vendor/lua/lib/lua/luarocks/fetch/git.lua +81 -0
- data/vendor/lua/lib/lua/luarocks/fetch/git_file.lua +17 -0
- data/vendor/lua/lib/lua/luarocks/fetch/hg.lua +54 -0
- data/vendor/lua/lib/lua/luarocks/fetch/sscm.lua +42 -0
- data/vendor/lua/lib/lua/luarocks/fetch/svn.lua +53 -0
- data/vendor/lua/lib/lua/luarocks/fs.lua +40 -0
- data/vendor/lua/lib/lua/luarocks/fs/lua.lua +676 -0
- data/vendor/lua/lib/lua/luarocks/fs/unix.lua +88 -0
- data/vendor/lua/lib/lua/luarocks/fs/unix/tools.lua +325 -0
- data/vendor/lua/lib/lua/luarocks/fs/win32.lua +107 -0
- data/vendor/lua/lib/lua/luarocks/fs/win32/tools.lua +334 -0
- data/vendor/lua/lib/lua/luarocks/help.lua +101 -0
- data/vendor/lua/lib/lua/luarocks/index.lua +172 -0
- data/vendor/lua/lib/lua/luarocks/install.lua +151 -0
- data/vendor/lua/lib/lua/luarocks/list.lua +35 -0
- data/vendor/lua/lib/lua/luarocks/loader.lua +228 -0
- data/vendor/lua/lib/lua/luarocks/make.lua +71 -0
- data/vendor/lua/lib/lua/luarocks/make_manifest.lua +34 -0
- data/vendor/lua/lib/lua/luarocks/manif.lua +360 -0
- data/vendor/lua/lib/lua/luarocks/manif_core.lua +75 -0
- data/vendor/lua/lib/lua/luarocks/new_version.lua +141 -0
- data/vendor/lua/lib/lua/luarocks/pack.lua +205 -0
- data/vendor/lua/lib/lua/luarocks/path.lua +315 -0
- data/vendor/lua/lib/lua/luarocks/persist.lua +173 -0
- data/vendor/lua/lib/lua/luarocks/refresh_cache.lua +30 -0
- data/vendor/lua/lib/lua/luarocks/remove.lua +135 -0
- data/vendor/lua/lib/lua/luarocks/rep.lua +313 -0
- data/vendor/lua/lib/lua/luarocks/require.lua +6 -0
- data/vendor/lua/lib/lua/luarocks/search.lua +399 -0
- data/vendor/lua/lib/lua/luarocks/show.lua +138 -0
- data/vendor/lua/lib/lua/luarocks/site_config.lua +23 -0
- data/vendor/lua/lib/lua/luarocks/tools/patch.lua +712 -0
- data/vendor/lua/lib/lua/luarocks/tools/tar.lua +144 -0
- data/vendor/lua/lib/lua/luarocks/tools/zip.lua +245 -0
- data/vendor/lua/lib/lua/luarocks/type_check.lua +267 -0
- data/vendor/lua/lib/lua/luarocks/unpack.lua +151 -0
- data/vendor/lua/lib/lua/luarocks/util.lua +420 -0
- data/vendor/lua/lib/lua/luarocks/validate.lua +164 -0
- data/vendor/lua/lib/lua/luars232.dll +0 -0
- data/vendor/lua/lib/lua/luasql/mysql.dll +0 -0
- data/vendor/lua/lib/lua/luasql/postgres.dll +0 -0
- data/vendor/lua/lib/lua/luasql/sqlite3.dll +0 -0
- data/vendor/lua/lib/lua/luaunit.lua +601 -0
- data/vendor/lua/lib/lua/lxp.dll +0 -0
- data/vendor/lua/lib/lua/lxp/lom.lua +60 -0
- data/vendor/lua/lib/lua/math_ext.lua +27 -0
- data/vendor/lua/lib/lua/mbox.lua +53 -0
- data/vendor/lua/lib/lua/md5.lua +19 -0
- data/vendor/lua/lib/lua/md5/core.dll +0 -0
- data/vendor/lua/lib/lua/metalua.lua +0 -0
- data/vendor/lua/lib/lua/metalua/ast_to_string.mlua +553 -0
- data/vendor/lua/lib/lua/metalua/base.lua +104 -0
- data/vendor/lua/lib/lua/metalua/bytecode.lua +0 -0
- data/vendor/lua/lib/lua/metalua/clopts.mlua +204 -0
- data/vendor/lua/lib/lua/metalua/compiler.lua +3 -0
- data/vendor/lua/lib/lua/metalua/dollar.mlua +24 -0
- data/vendor/lua/lib/lua/metalua/extension/H-runtime.mlua +216 -0
- data/vendor/lua/lib/lua/metalua/extension/H.mlua +22 -0
- data/vendor/lua/lib/lua/metalua/extension/anaphoric.mlua +54 -0
- data/vendor/lua/lib/lua/metalua/extension/clist.mlua +149 -0
- data/vendor/lua/lib/lua/metalua/extension/continue.mlua +53 -0
- data/vendor/lua/lib/lua/metalua/extension/localin.mlua +2 -0
- data/vendor/lua/lib/lua/metalua/extension/log.mlua +39 -0
- data/vendor/lua/lib/lua/metalua/extension/match.mlua +374 -0
- data/vendor/lua/lib/lua/metalua/extension/ternary.mlua +10 -0
- data/vendor/lua/lib/lua/metalua/extension/trycatch.mlua +189 -0
- data/vendor/lua/lib/lua/metalua/extension/types-runtime.mlua +159 -0
- data/vendor/lua/lib/lua/metalua/extension/types.mlua +352 -0
- data/vendor/lua/lib/lua/metalua/extension/withdo.mlua +30 -0
- data/vendor/lua/lib/lua/metalua/extension/xglobal-runtime.lua +41 -0
- data/vendor/lua/lib/lua/metalua/extension/xglobal.mlua +20 -0
- data/vendor/lua/lib/lua/metalua/extension/xloop.mlua +100 -0
- data/vendor/lua/lib/lua/metalua/extension/xmatch.mlua +216 -0
- data/vendor/lua/lib/lua/metalua/metaloop.mlua +76 -0
- data/vendor/lua/lib/lua/metalua/mlc.lua +0 -0
- data/vendor/lua/lib/lua/metalua/mlc_xcall.lua +119 -0
- data/vendor/lua/lib/lua/metalua/mlp.lua +0 -0
- data/vendor/lua/lib/lua/metalua/package2.lua +101 -0
- data/vendor/lua/lib/lua/metalua/runtime.lua +3 -0
- data/vendor/lua/lib/lua/metalua/string2.lua +44 -0
- data/vendor/lua/lib/lua/metalua/table2.lua +372 -0
- data/vendor/lua/lib/lua/metalua/walk.mlua +304 -0
- data/vendor/lua/lib/lua/metalua/walk/bindings.mlua +41 -0
- data/vendor/lua/lib/lua/metalua/walk/id.mlua +186 -0
- data/vendor/lua/lib/lua/metalua/walk/scope.lua +54 -0
- data/vendor/lua/lib/lua/mime.lua +87 -0
- data/vendor/lua/lib/lua/mime/core.dll +0 -0
- data/vendor/lua/lib/lua/mobdebug.lua +1484 -0
- data/vendor/lua/lib/lua/modules.lua +16 -0
- data/vendor/lua/lib/lua/object.lua +56 -0
- data/vendor/lua/lib/lua/oil/Exception.lua +26 -0
- data/vendor/lua/lib/lua/oil/arch.lua +27 -0
- data/vendor/lua/lib/lua/oil/arch/basic/client.lua +29 -0
- data/vendor/lua/lib/lua/oil/arch/basic/common.lua +13 -0
- data/vendor/lua/lib/lua/oil/arch/basic/server.lua +27 -0
- data/vendor/lua/lib/lua/oil/arch/cooperative/common.lua +10 -0
- data/vendor/lua/lib/lua/oil/arch/cooperative/server.lua +16 -0
- data/vendor/lua/lib/lua/oil/arch/corba/client.lua +39 -0
- data/vendor/lua/lib/lua/oil/arch/corba/common.lua +58 -0
- data/vendor/lua/lib/lua/oil/arch/corba/intercepted/client.lua +9 -0
- data/vendor/lua/lib/lua/oil/arch/corba/intercepted/server.lua +9 -0
- data/vendor/lua/lib/lua/oil/arch/corba/server.lua +35 -0
- data/vendor/lua/lib/lua/oil/arch/ludo/byref.lua +18 -0
- data/vendor/lua/lib/lua/oil/arch/ludo/client.lua +19 -0
- data/vendor/lua/lib/lua/oil/arch/ludo/common.lua +18 -0
- data/vendor/lua/lib/lua/oil/arch/ludo/server.lua +19 -0
- data/vendor/lua/lib/lua/oil/arch/typed/client.lua +27 -0
- data/vendor/lua/lib/lua/oil/arch/typed/common.lua +9 -0
- data/vendor/lua/lib/lua/oil/arch/typed/server.lua +18 -0
- data/vendor/lua/lib/lua/oil/assert.lua +87 -0
- data/vendor/lua/lib/lua/oil/builder.lua +45 -0
- data/vendor/lua/lib/lua/oil/builder/basic/client.lua +31 -0
- data/vendor/lua/lib/lua/oil/builder/basic/common.lua +11 -0
- data/vendor/lua/lib/lua/oil/builder/basic/server.lua +13 -0
- data/vendor/lua/lib/lua/oil/builder/cooperative/common.lua +11 -0
- data/vendor/lua/lib/lua/oil/builder/cooperative/server.lua +11 -0
- data/vendor/lua/lib/lua/oil/builder/corba/client.lua +13 -0
- data/vendor/lua/lib/lua/oil/builder/corba/common.lua +24 -0
- data/vendor/lua/lib/lua/oil/builder/corba/gencode.lua +13 -0
- data/vendor/lua/lib/lua/oil/builder/corba/intercepted/client.lua +11 -0
- data/vendor/lua/lib/lua/oil/builder/corba/intercepted/server.lua +11 -0
- data/vendor/lua/lib/lua/oil/builder/corba/server.lua +13 -0
- data/vendor/lua/lib/lua/oil/builder/lua/client.lua +11 -0
- data/vendor/lua/lib/lua/oil/builder/lua/server.lua +12 -0
- data/vendor/lua/lib/lua/oil/builder/ludo/byref.lua +13 -0
- data/vendor/lua/lib/lua/oil/builder/ludo/client.lua +13 -0
- data/vendor/lua/lib/lua/oil/builder/ludo/common.lua +14 -0
- data/vendor/lua/lib/lua/oil/builder/ludo/server.lua +13 -0
- data/vendor/lua/lib/lua/oil/builder/typed/client.lua +16 -0
- data/vendor/lua/lib/lua/oil/builder/typed/server.lua +12 -0
- data/vendor/lua/lib/lua/oil/compat.lua +846 -0
- data/vendor/lua/lib/lua/oil/component.lua +1 -0
- data/vendor/lua/lib/lua/oil/corba/giop.lua +301 -0
- data/vendor/lua/lib/lua/oil/corba/giop/Codec.lua +1568 -0
- data/vendor/lua/lib/lua/oil/corba/giop/CodecGen.lua +589 -0
- data/vendor/lua/lib/lua/oil/corba/giop/Exception.lua +25 -0
- data/vendor/lua/lib/lua/oil/corba/giop/Indexer.lua +63 -0
- data/vendor/lua/lib/lua/oil/corba/giop/Listener.lua +343 -0
- data/vendor/lua/lib/lua/oil/corba/giop/Messenger.lua +228 -0
- data/vendor/lua/lib/lua/oil/corba/giop/Referrer.lua +180 -0
- data/vendor/lua/lib/lua/oil/corba/giop/Requester.lua +462 -0
- data/vendor/lua/lib/lua/oil/corba/idl.lua +597 -0
- data/vendor/lua/lib/lua/oil/corba/idl/Compiler.lua +133 -0
- data/vendor/lua/lib/lua/oil/corba/idl/Importer.lua +235 -0
- data/vendor/lua/lib/lua/oil/corba/idl/Indexer.lua +95 -0
- data/vendor/lua/lib/lua/oil/corba/idl/Registry.lua +1821 -0
- data/vendor/lua/lib/lua/oil/corba/idl/ir.lua +847 -0
- data/vendor/lua/lib/lua/oil/corba/idl/sysex.lua +21 -0
- data/vendor/lua/lib/lua/oil/corba/iiop/Profiler.lua +200 -0
- data/vendor/lua/lib/lua/oil/corba/intercepted/Listener.lua +158 -0
- data/vendor/lua/lib/lua/oil/corba/intercepted/Requester.lua +181 -0
- data/vendor/lua/lib/lua/oil/corba/services/event.lua +126 -0
- data/vendor/lua/lib/lua/oil/corba/services/event/ConsumerAdmin.lua +50 -0
- data/vendor/lua/lib/lua/oil/corba/services/event/EventFactory.lua +15 -0
- data/vendor/lua/lib/lua/oil/corba/services/event/EventQueue.lua +37 -0
- data/vendor/lua/lib/lua/oil/corba/services/event/ProxyPushConsumer.lua +75 -0
- data/vendor/lua/lib/lua/oil/corba/services/event/ProxyPushSupplier.lua +62 -0
- data/vendor/lua/lib/lua/oil/corba/services/event/SingleDeferredDispatcher.lua +60 -0
- data/vendor/lua/lib/lua/oil/corba/services/event/SingleSynchronousDispatcher.lua +39 -0
- data/vendor/lua/lib/lua/oil/corba/services/event/SupplierAdmin.lua +50 -0
- data/vendor/lua/lib/lua/oil/corba/services/naming.lua +436 -0
- data/vendor/lua/lib/lua/oil/kernel/base/Acceptor.lua +268 -0
- data/vendor/lua/lib/lua/oil/kernel/base/Channels.lua +121 -0
- data/vendor/lua/lib/lua/oil/kernel/base/Connector.lua +147 -0
- data/vendor/lua/lib/lua/oil/kernel/base/Dispatcher.lua +99 -0
- data/vendor/lua/lib/lua/oil/kernel/base/Proxies.lua +86 -0
- data/vendor/lua/lib/lua/oil/kernel/base/Proxies/asynchronous.lua +56 -0
- data/vendor/lua/lib/lua/oil/kernel/base/Proxies/protected.lua +17 -0
- data/vendor/lua/lib/lua/oil/kernel/base/Proxies/synchronous.lua +17 -0
- data/vendor/lua/lib/lua/oil/kernel/base/Proxies/utils.lua +29 -0
- data/vendor/lua/lib/lua/oil/kernel/base/Receiver.lua +110 -0
- data/vendor/lua/lib/lua/oil/kernel/base/Servants.lua +207 -0
- data/vendor/lua/lib/lua/oil/kernel/base/Sockets.lua +44 -0
- data/vendor/lua/lib/lua/oil/kernel/cooperative/Receiver.lua +139 -0
- data/vendor/lua/lib/lua/oil/kernel/intercepted/Listener.lua +47 -0
- data/vendor/lua/lib/lua/oil/kernel/intercepted/Requester.lua +58 -0
- data/vendor/lua/lib/lua/oil/kernel/lua/Dispatcher.lua +76 -0
- data/vendor/lua/lib/lua/oil/kernel/lua/Proxies.lua +69 -0
- data/vendor/lua/lib/lua/oil/kernel/typed/Dispatcher.lua +91 -0
- data/vendor/lua/lib/lua/oil/kernel/typed/Proxies.lua +153 -0
- data/vendor/lua/lib/lua/oil/kernel/typed/Servants.lua +137 -0
- data/vendor/lua/lib/lua/oil/ludo/Codec.lua +66 -0
- data/vendor/lua/lib/lua/oil/ludo/CodecByRef.lua +103 -0
- data/vendor/lua/lib/lua/oil/ludo/Listener.lua +151 -0
- data/vendor/lua/lib/lua/oil/ludo/Referrer.lua +72 -0
- data/vendor/lua/lib/lua/oil/ludo/Requester.lua +107 -0
- data/vendor/lua/lib/lua/oil/oo.lua +1 -0
- data/vendor/lua/lib/lua/oil/port.lua +1 -0
- data/vendor/lua/lib/lua/oil/properties.lua +57 -0
- data/vendor/lua/lib/lua/oil/verbose.lua +133 -0
- data/vendor/lua/lib/lua/package_ext.lua +15 -0
- data/vendor/lua/lib/lua/parser.lua +268 -0
- data/vendor/lua/lib/lua/pl/Date.lua +555 -0
- data/vendor/lua/lib/lua/pl/List.lua +613 -0
- data/vendor/lua/lib/lua/pl/Map.lua +113 -0
- data/vendor/lua/lib/lua/pl/MultiMap.lua +62 -0
- data/vendor/lua/lib/lua/pl/OrderedMap.lua +151 -0
- data/vendor/lua/lib/lua/pl/Set.lua +153 -0
- data/vendor/lua/lib/lua/pl/app.lua +165 -0
- data/vendor/lua/lib/lua/pl/array2d.lua +501 -0
- data/vendor/lua/lib/lua/pl/class.lua +180 -0
- data/vendor/lua/lib/lua/pl/comprehension.lua +286 -0
- data/vendor/lua/lib/lua/pl/config.lua +176 -0
- data/vendor/lua/lib/lua/pl/data.lua +606 -0
- data/vendor/lua/lib/lua/pl/dir.lua +475 -0
- data/vendor/lua/lib/lua/pl/file.lua +70 -0
- data/vendor/lua/lib/lua/pl/func.lua +376 -0
- data/vendor/lua/lib/lua/pl/init.lua +68 -0
- data/vendor/lua/lib/lua/pl/input.lua +173 -0
- data/vendor/lua/lib/lua/pl/lapp.lua +407 -0
- data/vendor/lua/lib/lua/pl/lexer.lua +456 -0
- data/vendor/lua/lib/lua/pl/luabalanced.lua +264 -0
- data/vendor/lua/lib/lua/pl/operator.lua +201 -0
- data/vendor/lua/lib/lua/pl/path.lua +398 -0
- data/vendor/lua/lib/lua/pl/permute.lua +63 -0
- data/vendor/lua/lib/lua/pl/platf/luajava.lua +101 -0
- data/vendor/lua/lib/lua/pl/pretty.lua +285 -0
- data/vendor/lua/lib/lua/pl/seq.lua +551 -0
- data/vendor/lua/lib/lua/pl/sip.lua +344 -0
- data/vendor/lua/lib/lua/pl/strict.lua +70 -0
- data/vendor/lua/lib/lua/pl/stringio.lua +158 -0
- data/vendor/lua/lib/lua/pl/stringx.lua +440 -0
- data/vendor/lua/lib/lua/pl/tablex.lua +817 -0
- data/vendor/lua/lib/lua/pl/template.lua +103 -0
- data/vendor/lua/lib/lua/pl/test.lua +135 -0
- data/vendor/lua/lib/lua/pl/text.lua +243 -0
- data/vendor/lua/lib/lua/pl/utils.lua +550 -0
- data/vendor/lua/lib/lua/pl/xml.lua +689 -0
- data/vendor/lua/lib/lua/profiler.dll +0 -0
- data/vendor/lua/lib/lua/re.lua +248 -0
- data/vendor/lua/lib/lua/rex_onig.dll +0 -0
- data/vendor/lua/lib/lua/rex_pcre.dll +0 -0
- data/vendor/lua/lib/lua/rex_posix.dll +0 -0
- data/vendor/lua/lib/lua/rings.dll +0 -0
- data/vendor/lua/lib/lua/serialize.lua +193 -0
- data/vendor/lua/lib/lua/set.lua +149 -0
- data/vendor/lua/lib/lua/socket.lua +133 -0
- data/vendor/lua/lib/lua/socket/core.dll +0 -0
- data/vendor/lua/lib/lua/socket/ftp.lua +281 -0
- data/vendor/lua/lib/lua/socket/http.lua +350 -0
- data/vendor/lua/lib/lua/socket/smtp.lua +251 -0
- data/vendor/lua/lib/lua/socket/tp.lua +123 -0
- data/vendor/lua/lib/lua/socket/url.lua +297 -0
- data/vendor/lua/lib/lua/ssl.dll +0 -0
- data/vendor/lua/lib/lua/ssl.lua +93 -0
- data/vendor/lua/lib/lua/ssl/https.lua +138 -0
- data/vendor/lua/lib/lua/stable.lua +28 -0
- data/vendor/lua/lib/lua/std.lua +16 -0
- data/vendor/lua/lib/lua/strbuf.lua +32 -0
- data/vendor/lua/lib/lua/strict.lua +45 -0
- data/vendor/lua/lib/lua/string_ext.lua +274 -0
- data/vendor/lua/lib/lua/table_ext.lua +117 -0
- data/vendor/lua/lib/lua/tar.lua +262 -0
- data/vendor/lua/lib/lua/task.dll +0 -0
- data/vendor/lua/lib/lua/tree.lua +81 -0
- data/vendor/lua/lib/lua/unicode.dll +0 -0
- data/vendor/lua/lib/lua/verbose_require.lua +11 -0
- data/vendor/lua/lib/lua/vstruct.lua +86 -0
- data/vendor/lua/lib/lua/vstruct/ast.lua +192 -0
- data/vendor/lua/lib/lua/vstruct/ast/Bitpack.lua +33 -0
- data/vendor/lua/lib/lua/vstruct/ast/Generator.lua +174 -0
- data/vendor/lua/lib/lua/vstruct/ast/IO.lua +45 -0
- data/vendor/lua/lib/lua/vstruct/ast/List.lua +56 -0
- data/vendor/lua/lib/lua/vstruct/ast/Name.lua +20 -0
- data/vendor/lua/lib/lua/vstruct/ast/Repeat.lua +23 -0
- data/vendor/lua/lib/lua/vstruct/ast/Root.lua +19 -0
- data/vendor/lua/lib/lua/vstruct/ast/Table.lua +65 -0
- data/vendor/lua/lib/lua/vstruct/cursor.lua +81 -0
- data/vendor/lua/lib/lua/vstruct/io.lua +45 -0
- data/vendor/lua/lib/lua/vstruct/io/a.lua +24 -0
- data/vendor/lua/lib/lua/vstruct/io/b.lua +28 -0
- data/vendor/lua/lib/lua/vstruct/io/bigendian.lua +21 -0
- data/vendor/lua/lib/lua/vstruct/io/c.lua +25 -0
- data/vendor/lua/lib/lua/vstruct/io/defaults.lua +24 -0
- data/vendor/lua/lib/lua/vstruct/io/endianness.lua +41 -0
- data/vendor/lua/lib/lua/vstruct/io/f.lua +129 -0
- data/vendor/lua/lib/lua/vstruct/io/hostendian.lua +21 -0
- data/vendor/lua/lib/lua/vstruct/io/i.lua +42 -0
- data/vendor/lua/lib/lua/vstruct/io/littleendian.lua +21 -0
- data/vendor/lua/lib/lua/vstruct/io/m.lua +62 -0
- data/vendor/lua/lib/lua/vstruct/io/p.lua +23 -0
- data/vendor/lua/lib/lua/vstruct/io/s.lua +27 -0
- data/vendor/lua/lib/lua/vstruct/io/seekb.lua +18 -0
- data/vendor/lua/lib/lua/vstruct/io/seekf.lua +18 -0
- data/vendor/lua/lib/lua/vstruct/io/seekto.lua +18 -0
- data/vendor/lua/lib/lua/vstruct/io/u.lua +54 -0
- data/vendor/lua/lib/lua/vstruct/io/x.lua +34 -0
- data/vendor/lua/lib/lua/vstruct/io/z.lua +63 -0
- data/vendor/lua/lib/lua/vstruct/lexer.lua +100 -0
- data/vendor/lua/lib/lua/vstruct/pack.lua +142 -0
- data/vendor/lua/lib/lua/vstruct/test.lua +47 -0
- data/vendor/lua/lib/lua/vstruct/test/basic.lua +73 -0
- data/vendor/lua/lib/lua/vstruct/test/common.lua +100 -0
- data/vendor/lua/lib/lua/vstruct/test/fp-bigendian.lua +56 -0
- data/vendor/lua/lib/lua/vstruct/test/fp-littleendian.lua +56 -0
- data/vendor/lua/lib/lua/vstruct/test/struct-test-gen.lua +1230 -0
- data/vendor/lua/lib/lua/vstruct/unpack.lua +126 -0
- data/vendor/lua/lib/lua/wx.dll +0 -0
- data/vendor/lua/lib/lua/xml.lua +75 -0
- data/vendor/lua/lib/lua/zip.dll +0 -0
- data/vendor/lua/lib/lua/zlib.dll +0 -0
- metadata +529 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
--------------------------------------------------------------------------------
|
|
2
|
+
--
|
|
3
|
+
-- Scopes: this library helps keeping track of identifier scopes,
|
|
4
|
+
-- typically in code walkers.
|
|
5
|
+
--
|
|
6
|
+
-- * scope:new() returns a new scope instance s
|
|
7
|
+
--
|
|
8
|
+
-- * s:push() bookmarks the current set of variables, so the it can be
|
|
9
|
+
-- retrieved next time a s:pop() is performed.
|
|
10
|
+
--
|
|
11
|
+
-- * s:pop() retrieves the last state saved by s:push(). Calls to
|
|
12
|
+
-- :push() and :pop() can be nested as deep as one wants.
|
|
13
|
+
--
|
|
14
|
+
-- * s:add(var_list, val) adds new variable names (stirng) into the
|
|
15
|
+
-- scope, as keys. val is the (optional) value associated with them:
|
|
16
|
+
-- it allows to attach arbitrary information to variables, e.g. the
|
|
17
|
+
-- statement or expression that created them.
|
|
18
|
+
--
|
|
19
|
+
-- * s:push(var_list, val) is a shortcut for
|
|
20
|
+
-- s:push(); s:add(var_list, val).
|
|
21
|
+
--
|
|
22
|
+
-- * s.current is the current scope, a table with variable names as
|
|
23
|
+
-- keys and their associated value val (or 'true') as value.
|
|
24
|
+
--
|
|
25
|
+
--------------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
scope = { }
|
|
28
|
+
scope.__index = scope
|
|
29
|
+
|
|
30
|
+
function scope:new()
|
|
31
|
+
local ret = { current = { } }
|
|
32
|
+
ret.stack = { ret.current }
|
|
33
|
+
setmetatable (ret, self)
|
|
34
|
+
return ret
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
function scope:push(...)
|
|
38
|
+
table.insert (self.stack, table.shallow_copy (self.current))
|
|
39
|
+
if ... then return self:add(...) end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
function scope:pop()
|
|
43
|
+
self.current = table.remove (self.stack)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
function scope:add (vars, val)
|
|
47
|
+
val = val or true
|
|
48
|
+
for i, id in ipairs (vars) do
|
|
49
|
+
assert(id.tag=='Id' or id.tag=='Dots' and i==#vars)
|
|
50
|
+
if id.tag=='Id' then self.current[id[1]] = val end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
return scope
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
-----------------------------------------------------------------------------
|
|
2
|
+
-- MIME support for the Lua language.
|
|
3
|
+
-- Author: Diego Nehab
|
|
4
|
+
-- Conforming to RFCs 2045-2049
|
|
5
|
+
-- RCS ID: $Id$
|
|
6
|
+
-----------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
-----------------------------------------------------------------------------
|
|
9
|
+
-- Declare module and import dependencies
|
|
10
|
+
-----------------------------------------------------------------------------
|
|
11
|
+
local base = _G
|
|
12
|
+
local ltn12 = require("ltn12")
|
|
13
|
+
local mime = require("mime.core")
|
|
14
|
+
local io = require("io")
|
|
15
|
+
local string = require("string")
|
|
16
|
+
module("mime")
|
|
17
|
+
|
|
18
|
+
-- encode, decode and wrap algorithm tables
|
|
19
|
+
encodet = {}
|
|
20
|
+
decodet = {}
|
|
21
|
+
wrapt = {}
|
|
22
|
+
|
|
23
|
+
-- creates a function that chooses a filter by name from a given table
|
|
24
|
+
local function choose(table)
|
|
25
|
+
return function(name, opt1, opt2)
|
|
26
|
+
if base.type(name) ~= "string" then
|
|
27
|
+
name, opt1, opt2 = "default", name, opt1
|
|
28
|
+
end
|
|
29
|
+
local f = table[name or "nil"]
|
|
30
|
+
if not f then
|
|
31
|
+
base.error("unknown key (" .. base.tostring(name) .. ")", 3)
|
|
32
|
+
else return f(opt1, opt2) end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
-- define the encoding filters
|
|
37
|
+
encodet['base64'] = function()
|
|
38
|
+
return ltn12.filter.cycle(b64, "")
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
encodet['quoted-printable'] = function(mode)
|
|
42
|
+
return ltn12.filter.cycle(qp, "",
|
|
43
|
+
(mode == "binary") and "=0D=0A" or "\r\n")
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
-- define the decoding filters
|
|
47
|
+
decodet['base64'] = function()
|
|
48
|
+
return ltn12.filter.cycle(unb64, "")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
decodet['quoted-printable'] = function()
|
|
52
|
+
return ltn12.filter.cycle(unqp, "")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
local function format(chunk)
|
|
56
|
+
if chunk then
|
|
57
|
+
if chunk == "" then return "''"
|
|
58
|
+
else return string.len(chunk) end
|
|
59
|
+
else return "nil" end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
-- define the line-wrap filters
|
|
63
|
+
wrapt['text'] = function(length)
|
|
64
|
+
length = length or 76
|
|
65
|
+
return ltn12.filter.cycle(wrp, length, length)
|
|
66
|
+
end
|
|
67
|
+
wrapt['base64'] = wrapt['text']
|
|
68
|
+
wrapt['default'] = wrapt['text']
|
|
69
|
+
|
|
70
|
+
wrapt['quoted-printable'] = function()
|
|
71
|
+
return ltn12.filter.cycle(qpwrp, 76, 76)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
-- function that choose the encoding, decoding or wrap algorithm
|
|
75
|
+
encode = choose(encodet)
|
|
76
|
+
decode = choose(decodet)
|
|
77
|
+
wrap = choose(wrapt)
|
|
78
|
+
|
|
79
|
+
-- define the end-of-line normalization filter
|
|
80
|
+
function normalize(marker)
|
|
81
|
+
return ltn12.filter.cycle(eol, 0, marker)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
-- high level stuffing filter
|
|
85
|
+
function stuff()
|
|
86
|
+
return ltn12.filter.cycle(dot, 2)
|
|
87
|
+
end
|
|
Binary file
|
|
@@ -0,0 +1,1484 @@
|
|
|
1
|
+
--
|
|
2
|
+
-- MobDebug 0.515
|
|
3
|
+
-- Copyright 2011-12 Paul Kulchenko
|
|
4
|
+
-- Based on RemDebug 1.0 Copyright Kepler Project 2005
|
|
5
|
+
--
|
|
6
|
+
|
|
7
|
+
local mobdebug = {
|
|
8
|
+
_NAME = "mobdebug",
|
|
9
|
+
_VERSION = 0.515,
|
|
10
|
+
_COPYRIGHT = "Paul Kulchenko",
|
|
11
|
+
_DESCRIPTION = "Mobile Remote Debugger for the Lua programming language",
|
|
12
|
+
port = os and os.getenv and os.getenv("MOBDEBUG_PORT") or 8172,
|
|
13
|
+
yieldtimeout = 0.02,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
local coroutine = coroutine
|
|
17
|
+
local error = error
|
|
18
|
+
local getfenv = getfenv
|
|
19
|
+
local setfenv = setfenv
|
|
20
|
+
local loadstring = loadstring or load -- "load" replaced "loadstring" in Lua 5.2
|
|
21
|
+
local io = io
|
|
22
|
+
local os = os
|
|
23
|
+
local pairs = pairs
|
|
24
|
+
local require = require
|
|
25
|
+
local setmetatable = setmetatable
|
|
26
|
+
local string = string
|
|
27
|
+
local tonumber = tonumber
|
|
28
|
+
|
|
29
|
+
-- if strict.lua is used, then need to avoid referencing some global
|
|
30
|
+
-- variables, as they can be undefined;
|
|
31
|
+
-- use rawget to to avoid complaints from strict.lua at run-time.
|
|
32
|
+
-- it's safe to do the initialization here as all these variables
|
|
33
|
+
-- should get defined values (of any) before the debugging starts.
|
|
34
|
+
-- there is also global 'wx' variable, which is checked as part of
|
|
35
|
+
-- the debug loop as 'wx' can be loaded at any time during debugging.
|
|
36
|
+
local genv = _G or _ENV
|
|
37
|
+
local jit = rawget(genv, "jit")
|
|
38
|
+
local mosync = rawget(genv, "mosync")
|
|
39
|
+
local MOAICoroutine = rawget(genv, "MOAICoroutine")
|
|
40
|
+
|
|
41
|
+
if not setfenv then -- Lua 5.2
|
|
42
|
+
-- based on http://lua-users.org/lists/lua-l/2010-06/msg00314.html
|
|
43
|
+
-- this assumes f is a function
|
|
44
|
+
local function findenv(f)
|
|
45
|
+
local level = 1
|
|
46
|
+
repeat
|
|
47
|
+
local name, value = debug.getupvalue(f, level)
|
|
48
|
+
if name == '_ENV' then return level, value end
|
|
49
|
+
level = level + 1
|
|
50
|
+
until name == nil
|
|
51
|
+
return nil end
|
|
52
|
+
getfenv = function (f) return(select(2, findenv(f)) or _G) end
|
|
53
|
+
setfenv = function (f, t)
|
|
54
|
+
local level = findenv(f)
|
|
55
|
+
if level then debug.setupvalue(f, level, t) end
|
|
56
|
+
return f end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
-- check for OS and convert file names to lower case on windows
|
|
60
|
+
-- (its file system is case insensitive, but case preserving), as setting a
|
|
61
|
+
-- breakpoint on x:\Foo.lua will not work if the file was loaded as X:\foo.lua.
|
|
62
|
+
local iswindows = os and os.getenv and (os.getenv('WINDIR')
|
|
63
|
+
or (os.getenv('OS') or ''):match('[Ww]indows'))
|
|
64
|
+
or pcall(require, "winapi")
|
|
65
|
+
|
|
66
|
+
-- this is a socket class that implements maConnect interface
|
|
67
|
+
local function socketMobileLua()
|
|
68
|
+
local self = {}
|
|
69
|
+
self.select = function(readfrom) -- writeto and timeout parameters are ignored
|
|
70
|
+
local canread = {}
|
|
71
|
+
for _,s in ipairs(readfrom) do
|
|
72
|
+
if s:receive(0) then canread[s] = true end
|
|
73
|
+
end
|
|
74
|
+
return canread
|
|
75
|
+
end
|
|
76
|
+
self.connect = coroutine.wrap(function(host, port)
|
|
77
|
+
while true do
|
|
78
|
+
local connection = mosync.maConnect("socket://" .. host .. ":" .. port)
|
|
79
|
+
|
|
80
|
+
if connection > 0 then
|
|
81
|
+
local event = mosync.SysEventCreate()
|
|
82
|
+
while true do
|
|
83
|
+
mosync.maWait(0)
|
|
84
|
+
mosync.maGetEvent(event)
|
|
85
|
+
local eventType = mosync.SysEventGetType(event)
|
|
86
|
+
if (mosync.EVENT_TYPE_CONN == eventType and
|
|
87
|
+
mosync.SysEventGetConnHandle(event) == connection and
|
|
88
|
+
mosync.SysEventGetConnOpType(event) == mosync.CONNOP_CONNECT) then
|
|
89
|
+
-- result > 0 ? success : error
|
|
90
|
+
if not (mosync.SysEventGetConnResult(event) > 0) then connection = nil end
|
|
91
|
+
break
|
|
92
|
+
elseif mosync.EventMonitor and mosync.EventMonitor.HandleEvent then
|
|
93
|
+
mosync.EventMonitor:HandleEvent(event)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
mosync.SysFree(event)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
host, port = coroutine.yield(connection and (function ()
|
|
100
|
+
local self = {}
|
|
101
|
+
local outBuffer = mosync.SysAlloc(1000)
|
|
102
|
+
local inBuffer = mosync.SysAlloc(1000)
|
|
103
|
+
local event = mosync.SysEventCreate()
|
|
104
|
+
local recvBuffer = ""
|
|
105
|
+
function stringToBuffer(s, buffer)
|
|
106
|
+
local i = 0
|
|
107
|
+
for c in s:gmatch(".") do
|
|
108
|
+
i = i + 1
|
|
109
|
+
local b = s:byte(i)
|
|
110
|
+
mosync.SysBufferSetByte(buffer, i - 1, b)
|
|
111
|
+
end
|
|
112
|
+
return i
|
|
113
|
+
end
|
|
114
|
+
function bufferToString(buffer, len)
|
|
115
|
+
local s = ""
|
|
116
|
+
for i = 0, len - 1 do
|
|
117
|
+
local c = mosync.SysBufferGetByte(buffer, i)
|
|
118
|
+
s = s .. string.char(c)
|
|
119
|
+
end
|
|
120
|
+
return s
|
|
121
|
+
end
|
|
122
|
+
self.send = coroutine.wrap(function(self, msg)
|
|
123
|
+
while true do
|
|
124
|
+
local numberOfBytes = stringToBuffer(msg, outBuffer)
|
|
125
|
+
mosync.maConnWrite(connection, outBuffer, numberOfBytes)
|
|
126
|
+
while true do
|
|
127
|
+
mosync.maWait(0)
|
|
128
|
+
mosync.maGetEvent(event)
|
|
129
|
+
local eventType = mosync.SysEventGetType(event)
|
|
130
|
+
if (mosync.EVENT_TYPE_CONN == eventType and
|
|
131
|
+
mosync.SysEventGetConnHandle(event) == connection and
|
|
132
|
+
mosync.SysEventGetConnOpType(event) == mosync.CONNOP_WRITE) then
|
|
133
|
+
break
|
|
134
|
+
elseif mosync.EventMonitor and mosync.EventMonitor.HandleEvent then
|
|
135
|
+
mosync.EventMonitor:HandleEvent(event)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
self, msg = coroutine.yield()
|
|
139
|
+
end
|
|
140
|
+
end)
|
|
141
|
+
self.receive = coroutine.wrap(function(self, len)
|
|
142
|
+
while true do
|
|
143
|
+
local line = recvBuffer
|
|
144
|
+
while (len and string.len(line) < len) -- either we need len bytes
|
|
145
|
+
or (not len and not line:find("\n")) -- or one line (if no len specified)
|
|
146
|
+
or (len == 0) do -- only check for new data (select-like)
|
|
147
|
+
mosync.maConnRead(connection, inBuffer, 1000)
|
|
148
|
+
while true do
|
|
149
|
+
if len ~= 0 then mosync.maWait(0) end
|
|
150
|
+
mosync.maGetEvent(event)
|
|
151
|
+
local eventType = mosync.SysEventGetType(event)
|
|
152
|
+
if (mosync.EVENT_TYPE_CONN == eventType and
|
|
153
|
+
mosync.SysEventGetConnHandle(event) == connection and
|
|
154
|
+
mosync.SysEventGetConnOpType(event) == mosync.CONNOP_READ) then
|
|
155
|
+
local result = mosync.SysEventGetConnResult(event)
|
|
156
|
+
if result > 0 then line = line .. bufferToString(inBuffer, result) end
|
|
157
|
+
if len == 0 then self, len = coroutine.yield("") end
|
|
158
|
+
break -- got the event we wanted; now check if we have all we need
|
|
159
|
+
elseif len == 0 then
|
|
160
|
+
self, len = coroutine.yield(nil)
|
|
161
|
+
elseif mosync.EventMonitor and mosync.EventMonitor.HandleEvent then
|
|
162
|
+
mosync.EventMonitor:HandleEvent(event)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
if not len then
|
|
168
|
+
len = string.find(line, "\n") or string.len(line)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
recvBuffer = string.sub(line, len+1)
|
|
172
|
+
line = string.sub(line, 1, len)
|
|
173
|
+
|
|
174
|
+
self, len = coroutine.yield(line)
|
|
175
|
+
end
|
|
176
|
+
end)
|
|
177
|
+
self.close = coroutine.wrap(function(self)
|
|
178
|
+
while true do
|
|
179
|
+
mosync.SysFree(inBuffer)
|
|
180
|
+
mosync.SysFree(outBuffer)
|
|
181
|
+
mosync.SysFree(event)
|
|
182
|
+
mosync.maConnClose(connection)
|
|
183
|
+
coroutine.yield(self)
|
|
184
|
+
end
|
|
185
|
+
end)
|
|
186
|
+
return self
|
|
187
|
+
end)())
|
|
188
|
+
end
|
|
189
|
+
end)
|
|
190
|
+
|
|
191
|
+
return self
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
-- overwrite RunEventLoop in MobileLua as it conflicts with the event
|
|
195
|
+
-- loop that needs to run to process debugger events (socket read/write).
|
|
196
|
+
-- event loop functionality is implemented by calling HandleEvent
|
|
197
|
+
-- while waiting for debugger events.
|
|
198
|
+
if mosync and mosync.EventMonitor then
|
|
199
|
+
mosync.EventMonitor.RunEventLoop = function(self) end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
-- turn jit off based on Mike Pall's comment in this discussion:
|
|
203
|
+
-- http://www.freelists.org/post/luajit/Debug-hooks-and-JIT,2
|
|
204
|
+
-- "You need to turn it off at the start if you plan to receive
|
|
205
|
+
-- reliable hook calls at any later point in time."
|
|
206
|
+
if jit and jit.off then jit.off() end
|
|
207
|
+
|
|
208
|
+
local socket = mosync and socketMobileLua() or (require "socket")
|
|
209
|
+
|
|
210
|
+
local debug = require "debug"
|
|
211
|
+
local coro_debugger
|
|
212
|
+
local coro_debugee
|
|
213
|
+
local coroutines = {}; setmetatable(coroutines, {__mode = "k"}) -- "weak" keys
|
|
214
|
+
local events = { BREAK = 1, WATCH = 2, RESTART = 3, STACK = 4 }
|
|
215
|
+
local breakpoints = {}
|
|
216
|
+
local watches = {}
|
|
217
|
+
local lastsource
|
|
218
|
+
local lastfile
|
|
219
|
+
local watchescnt = 0
|
|
220
|
+
local abort -- default value is nil; this is used in start/loop distinction
|
|
221
|
+
local seen_hook = false
|
|
222
|
+
local skip
|
|
223
|
+
local skipcount = 0
|
|
224
|
+
local step_into = false
|
|
225
|
+
local step_over = false
|
|
226
|
+
local step_level = 0
|
|
227
|
+
local stack_level = 0
|
|
228
|
+
local server
|
|
229
|
+
local rset
|
|
230
|
+
local outputs = {}
|
|
231
|
+
local iobase = {print = print}
|
|
232
|
+
local basedir = ""
|
|
233
|
+
local deferror = "execution aborted at default debugee"
|
|
234
|
+
local debugee = function ()
|
|
235
|
+
local a = 1
|
|
236
|
+
for _ = 1, 10 do a = a + 1 end
|
|
237
|
+
error(deferror)
|
|
238
|
+
end
|
|
239
|
+
local function q(s) return s:gsub('([%(%)%.%%%+%-%*%?%[%^%$%]])','%%%1') end
|
|
240
|
+
|
|
241
|
+
local serpent = (function() ---- include Serpent module for serialization
|
|
242
|
+
local n, v = "serpent", 0.22 -- (C) 2012 Paul Kulchenko; MIT License
|
|
243
|
+
local c, d = "Paul Kulchenko", "Serializer and pretty printer of Lua data types"
|
|
244
|
+
local snum = {[tostring(1/0)]='1/0 --[[math.huge]]',[tostring(-1/0)]='-1/0 --[[-math.huge]]',[tostring(0/0)]='0/0'}
|
|
245
|
+
local badtype = {thread = true, userdata = true}
|
|
246
|
+
local keyword, globals, G = {}, {}, (_G or _ENV)
|
|
247
|
+
for _,k in ipairs({'and', 'break', 'do', 'else', 'elseif', 'end', 'false',
|
|
248
|
+
'for', 'function', 'goto', 'if', 'in', 'local', 'nil', 'not', 'or', 'repeat',
|
|
249
|
+
'return', 'then', 'true', 'until', 'while'}) do keyword[k] = true end
|
|
250
|
+
for k,v in pairs(G) do globals[v] = k end -- build func to name mapping
|
|
251
|
+
for _,g in ipairs({'coroutine', 'debug', 'io', 'math', 'string', 'table', 'os'}) do
|
|
252
|
+
for k,v in pairs(G[g]) do globals[v] = g..'.'..k end end
|
|
253
|
+
|
|
254
|
+
local function s(t, opts)
|
|
255
|
+
local name, indent, fatal = opts.name, opts.indent, opts.fatal
|
|
256
|
+
local sparse, custom, huge = opts.sparse, opts.custom, not opts.nohuge
|
|
257
|
+
local space, maxl = (opts.compact and '' or ' '), (opts.maxlevel or math.huge)
|
|
258
|
+
local comm = opts.comment and (tonumber(opts.comment) or math.huge)
|
|
259
|
+
local seen, sref, syms, symn = {}, {}, {}, 0
|
|
260
|
+
local function gensym(val) return (tostring(val):gsub("[^%w]",""):gsub("(%d%w+)",
|
|
261
|
+
function(s) if not syms[s] then symn = symn+1; syms[s] = symn end return syms[s] end)) end
|
|
262
|
+
local function safestr(s) return type(s) == "number" and (huge and snum[tostring(s)] or s)
|
|
263
|
+
or type(s) ~= "string" and tostring(s) -- escape NEWLINE/010 and EOF/026
|
|
264
|
+
or ("%q"):format(s):gsub("\010","n"):gsub("\026","\\026") end
|
|
265
|
+
local function comment(s,l) return comm and (l or 0) < comm and ' --[['..tostring(s)..']]' or '' end
|
|
266
|
+
local function globerr(s,l) return globals[s] and globals[s]..comment(s,l) or not fatal
|
|
267
|
+
and safestr(select(2, pcall(tostring, s))) or error("Can't serialize "..tostring(s)) end
|
|
268
|
+
local function safename(path, name) -- generates foo.bar, foo[3], or foo['b a r']
|
|
269
|
+
local n = name == nil and '' or name
|
|
270
|
+
local plain = type(n) == "string" and n:match("^[%l%u_][%w_]*$") and not keyword[n]
|
|
271
|
+
local safe = plain and n or '['..safestr(n)..']'
|
|
272
|
+
return (path or '')..(plain and path and '.' or '')..safe, safe end
|
|
273
|
+
local alphanumsort = type(opts.sortkeys) == 'function' and opts.sortkeys or function(o, n)
|
|
274
|
+
local maxn, to = tonumber(n) or 12, {number = 'a', string = 'b'}
|
|
275
|
+
local function padnum(d) return ("%0"..maxn.."d"):format(d) end
|
|
276
|
+
table.sort(o, function(a,b)
|
|
277
|
+
return (o[a] and 0 or to[type(a)] or 'z')..(tostring(a):gsub("%d+",padnum))
|
|
278
|
+
< (o[b] and 0 or to[type(b)] or 'z')..(tostring(b):gsub("%d+",padnum)) end) end
|
|
279
|
+
local function val2str(t, name, indent, insref, path, plainindex, level)
|
|
280
|
+
local ttype, level = type(t), (level or 0)
|
|
281
|
+
local spath, sname = safename(path, name)
|
|
282
|
+
local tag = plainindex and
|
|
283
|
+
((type(name) == "number") and '' or name..space..'='..space) or
|
|
284
|
+
(name ~= nil and sname..space..'='..space or '')
|
|
285
|
+
if seen[t] then -- if already seen and in sref processing,
|
|
286
|
+
if insref then return tag..seen[t] end -- then emit right away
|
|
287
|
+
table.insert(sref, spath..space..'='..space..seen[t])
|
|
288
|
+
return tag..'nil'..comment('ref', level)
|
|
289
|
+
elseif badtype[ttype] then
|
|
290
|
+
seen[t] = spath
|
|
291
|
+
return tag..globerr(t, level)
|
|
292
|
+
elseif ttype == 'function' then
|
|
293
|
+
seen[t] = insref or spath
|
|
294
|
+
local ok, res = pcall(string.dump, t)
|
|
295
|
+
local func = ok and ((opts.nocode and "function() --[[..skipped..]] end" or
|
|
296
|
+
"loadstring("..safestr(res)..",'@serialized')")..comment(t, level))
|
|
297
|
+
return tag..(func or globerr(t, level))
|
|
298
|
+
elseif ttype == "table" then
|
|
299
|
+
if level >= maxl then return tag..'{}'..comment('max', level) end
|
|
300
|
+
seen[t] = insref or spath -- set path to use as reference
|
|
301
|
+
if getmetatable(t) and getmetatable(t).__tostring
|
|
302
|
+
then return tag..val2str(tostring(t),nil,indent,false,nil,nil,level+1)..comment("meta", level) end
|
|
303
|
+
if next(t) == nil then return tag..'{}'..comment(t, level) end -- table empty
|
|
304
|
+
local maxn, o, out = #t, {}, {}
|
|
305
|
+
for key = 1, maxn do table.insert(o, key) end
|
|
306
|
+
for key in pairs(t) do if not o[key] then table.insert(o, key) end end
|
|
307
|
+
if opts.sortkeys then alphanumsort(o, opts.sortkeys) end
|
|
308
|
+
for n, key in ipairs(o) do
|
|
309
|
+
local value, ktype, plainindex = t[key], type(key), n <= maxn and not sparse
|
|
310
|
+
if opts.valignore and opts.valignore[value] -- skip ignored values; do nothing
|
|
311
|
+
or opts.keyallow and not opts.keyallow[key]
|
|
312
|
+
or opts.valtypeignore and opts.valtypeignore[type(value)] -- skipping ignored value types
|
|
313
|
+
or sparse and value == nil then -- skipping nils; do nothing
|
|
314
|
+
elseif ktype == 'table' or ktype == 'function' or badtype[ktype] then
|
|
315
|
+
if not seen[key] and not globals[key] then
|
|
316
|
+
table.insert(sref, 'placeholder')
|
|
317
|
+
sref[#sref] = 'local '..val2str(key,gensym(key),indent,gensym(key)) end
|
|
318
|
+
table.insert(sref, 'placeholder')
|
|
319
|
+
local path = seen[t]..'['..(seen[key] or globals[key] or gensym(key))..']'
|
|
320
|
+
sref[#sref] = path..space..'='..space..(seen[value] or val2str(value,nil,indent,path))
|
|
321
|
+
else
|
|
322
|
+
table.insert(out,val2str(value,key,indent,insref,seen[t],plainindex,level+1))
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
local prefix = string.rep(indent or '', level)
|
|
326
|
+
local head = indent and '{\n'..prefix..indent or '{'
|
|
327
|
+
local body = table.concat(out, ','..(indent and '\n'..prefix..indent or space))
|
|
328
|
+
local tail = indent and "\n"..prefix..'}' or '}'
|
|
329
|
+
return (custom and custom(tag,head,body,tail) or tag..head..body..tail)..comment(t, level)
|
|
330
|
+
else return tag..safestr(t) end -- handle all other types
|
|
331
|
+
end
|
|
332
|
+
local sepr = indent and "\n" or ";"..space
|
|
333
|
+
local body = val2str(t, name, indent) -- this call also populates sref
|
|
334
|
+
local tail = #sref>0 and table.concat(sref, sepr)..sepr or ''
|
|
335
|
+
return not name and body or "do local "..body..sepr..tail.."return "..name..sepr.."end"
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
local function merge(a, b) if b then for k,v in pairs(b) do a[k] = v end end; return a; end
|
|
339
|
+
return { _NAME = n, _COPYRIGHT = c, _DESCRIPTION = d, _VERSION = v, serialize = s,
|
|
340
|
+
dump = function(a, opts) return s(a, merge({name = '_', compact = true, sparse = true}, opts)) end,
|
|
341
|
+
line = function(a, opts) return s(a, merge({sortkeys = true, comment = true}, opts)) end,
|
|
342
|
+
block = function(a, opts) return s(a, merge({indent = ' ', sortkeys = true, comment = true}, opts)) end }
|
|
343
|
+
end)() ---- end of Serpent module
|
|
344
|
+
|
|
345
|
+
local function removebasedir(path, basedir)
|
|
346
|
+
if iswindows then
|
|
347
|
+
-- check if the lowercased path matches the basedir
|
|
348
|
+
-- if so, return substring of the original path (to not lowercase it)
|
|
349
|
+
return path:lower():find('^'..q(basedir:lower()))
|
|
350
|
+
and path:sub(#basedir+1) or path
|
|
351
|
+
else
|
|
352
|
+
return string.gsub(path, '^'..q(basedir), '')
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
local function stack(start)
|
|
357
|
+
local function vars(f)
|
|
358
|
+
local func = debug.getinfo(f, "f").func
|
|
359
|
+
local i = 1
|
|
360
|
+
local locals = {}
|
|
361
|
+
while true do
|
|
362
|
+
local name, value = debug.getlocal(f, i)
|
|
363
|
+
if not name then break end
|
|
364
|
+
if string.sub(name, 1, 1) ~= '(' then locals[name] = {value, tostring(value)} end
|
|
365
|
+
i = i + 1
|
|
366
|
+
end
|
|
367
|
+
i = 1
|
|
368
|
+
local ups = {}
|
|
369
|
+
while func and true do -- check for func as it may be nil for tail calls
|
|
370
|
+
local name, value = debug.getupvalue(func, i)
|
|
371
|
+
if not name then break end
|
|
372
|
+
ups[name] = {value, tostring(value)}
|
|
373
|
+
i = i + 1
|
|
374
|
+
end
|
|
375
|
+
return locals, ups
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
local stack = {}
|
|
379
|
+
for i = (start or 0), 100 do
|
|
380
|
+
local source = debug.getinfo(i, "Snl")
|
|
381
|
+
if not source then break end
|
|
382
|
+
|
|
383
|
+
-- remove basedir from source
|
|
384
|
+
local src = source.source
|
|
385
|
+
if src:find("@") == 1 then
|
|
386
|
+
src = src:sub(2):gsub("\\", "/")
|
|
387
|
+
if src:find("%./") == 1 then src = src:sub(3) end
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
table.insert(stack, {
|
|
391
|
+
{source.name, removebasedir(src, basedir), source.linedefined,
|
|
392
|
+
source.currentline, source.what, source.namewhat, source.short_src},
|
|
393
|
+
vars(i+1)})
|
|
394
|
+
if source.what == 'main' then break end
|
|
395
|
+
end
|
|
396
|
+
return stack
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
local function set_breakpoint(file, line)
|
|
400
|
+
if file == '-' and lastfile then file = lastfile
|
|
401
|
+
elseif iswindows then file = string.lower(file) end
|
|
402
|
+
if not breakpoints[file] then breakpoints[file] = {} end
|
|
403
|
+
breakpoints[file][line] = true
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
local function remove_breakpoint(file, line)
|
|
407
|
+
if file == '-' and lastfile then file = lastfile
|
|
408
|
+
elseif iswindows then file = string.lower(file) end
|
|
409
|
+
if breakpoints[file] then breakpoints[file][line] = nil end
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
-- this file name is already converted to lower case on windows.
|
|
413
|
+
local function has_breakpoint(file, line)
|
|
414
|
+
return breakpoints[file] and breakpoints[file][line]
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
local function restore_vars(vars)
|
|
418
|
+
if type(vars) ~= 'table' then return end
|
|
419
|
+
|
|
420
|
+
-- locals need to be processed in the reverse order, starting from
|
|
421
|
+
-- the inner block out, to make sure that the localized variables
|
|
422
|
+
-- are correctly updated with only the closest variable with
|
|
423
|
+
-- the same name being changed
|
|
424
|
+
-- first loop find how many local variables there is, while
|
|
425
|
+
-- the second loop processes them from i to 1
|
|
426
|
+
local i = 1
|
|
427
|
+
while true do
|
|
428
|
+
local name = debug.getlocal(3, i)
|
|
429
|
+
if not name then break end
|
|
430
|
+
i = i + 1
|
|
431
|
+
end
|
|
432
|
+
i = i - 1
|
|
433
|
+
local written_vars = {}
|
|
434
|
+
while i > 0 do
|
|
435
|
+
local name = debug.getlocal(3, i)
|
|
436
|
+
if not written_vars[name] then
|
|
437
|
+
if string.sub(name, 1, 1) ~= '(' then debug.setlocal(3, i, vars[name]) end
|
|
438
|
+
written_vars[name] = true
|
|
439
|
+
end
|
|
440
|
+
i = i - 1
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
i = 1
|
|
444
|
+
local func = debug.getinfo(3, "f").func
|
|
445
|
+
while true do
|
|
446
|
+
local name = debug.getupvalue(func, i)
|
|
447
|
+
if not name then break end
|
|
448
|
+
if not written_vars[name] then
|
|
449
|
+
if string.sub(name, 1, 1) ~= '(' then debug.setupvalue(func, i, vars[name]) end
|
|
450
|
+
written_vars[name] = true
|
|
451
|
+
end
|
|
452
|
+
i = i + 1
|
|
453
|
+
end
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
local function capture_vars(level)
|
|
457
|
+
local vars = {}
|
|
458
|
+
local func = debug.getinfo(level or 3, "f").func
|
|
459
|
+
local i = 1
|
|
460
|
+
while true do
|
|
461
|
+
local name, value = debug.getupvalue(func, i)
|
|
462
|
+
if not name then break end
|
|
463
|
+
if string.sub(name, 1, 1) ~= '(' then vars[name] = value end
|
|
464
|
+
i = i + 1
|
|
465
|
+
end
|
|
466
|
+
i = 1
|
|
467
|
+
while true do
|
|
468
|
+
local name, value = debug.getlocal(level or 3, i)
|
|
469
|
+
if not name then break end
|
|
470
|
+
if string.sub(name, 1, 1) ~= '(' then vars[name] = value end
|
|
471
|
+
i = i + 1
|
|
472
|
+
end
|
|
473
|
+
setmetatable(vars, { __index = getfenv(func), __newindex = getfenv(func) })
|
|
474
|
+
return vars
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
local function stack_depth(start_depth)
|
|
478
|
+
for i = start_depth, 0, -1 do
|
|
479
|
+
if debug.getinfo(i, "l") then return i+1 end
|
|
480
|
+
end
|
|
481
|
+
return start_depth
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
local function is_safe(stack_level)
|
|
485
|
+
-- the stack grows up: 0 is getinfo, 1 is is_safe, 2 is debug_hook, 3 is user function
|
|
486
|
+
if stack_level == 3 then return true end
|
|
487
|
+
for i = 3, stack_level do
|
|
488
|
+
-- return if it is not safe to abort
|
|
489
|
+
local info = debug.getinfo(i, "S")
|
|
490
|
+
if not info then return true end
|
|
491
|
+
if info.what == "C" then return false end
|
|
492
|
+
end
|
|
493
|
+
return true
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
local function in_debugger()
|
|
497
|
+
local this = debug.getinfo(1, "S").source
|
|
498
|
+
-- only need to check few frames as mobdebug frames should be close
|
|
499
|
+
for i = 3, 7 do
|
|
500
|
+
local info = debug.getinfo(i, "S")
|
|
501
|
+
if not info then return false end
|
|
502
|
+
if info.source == this then return true end
|
|
503
|
+
end
|
|
504
|
+
return false
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
local function debug_hook(event, line)
|
|
508
|
+
-- (1) LuaJIT needs special treatment. Because debug_hook is set for
|
|
509
|
+
-- *all* coroutines, and not just the one being debugged as in regular Lua
|
|
510
|
+
-- (http://lua-users.org/lists/lua-l/2011-06/msg00513.html),
|
|
511
|
+
-- need to avoid debugging mobdebug's own code as LuaJIT doesn't
|
|
512
|
+
-- always correctly generate call/return hook events (there are more
|
|
513
|
+
-- calls than returns, which breaks stack depth calculation and
|
|
514
|
+
-- 'step' and 'step over' commands stop working; possibly because
|
|
515
|
+
-- 'tail return' events are not generated by LuaJIT).
|
|
516
|
+
-- the next line checks if the debugger is run under LuaJIT and if
|
|
517
|
+
-- one of debugger methods is present in the stack, it simply returns.
|
|
518
|
+
if jit then
|
|
519
|
+
local coro = coroutine.running()
|
|
520
|
+
if coro_debugee and coro ~= coro_debugee and not coroutines[coro]
|
|
521
|
+
or not coro_debugee and (in_debugger() or coro and not coroutines[coro])
|
|
522
|
+
then return end
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
-- (2) check if abort has been requested and it's safe to abort
|
|
526
|
+
if abort and is_safe(stack_level) then error(abort) end
|
|
527
|
+
|
|
528
|
+
-- (3) also check if this debug hook has not been visited for any reason.
|
|
529
|
+
-- this check is needed to avoid stepping in too early
|
|
530
|
+
-- (for example, when coroutine.resume() is executed inside start()).
|
|
531
|
+
if not seen_hook and in_debugger() then return end
|
|
532
|
+
|
|
533
|
+
if event == "call" then
|
|
534
|
+
stack_level = stack_level + 1
|
|
535
|
+
elseif event == "return" or event == "tail return" then
|
|
536
|
+
stack_level = stack_level - 1
|
|
537
|
+
elseif event == "line" then
|
|
538
|
+
|
|
539
|
+
-- check if we need to skip some callbacks (to save time)
|
|
540
|
+
if skip then
|
|
541
|
+
skipcount = skipcount + 1
|
|
542
|
+
if skipcount < skip or not is_safe(stack_level) then return end
|
|
543
|
+
skipcount = 0
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
-- this is needed to check if the stack got shorter or longer.
|
|
547
|
+
-- unfortunately counting call/return calls is not reliable.
|
|
548
|
+
-- the discrepancy may happen when "pcall(load, '')" call is made
|
|
549
|
+
-- or when "error()" is called in a function.
|
|
550
|
+
-- in either case there are more "call" than "return" events reported.
|
|
551
|
+
-- this validation is done for every "line" event, but should be "cheap"
|
|
552
|
+
-- as it checks for the stack to get shorter (or longer by one call).
|
|
553
|
+
-- start from one level higher just in case we need to grow the stack.
|
|
554
|
+
-- this may happen after coroutine.resume call to a function that doesn't
|
|
555
|
+
-- have any other instructions to execute. it triggers three returns:
|
|
556
|
+
-- "return, tail return, return", which needs to be accounted for.
|
|
557
|
+
stack_level = stack_depth(stack_level+1)
|
|
558
|
+
local caller = debug.getinfo(2, "S")
|
|
559
|
+
|
|
560
|
+
-- grab the filename and fix it if needed
|
|
561
|
+
local file = lastfile
|
|
562
|
+
if (lastsource ~= caller.source) then
|
|
563
|
+
lastsource = caller.source
|
|
564
|
+
file = lastsource
|
|
565
|
+
if file:find("@") == 1 then
|
|
566
|
+
file = file:sub(2):gsub("\\", "/")
|
|
567
|
+
-- need this conversion to be applied to relative and absolute
|
|
568
|
+
-- file names as you may write "require 'Foo'" on Windows to
|
|
569
|
+
-- load "foo.lua" (as it's case insensitive) and breakpoints
|
|
570
|
+
-- set on foo.lua will not work if not converted to the same case.
|
|
571
|
+
if iswindows then file = string.lower(file) end
|
|
572
|
+
if file:find("%./") == 1 then file = file:sub(3)
|
|
573
|
+
else file = file:gsub('^'..q(basedir), '') end
|
|
574
|
+
end
|
|
575
|
+
|
|
576
|
+
-- fix filenames for loaded strings that may contain scripts with newlines;
|
|
577
|
+
-- some filesystems may allow "\n" in filenames, which is not supported here.
|
|
578
|
+
if file:find("\n") then
|
|
579
|
+
file = file:gsub("\n", ' '):sub(1, 32) -- limit to 32 chars
|
|
580
|
+
end
|
|
581
|
+
|
|
582
|
+
-- set to true if we got here; this only needs to be done once per
|
|
583
|
+
-- session, so do it here to at least avoid setting it for every line.
|
|
584
|
+
seen_hook = true
|
|
585
|
+
lastfile = file
|
|
586
|
+
end
|
|
587
|
+
|
|
588
|
+
local vars, status, res
|
|
589
|
+
if (watchescnt > 0) then
|
|
590
|
+
vars = capture_vars()
|
|
591
|
+
for index, value in pairs(watches) do
|
|
592
|
+
setfenv(value, vars)
|
|
593
|
+
local ok, fired = pcall(value)
|
|
594
|
+
if ok and fired then
|
|
595
|
+
status, res = coroutine.resume(coro_debugger, events.WATCH, vars, file, line, index)
|
|
596
|
+
break -- any one watch is enough; don't check multiple times
|
|
597
|
+
end
|
|
598
|
+
end
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
-- need to get into the "regular" debug handler, but only if there was
|
|
602
|
+
-- no watch that was fired. If there was a watch, handle its result.
|
|
603
|
+
local getin = (status == nil) and
|
|
604
|
+
(step_into
|
|
605
|
+
or (step_over and stack_level <= step_level)
|
|
606
|
+
or has_breakpoint(file, line)
|
|
607
|
+
or (socket.select(rset, nil, 0))[server])
|
|
608
|
+
|
|
609
|
+
if getin then
|
|
610
|
+
vars = vars or capture_vars()
|
|
611
|
+
step_into = false
|
|
612
|
+
step_over = false
|
|
613
|
+
status, res = coroutine.resume(coro_debugger, events.BREAK, vars, file, line)
|
|
614
|
+
end
|
|
615
|
+
|
|
616
|
+
-- handle 'stack' command that provides stack() information to the debugger
|
|
617
|
+
if status and res == 'stack' then
|
|
618
|
+
while status and res == 'stack' do
|
|
619
|
+
-- resume with the stack trace and variables
|
|
620
|
+
if vars then restore_vars(vars) end -- restore vars so they are reflected in stack values
|
|
621
|
+
-- this may fail if __tostring method fails at run-time
|
|
622
|
+
local ok, snapshot = pcall(stack, 4)
|
|
623
|
+
status, res = coroutine.resume(coro_debugger, ok and events.STACK or events.BREAK, snapshot, file, line)
|
|
624
|
+
end
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
-- need to recheck once more as resume after 'stack' command may
|
|
628
|
+
-- return something else (for example, 'exit'), which needs to be handled
|
|
629
|
+
if status and res and res ~= 'stack' then
|
|
630
|
+
if abort == nil and res == "exit" then os.exit(1) end
|
|
631
|
+
abort = res
|
|
632
|
+
-- only abort if safe; if not, there is another (earlier) check inside
|
|
633
|
+
-- debug_hook, which will abort execution at the first safe opportunity
|
|
634
|
+
if is_safe(stack_level) then error(abort) end
|
|
635
|
+
elseif not status and res then
|
|
636
|
+
error(res, 2) -- report any other (internal) errors back to the application
|
|
637
|
+
end
|
|
638
|
+
|
|
639
|
+
if vars then restore_vars(vars) end
|
|
640
|
+
end
|
|
641
|
+
end
|
|
642
|
+
|
|
643
|
+
local function stringify_results(status, ...)
|
|
644
|
+
if not status then return status, ... end -- on error report as it
|
|
645
|
+
|
|
646
|
+
local t = {...}
|
|
647
|
+
for i,v in pairs(t) do -- stringify each of the returned values
|
|
648
|
+
local ok, res = pcall(serpent.line, v, {nocode = true, comment = 1})
|
|
649
|
+
t[i] = ok and res or ("%q"):format(res):gsub("\010","n"):gsub("\026","\\026")
|
|
650
|
+
end
|
|
651
|
+
-- stringify table with all returned values
|
|
652
|
+
-- this is done to allow each returned value to be used (serialized or not)
|
|
653
|
+
-- intependently and to preserve "original" comments
|
|
654
|
+
return pcall(serpent.dump, t, {sparse = false})
|
|
655
|
+
end
|
|
656
|
+
|
|
657
|
+
local function debugger_loop(sfile, sline)
|
|
658
|
+
local command
|
|
659
|
+
local app, osname
|
|
660
|
+
local eval_env = {}
|
|
661
|
+
local function emptyWatch () return false end
|
|
662
|
+
local loaded = {}
|
|
663
|
+
for k in pairs(package.loaded) do loaded[k] = true end
|
|
664
|
+
|
|
665
|
+
while true do
|
|
666
|
+
local line, err
|
|
667
|
+
local wx = rawget(genv, "wx") -- use rawread to make strict.lua happy
|
|
668
|
+
if (wx or mobdebug.yield) and server.settimeout then server:settimeout(mobdebug.yieldtimeout) end
|
|
669
|
+
while true do
|
|
670
|
+
line, err = server:receive()
|
|
671
|
+
if not line and err == "timeout" then
|
|
672
|
+
-- yield for wx GUI applications if possible to avoid "busyness"
|
|
673
|
+
app = app or (wx and wx.wxGetApp and wx.wxGetApp())
|
|
674
|
+
if app then
|
|
675
|
+
local win = app:GetTopWindow()
|
|
676
|
+
local inloop = app:IsMainLoopRunning()
|
|
677
|
+
osname = osname or wx.wxPlatformInfo.Get():GetOperatingSystemFamilyName()
|
|
678
|
+
if win and not inloop then
|
|
679
|
+
-- process messages in a regular way
|
|
680
|
+
-- and exit as soon as the event loop is idle
|
|
681
|
+
if osname == 'Unix' then wx.wxTimer(app):Start(10, true) end
|
|
682
|
+
local exitLoop = function()
|
|
683
|
+
win:Disconnect(wx.wxID_ANY, wx.wxID_ANY, wx.wxEVT_IDLE)
|
|
684
|
+
win:Disconnect(wx.wxID_ANY, wx.wxID_ANY, wx.wxEVT_TIMER)
|
|
685
|
+
app:ExitMainLoop()
|
|
686
|
+
end
|
|
687
|
+
win:Connect(wx.wxEVT_IDLE, exitLoop)
|
|
688
|
+
win:Connect(wx.wxEVT_TIMER, exitLoop)
|
|
689
|
+
app:MainLoop()
|
|
690
|
+
end
|
|
691
|
+
elseif mobdebug.yield then mobdebug.yield()
|
|
692
|
+
end
|
|
693
|
+
elseif not line and err == "closed" then
|
|
694
|
+
error("Debugger connection unexpectedly closed", 0)
|
|
695
|
+
else
|
|
696
|
+
break
|
|
697
|
+
end
|
|
698
|
+
end
|
|
699
|
+
if server.settimeout then server:settimeout() end -- back to blocking
|
|
700
|
+
command = string.sub(line, string.find(line, "^[A-Z]+"))
|
|
701
|
+
if command == "SETB" then
|
|
702
|
+
local _, _, _, file, line = string.find(line, "^([A-Z]+)%s+(.-)%s+(%d+)%s*$")
|
|
703
|
+
if file and line then
|
|
704
|
+
set_breakpoint(file, tonumber(line))
|
|
705
|
+
server:send("200 OK\n")
|
|
706
|
+
else
|
|
707
|
+
server:send("400 Bad Request\n")
|
|
708
|
+
end
|
|
709
|
+
elseif command == "DELB" then
|
|
710
|
+
local _, _, _, file, line = string.find(line, "^([A-Z]+)%s+(.-)%s+(%d+)%s*$")
|
|
711
|
+
if file and line then
|
|
712
|
+
remove_breakpoint(file, tonumber(line))
|
|
713
|
+
server:send("200 OK\n")
|
|
714
|
+
else
|
|
715
|
+
server:send("400 Bad Request\n")
|
|
716
|
+
end
|
|
717
|
+
elseif command == "EXEC" then
|
|
718
|
+
local _, _, chunk = string.find(line, "^[A-Z]+%s+(.+)$")
|
|
719
|
+
if chunk then
|
|
720
|
+
local func, res = loadstring(chunk)
|
|
721
|
+
local status
|
|
722
|
+
if func then
|
|
723
|
+
setfenv(func, eval_env)
|
|
724
|
+
status, res = stringify_results(pcall(func))
|
|
725
|
+
end
|
|
726
|
+
if status then
|
|
727
|
+
server:send("200 OK " .. #res .. "\n")
|
|
728
|
+
server:send(res)
|
|
729
|
+
else
|
|
730
|
+
server:send("401 Error in Expression " .. #res .. "\n")
|
|
731
|
+
server:send(res)
|
|
732
|
+
end
|
|
733
|
+
else
|
|
734
|
+
server:send("400 Bad Request\n")
|
|
735
|
+
end
|
|
736
|
+
elseif command == "LOAD" then
|
|
737
|
+
local _, _, size, name = string.find(line, "^[A-Z]+%s+(%d+)%s+(%S.-)%s*$")
|
|
738
|
+
size = tonumber(size)
|
|
739
|
+
|
|
740
|
+
if abort == nil then -- no LOAD/RELOAD allowed inside start()
|
|
741
|
+
if size > 0 then server:receive(size) end
|
|
742
|
+
if sfile and sline then
|
|
743
|
+
server:send("201 Started " .. sfile .. " " .. sline .. "\n")
|
|
744
|
+
else
|
|
745
|
+
server:send("200 OK 0\n")
|
|
746
|
+
end
|
|
747
|
+
else
|
|
748
|
+
-- reset environment to allow required modules to load again
|
|
749
|
+
-- remove those packages that weren't loaded when debugger started
|
|
750
|
+
for k in pairs(package.loaded) do
|
|
751
|
+
if not loaded[k] then package.loaded[k] = nil end
|
|
752
|
+
end
|
|
753
|
+
|
|
754
|
+
if size == 0 then -- RELOAD the current script being debugged
|
|
755
|
+
server:send("200 OK 0\n")
|
|
756
|
+
coroutine.yield("load")
|
|
757
|
+
else
|
|
758
|
+
local chunk = server:receive(size)
|
|
759
|
+
if chunk then -- LOAD a new script for debugging
|
|
760
|
+
local func, res = loadstring(chunk, name)
|
|
761
|
+
if func then
|
|
762
|
+
server:send("200 OK 0\n")
|
|
763
|
+
debugee = func
|
|
764
|
+
coroutine.yield("load")
|
|
765
|
+
else
|
|
766
|
+
server:send("401 Error in Expression " .. #res .. "\n")
|
|
767
|
+
server:send(res)
|
|
768
|
+
end
|
|
769
|
+
else
|
|
770
|
+
server:send("400 Bad Request\n")
|
|
771
|
+
end
|
|
772
|
+
end
|
|
773
|
+
end
|
|
774
|
+
elseif command == "SETW" then
|
|
775
|
+
local _, _, exp = string.find(line, "^[A-Z]+%s+(.+)%s*$")
|
|
776
|
+
if exp then
|
|
777
|
+
local func, res = loadstring("return(" .. exp .. ")")
|
|
778
|
+
if func then
|
|
779
|
+
watchescnt = watchescnt + 1
|
|
780
|
+
local newidx = #watches + 1
|
|
781
|
+
watches[newidx] = func
|
|
782
|
+
server:send("200 OK " .. newidx .. "\n")
|
|
783
|
+
else
|
|
784
|
+
server:send("401 Error in Expression " .. #res .. "\n")
|
|
785
|
+
server:send(res)
|
|
786
|
+
end
|
|
787
|
+
else
|
|
788
|
+
server:send("400 Bad Request\n")
|
|
789
|
+
end
|
|
790
|
+
elseif command == "DELW" then
|
|
791
|
+
local _, _, index = string.find(line, "^[A-Z]+%s+(%d+)%s*$")
|
|
792
|
+
index = tonumber(index)
|
|
793
|
+
if index > 0 and index <= #watches then
|
|
794
|
+
watchescnt = watchescnt - (watches[index] ~= emptyWatch and 1 or 0)
|
|
795
|
+
watches[index] = emptyWatch
|
|
796
|
+
server:send("200 OK\n")
|
|
797
|
+
else
|
|
798
|
+
server:send("400 Bad Request\n")
|
|
799
|
+
end
|
|
800
|
+
elseif command == "RUN" then
|
|
801
|
+
server:send("200 OK\n")
|
|
802
|
+
|
|
803
|
+
local ev, vars, file, line, idx_watch = coroutine.yield()
|
|
804
|
+
eval_env = vars
|
|
805
|
+
if ev == events.BREAK then
|
|
806
|
+
server:send("202 Paused " .. file .. " " .. line .. "\n")
|
|
807
|
+
elseif ev == events.WATCH then
|
|
808
|
+
server:send("203 Paused " .. file .. " " .. line .. " " .. idx_watch .. "\n")
|
|
809
|
+
elseif ev == events.RESTART then
|
|
810
|
+
-- nothing to do
|
|
811
|
+
else
|
|
812
|
+
server:send("401 Error in Execution " .. #file .. "\n")
|
|
813
|
+
server:send(file)
|
|
814
|
+
end
|
|
815
|
+
elseif command == "STEP" then
|
|
816
|
+
server:send("200 OK\n")
|
|
817
|
+
step_into = true
|
|
818
|
+
|
|
819
|
+
local ev, vars, file, line, idx_watch = coroutine.yield()
|
|
820
|
+
eval_env = vars
|
|
821
|
+
if ev == events.BREAK then
|
|
822
|
+
server:send("202 Paused " .. file .. " " .. line .. "\n")
|
|
823
|
+
elseif ev == events.WATCH then
|
|
824
|
+
server:send("203 Paused " .. file .. " " .. line .. " " .. idx_watch .. "\n")
|
|
825
|
+
elseif ev == events.RESTART then
|
|
826
|
+
-- nothing to do
|
|
827
|
+
else
|
|
828
|
+
server:send("401 Error in Execution " .. #file .. "\n")
|
|
829
|
+
server:send(file)
|
|
830
|
+
end
|
|
831
|
+
elseif command == "OVER" or command == "OUT" then
|
|
832
|
+
server:send("200 OK\n")
|
|
833
|
+
step_over = true
|
|
834
|
+
|
|
835
|
+
-- OVER and OUT are very similar except for
|
|
836
|
+
-- the stack level value at which to stop
|
|
837
|
+
if command == "OUT" then step_level = stack_level - 1
|
|
838
|
+
else step_level = stack_level end
|
|
839
|
+
|
|
840
|
+
local ev, vars, file, line, idx_watch = coroutine.yield()
|
|
841
|
+
eval_env = vars
|
|
842
|
+
if ev == events.BREAK then
|
|
843
|
+
server:send("202 Paused " .. file .. " " .. line .. "\n")
|
|
844
|
+
elseif ev == events.WATCH then
|
|
845
|
+
server:send("203 Paused " .. file .. " " .. line .. " " .. idx_watch .. "\n")
|
|
846
|
+
elseif ev == events.RESTART then
|
|
847
|
+
-- nothing to do
|
|
848
|
+
else
|
|
849
|
+
server:send("401 Error in Execution " .. #file .. "\n")
|
|
850
|
+
server:send(file)
|
|
851
|
+
end
|
|
852
|
+
elseif command == "BASEDIR" then
|
|
853
|
+
local _, _, dir = string.find(line, "^[A-Z]+%s+(.+)%s*$")
|
|
854
|
+
if dir then
|
|
855
|
+
basedir = iswindows and string.lower(dir) or dir
|
|
856
|
+
server:send("200 OK\n")
|
|
857
|
+
else
|
|
858
|
+
server:send("400 Bad Request\n")
|
|
859
|
+
end
|
|
860
|
+
elseif command == "SUSPEND" then
|
|
861
|
+
-- do nothing; it already fulfilled its role
|
|
862
|
+
elseif command == "STACK" then
|
|
863
|
+
-- first check if we can execute the stack command
|
|
864
|
+
-- as it requires yielding back to debug_hook it cannot be executed
|
|
865
|
+
-- if we have not seen the hook yet as happens after start().
|
|
866
|
+
-- in this case we simply return an empty result
|
|
867
|
+
local vars, ev = {}
|
|
868
|
+
if seen_hook then
|
|
869
|
+
ev, vars = coroutine.yield("stack")
|
|
870
|
+
end
|
|
871
|
+
if ev and ev ~= events.STACK then
|
|
872
|
+
server:send("401 Error in Execution " .. #vars .. "\n")
|
|
873
|
+
server:send(vars)
|
|
874
|
+
else
|
|
875
|
+
local ok, res = pcall(serpent.dump, vars, {nocode = true, sparse = false})
|
|
876
|
+
if ok then
|
|
877
|
+
server:send("200 OK " .. res .. "\n")
|
|
878
|
+
else
|
|
879
|
+
server:send("401 Error in Execution " .. #res .. "\n")
|
|
880
|
+
server:send(res)
|
|
881
|
+
end
|
|
882
|
+
end
|
|
883
|
+
elseif command == "OUTPUT" then
|
|
884
|
+
local _, _, stream, mode = string.find(line, "^[A-Z]+%s+(%w+)%s+([dcr])%s*$")
|
|
885
|
+
if stream and mode and stream == "stdout" then
|
|
886
|
+
-- assign "print" in the global environment
|
|
887
|
+
genv.print = mode == 'd' and iobase.print or coroutine.wrap(function(...)
|
|
888
|
+
-- wrapping into coroutine.wrap protects this function from
|
|
889
|
+
-- being stepped through in the debugger
|
|
890
|
+
local tbl = {...}
|
|
891
|
+
while true do
|
|
892
|
+
if mode == 'c' then iobase.print(unpack(tbl)) end
|
|
893
|
+
for n = 1, #tbl do
|
|
894
|
+
tbl[n] = select(2, pcall(serpent.line, tbl[n], {nocode = true, comment = false})) end
|
|
895
|
+
local file = table.concat(tbl, "\t").."\n"
|
|
896
|
+
server:send("204 Output " .. stream .. " " .. #file .. "\n" .. file)
|
|
897
|
+
tbl = {coroutine.yield()}
|
|
898
|
+
end
|
|
899
|
+
end)
|
|
900
|
+
server:send("200 OK\n")
|
|
901
|
+
else
|
|
902
|
+
server:send("400 Bad Request\n")
|
|
903
|
+
end
|
|
904
|
+
elseif command == "EXIT" then
|
|
905
|
+
server:send("200 OK\n")
|
|
906
|
+
coroutine.yield("exit")
|
|
907
|
+
else
|
|
908
|
+
server:send("400 Bad Request\n")
|
|
909
|
+
end
|
|
910
|
+
end
|
|
911
|
+
end
|
|
912
|
+
|
|
913
|
+
local function connect(controller_host, controller_port)
|
|
914
|
+
return (socket.connect4 or socket.connect)(controller_host, controller_port)
|
|
915
|
+
end
|
|
916
|
+
|
|
917
|
+
local function isrunning()
|
|
918
|
+
return coro_debugger and coroutine.status(coro_debugger) == 'suspended'
|
|
919
|
+
end
|
|
920
|
+
|
|
921
|
+
-- Starts a debug session by connecting to a controller
|
|
922
|
+
local function start(controller_host, controller_port)
|
|
923
|
+
-- only one debugging session can be run (as there is only one debug hook)
|
|
924
|
+
if isrunning() then return end
|
|
925
|
+
|
|
926
|
+
controller_host = controller_host or "localhost"
|
|
927
|
+
controller_port = controller_port or mobdebug.port
|
|
928
|
+
|
|
929
|
+
server = (socket.connect4 or socket.connect)(controller_host, controller_port)
|
|
930
|
+
if server then
|
|
931
|
+
rset = {server} -- store hash to avoid recreating it later
|
|
932
|
+
-- check if we are called from the debugger as this may happen
|
|
933
|
+
-- when another debugger function calls start(); only check one level deep
|
|
934
|
+
local this = debug.getinfo(1, "S").source
|
|
935
|
+
local info = debug.getinfo(2, "Sl")
|
|
936
|
+
if info.source == this then info = debug.getinfo(3, "Sl") end
|
|
937
|
+
|
|
938
|
+
local file = info.source
|
|
939
|
+
if string.find(file, "@") == 1 then file = string.sub(file, 2) end
|
|
940
|
+
if string.find(file, "%.[/\\]") == 1 then file = string.sub(file, 3) end
|
|
941
|
+
|
|
942
|
+
-- correct stack depth which already has some calls on it
|
|
943
|
+
-- so it doesn't go into negative when those calls return
|
|
944
|
+
-- as this breaks subsequence checks in stack_depth().
|
|
945
|
+
-- start from 16th frame, which is sufficiently large for this check.
|
|
946
|
+
stack_level = stack_depth(16)
|
|
947
|
+
|
|
948
|
+
-- provide our own traceback function to report the error remotely
|
|
949
|
+
do
|
|
950
|
+
local dtraceback = debug.traceback
|
|
951
|
+
debug.traceback = function (err) genv.print(dtraceback(err, 3)) end
|
|
952
|
+
end
|
|
953
|
+
coro_debugger = coroutine.create(debugger_loop)
|
|
954
|
+
debug.sethook(debug_hook, "lcr")
|
|
955
|
+
local ok, res = coroutine.resume(coro_debugger, file, info.currentline)
|
|
956
|
+
if not ok and res then error(res, 2) end
|
|
957
|
+
return true
|
|
958
|
+
else
|
|
959
|
+
print("Could not connect to " .. controller_host .. ":" .. controller_port)
|
|
960
|
+
end
|
|
961
|
+
end
|
|
962
|
+
|
|
963
|
+
local function controller(controller_host, controller_port)
|
|
964
|
+
-- only one debugging session can be run (as there is only one debug hook)
|
|
965
|
+
if isrunning() then return end
|
|
966
|
+
|
|
967
|
+
controller_host = controller_host or "localhost"
|
|
968
|
+
controller_port = controller_port or mobdebug.port
|
|
969
|
+
|
|
970
|
+
local exitonerror = not skip -- exit if not running a scratchpad
|
|
971
|
+
server = (socket.connect4 or socket.connect)(controller_host, controller_port)
|
|
972
|
+
if server then
|
|
973
|
+
rset = {server} -- store hash to avoid recreating it later
|
|
974
|
+
|
|
975
|
+
local function report(trace, err)
|
|
976
|
+
local msg = err .. "\n" .. trace
|
|
977
|
+
server:send("401 Error in Execution " .. #msg .. "\n")
|
|
978
|
+
server:send(msg)
|
|
979
|
+
return err
|
|
980
|
+
end
|
|
981
|
+
|
|
982
|
+
seen_hook = true -- allow to accept all commands
|
|
983
|
+
coro_debugger = coroutine.create(debugger_loop)
|
|
984
|
+
|
|
985
|
+
while true do
|
|
986
|
+
step_into = true -- start with step command
|
|
987
|
+
abort = false -- reset abort flag from the previous loop
|
|
988
|
+
if skip then skipcount = skip end -- force suspend right away
|
|
989
|
+
|
|
990
|
+
coro_debugee = coroutine.create(debugee)
|
|
991
|
+
debug.sethook(coro_debugee, debug_hook, "lcr")
|
|
992
|
+
local status, err = coroutine.resume(coro_debugee)
|
|
993
|
+
|
|
994
|
+
-- was there an error or is the script done?
|
|
995
|
+
-- 'abort' state is allowed here; ignore it
|
|
996
|
+
if abort then
|
|
997
|
+
if tostring(abort) == 'exit' then break end
|
|
998
|
+
else
|
|
999
|
+
if status then -- normal execution is done
|
|
1000
|
+
break
|
|
1001
|
+
elseif err and not tostring(err):find(deferror) then
|
|
1002
|
+
-- report the error back
|
|
1003
|
+
-- err is not necessarily a string, so convert to string to report
|
|
1004
|
+
report(debug.traceback(coro_debugee), tostring(err))
|
|
1005
|
+
if exitonerror then break end
|
|
1006
|
+
-- resume once more to clear the response the debugger wants to send
|
|
1007
|
+
local status, err = coroutine.resume(coro_debugger, events.RESTART, capture_vars(2))
|
|
1008
|
+
if not status or status and err == "exit" then break end
|
|
1009
|
+
end
|
|
1010
|
+
end
|
|
1011
|
+
end
|
|
1012
|
+
else
|
|
1013
|
+
print("Could not connect to " .. controller_host .. ":" .. controller_port)
|
|
1014
|
+
return false
|
|
1015
|
+
end
|
|
1016
|
+
return true
|
|
1017
|
+
end
|
|
1018
|
+
|
|
1019
|
+
local function scratchpad(controller_host, controller_port, frequency)
|
|
1020
|
+
skip = frequency or 100
|
|
1021
|
+
return controller(controller_host, controller_port)
|
|
1022
|
+
end
|
|
1023
|
+
|
|
1024
|
+
local function loop(controller_host, controller_port)
|
|
1025
|
+
skip = nil -- just in case if loop() is called after scratchpad()
|
|
1026
|
+
return controller(controller_host, controller_port)
|
|
1027
|
+
end
|
|
1028
|
+
|
|
1029
|
+
local function on()
|
|
1030
|
+
if not (isrunning() and server) then return end
|
|
1031
|
+
|
|
1032
|
+
local co = coroutine.running()
|
|
1033
|
+
if co then
|
|
1034
|
+
if not coroutines[co] then
|
|
1035
|
+
coroutines[co] = true
|
|
1036
|
+
debug.sethook(co, debug_hook, "lcr")
|
|
1037
|
+
end
|
|
1038
|
+
else
|
|
1039
|
+
debug.sethook(debug_hook, "lcr")
|
|
1040
|
+
end
|
|
1041
|
+
end
|
|
1042
|
+
|
|
1043
|
+
local function off()
|
|
1044
|
+
if not (isrunning() and server) then return end
|
|
1045
|
+
|
|
1046
|
+
local co = coroutine.running()
|
|
1047
|
+
if co then
|
|
1048
|
+
if coroutines[co] then coroutines[co] = false end
|
|
1049
|
+
-- don't remove coroutine hook under LuaJIT as there is only one (global) hook
|
|
1050
|
+
if not jit then debug.sethook(co) end
|
|
1051
|
+
else
|
|
1052
|
+
debug.sethook()
|
|
1053
|
+
end
|
|
1054
|
+
end
|
|
1055
|
+
|
|
1056
|
+
-- Handles server debugging commands
|
|
1057
|
+
local function handle(params, client, options)
|
|
1058
|
+
local _, _, command = string.find(params, "^([a-z]+)")
|
|
1059
|
+
local file, line, watch_idx
|
|
1060
|
+
if command == "run" or command == "step" or command == "out"
|
|
1061
|
+
or command == "over" or command == "exit" then
|
|
1062
|
+
client:send(string.upper(command) .. "\n")
|
|
1063
|
+
client:receive() -- this should consume the first '200 OK' response
|
|
1064
|
+
while true do
|
|
1065
|
+
local done = true
|
|
1066
|
+
local breakpoint = client:receive()
|
|
1067
|
+
if not breakpoint then
|
|
1068
|
+
print("Program finished")
|
|
1069
|
+
os.exit()
|
|
1070
|
+
return -- use return here for those cases where os.exit() is not wanted
|
|
1071
|
+
end
|
|
1072
|
+
local _, _, status = string.find(breakpoint, "^(%d+)")
|
|
1073
|
+
if status == "200" then
|
|
1074
|
+
-- don't need to do anything
|
|
1075
|
+
elseif status == "202" then
|
|
1076
|
+
_, _, file, line = string.find(breakpoint, "^202 Paused%s+(.-)%s+(%d+)%s*$")
|
|
1077
|
+
if file and line then
|
|
1078
|
+
print("Paused at file " .. file .. " line " .. line)
|
|
1079
|
+
end
|
|
1080
|
+
elseif status == "203" then
|
|
1081
|
+
_, _, file, line, watch_idx = string.find(breakpoint, "^203 Paused%s+(.-)%s+(%d+)%s+(%d+)%s*$")
|
|
1082
|
+
if file and line and watch_idx then
|
|
1083
|
+
print("Paused at file " .. file .. " line " .. line .. " (watch expression " .. watch_idx .. ": [" .. watches[watch_idx] .. "])")
|
|
1084
|
+
end
|
|
1085
|
+
elseif status == "204" then
|
|
1086
|
+
local _, _, stream, size = string.find(breakpoint, "^204 Output (%w+) (%d+)$")
|
|
1087
|
+
if stream and size then
|
|
1088
|
+
local msg = client:receive(tonumber(size))
|
|
1089
|
+
print(msg)
|
|
1090
|
+
if outputs[stream] then outputs[stream](msg) end
|
|
1091
|
+
-- this was just the output, so go back reading the response
|
|
1092
|
+
done = false
|
|
1093
|
+
end
|
|
1094
|
+
elseif status == "401" then
|
|
1095
|
+
local _, _, size = string.find(breakpoint, "^401 Error in Execution (%d+)$")
|
|
1096
|
+
if size then
|
|
1097
|
+
local msg = client:receive(tonumber(size))
|
|
1098
|
+
print("Error in remote application: " .. msg)
|
|
1099
|
+
os.exit(1)
|
|
1100
|
+
return nil, nil, msg -- use return here for those cases where os.exit() is not wanted
|
|
1101
|
+
end
|
|
1102
|
+
else
|
|
1103
|
+
print("Unknown error")
|
|
1104
|
+
os.exit(1)
|
|
1105
|
+
-- use return here for those cases where os.exit() is not wanted
|
|
1106
|
+
return nil, nil, "Debugger error: unexpected response '" .. breakpoint .. "'"
|
|
1107
|
+
end
|
|
1108
|
+
if done then break end
|
|
1109
|
+
end
|
|
1110
|
+
elseif command == "setb" then
|
|
1111
|
+
_, _, _, file, line = string.find(params, "^([a-z]+)%s+(.-)%s+(%d+)%s*$")
|
|
1112
|
+
if file and line then
|
|
1113
|
+
file = string.gsub(file, "\\", "/") -- convert slash
|
|
1114
|
+
file = removebasedir(file, basedir)
|
|
1115
|
+
client:send("SETB " .. file .. " " .. line .. "\n")
|
|
1116
|
+
if client:receive() == "200 OK" then
|
|
1117
|
+
if not breakpoints[file] then breakpoints[file] = {} end
|
|
1118
|
+
breakpoints[file][line] = true
|
|
1119
|
+
else
|
|
1120
|
+
print("Error: breakpoint not inserted")
|
|
1121
|
+
end
|
|
1122
|
+
else
|
|
1123
|
+
print("Invalid command")
|
|
1124
|
+
end
|
|
1125
|
+
elseif command == "setw" then
|
|
1126
|
+
local _, _, exp = string.find(params, "^[a-z]+%s+(.+)$")
|
|
1127
|
+
if exp then
|
|
1128
|
+
client:send("SETW " .. exp .. "\n")
|
|
1129
|
+
local answer = client:receive()
|
|
1130
|
+
local _, _, watch_idx = string.find(answer, "^200 OK (%d+)%s*$")
|
|
1131
|
+
if watch_idx then
|
|
1132
|
+
watches[watch_idx] = exp
|
|
1133
|
+
print("Inserted watch exp no. " .. watch_idx)
|
|
1134
|
+
else
|
|
1135
|
+
local _, _, size = string.find(answer, "^401 Error in Expression (%d+)$")
|
|
1136
|
+
if size then
|
|
1137
|
+
local err = client:receive(tonumber(size)):gsub(".-:%d+:%s*","")
|
|
1138
|
+
print("Error: watch expression not set: " .. err)
|
|
1139
|
+
else
|
|
1140
|
+
print("Error: watch expression not set")
|
|
1141
|
+
end
|
|
1142
|
+
end
|
|
1143
|
+
else
|
|
1144
|
+
print("Invalid command")
|
|
1145
|
+
end
|
|
1146
|
+
elseif command == "delb" then
|
|
1147
|
+
_, _, _, file, line = string.find(params, "^([a-z]+)%s+(.-)%s+(%d+)%s*$")
|
|
1148
|
+
if file and line then
|
|
1149
|
+
file = string.gsub(file, "\\", "/") -- convert slash
|
|
1150
|
+
file = removebasedir(file, basedir)
|
|
1151
|
+
client:send("DELB " .. file .. " " .. line .. "\n")
|
|
1152
|
+
if client:receive() == "200 OK" then
|
|
1153
|
+
if breakpoints[file] then breakpoints[file][line] = nil end
|
|
1154
|
+
else
|
|
1155
|
+
print("Error: breakpoint not removed")
|
|
1156
|
+
end
|
|
1157
|
+
else
|
|
1158
|
+
print("Invalid command")
|
|
1159
|
+
end
|
|
1160
|
+
elseif command == "delallb" then
|
|
1161
|
+
for file, breaks in pairs(breakpoints) do
|
|
1162
|
+
for line, _ in pairs(breaks) do
|
|
1163
|
+
client:send("DELB " .. file .. " " .. line .. "\n")
|
|
1164
|
+
if client:receive() == "200 OK" then
|
|
1165
|
+
breakpoints[file][line] = nil
|
|
1166
|
+
else
|
|
1167
|
+
print("Error: breakpoint at file " .. file .. " line " .. line .. " not removed")
|
|
1168
|
+
end
|
|
1169
|
+
end
|
|
1170
|
+
end
|
|
1171
|
+
elseif command == "delw" then
|
|
1172
|
+
local _, _, index = string.find(params, "^[a-z]+%s+(%d+)%s*$")
|
|
1173
|
+
if index then
|
|
1174
|
+
client:send("DELW " .. index .. "\n")
|
|
1175
|
+
if client:receive() == "200 OK" then
|
|
1176
|
+
watches[index] = nil
|
|
1177
|
+
else
|
|
1178
|
+
print("Error: watch expression not removed")
|
|
1179
|
+
end
|
|
1180
|
+
else
|
|
1181
|
+
print("Invalid command")
|
|
1182
|
+
end
|
|
1183
|
+
elseif command == "delallw" then
|
|
1184
|
+
for index, exp in pairs(watches) do
|
|
1185
|
+
client:send("DELW " .. index .. "\n")
|
|
1186
|
+
if client:receive() == "200 OK" then
|
|
1187
|
+
watches[index] = nil
|
|
1188
|
+
else
|
|
1189
|
+
print("Error: watch expression at index " .. index .. " [" .. exp .. "] not removed")
|
|
1190
|
+
end
|
|
1191
|
+
end
|
|
1192
|
+
elseif command == "eval" or command == "exec"
|
|
1193
|
+
or command == "load" or command == "loadstring"
|
|
1194
|
+
or command == "reload" then
|
|
1195
|
+
local _, _, exp = string.find(params, "^[a-z]+%s+(.+)$")
|
|
1196
|
+
if exp or (command == "reload") then
|
|
1197
|
+
if command == "eval" or command == "exec" then
|
|
1198
|
+
exp = (exp:gsub("%-%-%[(=*)%[.-%]%1%]", "") -- remove comments
|
|
1199
|
+
:gsub("%-%-.-\n", " ") -- remove line comments
|
|
1200
|
+
:gsub("\n", " ")) -- convert new lines
|
|
1201
|
+
if command == "eval" then exp = "return " .. exp end
|
|
1202
|
+
client:send("EXEC " .. exp .. "\n")
|
|
1203
|
+
elseif command == "reload" then
|
|
1204
|
+
client:send("LOAD 0 -\n")
|
|
1205
|
+
elseif command == "loadstring" then
|
|
1206
|
+
local _, _, _, file, lines = string.find(exp, "^([\"'])(.-)%1%s+(.+)")
|
|
1207
|
+
if not file then
|
|
1208
|
+
_, _, file, lines = string.find(exp, "^(%S+)%s+(.+)")
|
|
1209
|
+
end
|
|
1210
|
+
client:send("LOAD " .. #lines .. " " .. file .. "\n")
|
|
1211
|
+
client:send(lines)
|
|
1212
|
+
else
|
|
1213
|
+
local file = io.open(exp, "r")
|
|
1214
|
+
if not file and pcall(require, "winapi") then
|
|
1215
|
+
-- if file is not open and winapi is there, try with a short path;
|
|
1216
|
+
-- this may be needed for unicode paths on windows
|
|
1217
|
+
winapi.set_encoding(winapi.CP_UTF8)
|
|
1218
|
+
file = io.open(winapi.short_path(exp), "r")
|
|
1219
|
+
end
|
|
1220
|
+
if not file then error("Cannot open file " .. exp) end
|
|
1221
|
+
-- read the file and remove the shebang line as it causes a compilation error
|
|
1222
|
+
local lines = file:read("*all"):gsub("^#!.-\n", "\n")
|
|
1223
|
+
file:close()
|
|
1224
|
+
|
|
1225
|
+
local file = string.gsub(exp, "\\", "/") -- convert slash
|
|
1226
|
+
file = removebasedir(file, basedir)
|
|
1227
|
+
client:send("LOAD " .. #lines .. " " .. file .. "\n")
|
|
1228
|
+
client:send(lines)
|
|
1229
|
+
end
|
|
1230
|
+
while true do
|
|
1231
|
+
local params, err = client:receive()
|
|
1232
|
+
if not params then
|
|
1233
|
+
return nil, nil, "Debugger connection " .. (err or "error")
|
|
1234
|
+
end
|
|
1235
|
+
local done = true
|
|
1236
|
+
local _, _, status, len = string.find(params, "^(%d+).-%s+(%d+)%s*$")
|
|
1237
|
+
if status == "200" then
|
|
1238
|
+
len = tonumber(len)
|
|
1239
|
+
if len > 0 then
|
|
1240
|
+
local status, res
|
|
1241
|
+
local str = client:receive(len)
|
|
1242
|
+
-- handle serialized table with results
|
|
1243
|
+
local func, err = loadstring(str)
|
|
1244
|
+
if func then
|
|
1245
|
+
status, res = pcall(func)
|
|
1246
|
+
if not status then err = res
|
|
1247
|
+
elseif type(res) ~= "table" then
|
|
1248
|
+
err = "received "..type(res).." instead of expected 'table'"
|
|
1249
|
+
end
|
|
1250
|
+
end
|
|
1251
|
+
if err then
|
|
1252
|
+
print("Error in processing results: " .. err)
|
|
1253
|
+
return nil, nil, "Error in processing results: " .. err
|
|
1254
|
+
end
|
|
1255
|
+
print((table.unpack or unpack)(res))
|
|
1256
|
+
return res[1], res
|
|
1257
|
+
end
|
|
1258
|
+
elseif status == "201" then
|
|
1259
|
+
_, _, file, line = string.find(params, "^201 Started%s+(.-)%s+(%d+)%s*$")
|
|
1260
|
+
elseif status == "202" or params == "200 OK" then
|
|
1261
|
+
-- do nothing; this only happens when RE/LOAD command gets the response
|
|
1262
|
+
-- that was for the original command that was aborted
|
|
1263
|
+
elseif status == "204" then
|
|
1264
|
+
local _, _, stream, size = string.find(params, "^204 Output (%w+) (%d+)$")
|
|
1265
|
+
if stream and size then
|
|
1266
|
+
local msg = client:receive(tonumber(size))
|
|
1267
|
+
print(msg)
|
|
1268
|
+
if outputs[stream] then outputs[stream](msg) end
|
|
1269
|
+
-- this was just the output, so go back reading the response
|
|
1270
|
+
done = false
|
|
1271
|
+
end
|
|
1272
|
+
elseif status == "401" then
|
|
1273
|
+
len = tonumber(len)
|
|
1274
|
+
local res = client:receive(len)
|
|
1275
|
+
print("Error in expression: " .. res)
|
|
1276
|
+
return nil, nil, res
|
|
1277
|
+
else
|
|
1278
|
+
print("Unknown error")
|
|
1279
|
+
return nil, nil, "Debugger error: unexpected response after EXEC/LOAD '" .. params .. "'"
|
|
1280
|
+
end
|
|
1281
|
+
if done then break end
|
|
1282
|
+
end
|
|
1283
|
+
else
|
|
1284
|
+
print("Invalid command")
|
|
1285
|
+
end
|
|
1286
|
+
elseif command == "listb" then
|
|
1287
|
+
for k, v in pairs(breakpoints) do
|
|
1288
|
+
local b = k .. ": " -- get filename
|
|
1289
|
+
for k in pairs(v) do
|
|
1290
|
+
b = b .. k .. " " -- get line numbers
|
|
1291
|
+
end
|
|
1292
|
+
print(b)
|
|
1293
|
+
end
|
|
1294
|
+
elseif command == "listw" then
|
|
1295
|
+
for i, v in pairs(watches) do
|
|
1296
|
+
print("Watch exp. " .. i .. ": " .. v)
|
|
1297
|
+
end
|
|
1298
|
+
elseif command == "suspend" then
|
|
1299
|
+
client:send("SUSPEND\n")
|
|
1300
|
+
elseif command == "stack" then
|
|
1301
|
+
client:send("STACK\n")
|
|
1302
|
+
local resp = client:receive()
|
|
1303
|
+
local _, _, status, res = string.find(resp, "^(%d+)%s+%w+%s+(.+)%s*$")
|
|
1304
|
+
if status == "200" then
|
|
1305
|
+
local func, err = loadstring(res)
|
|
1306
|
+
if func == nil then
|
|
1307
|
+
print("Error in stack information: " .. err)
|
|
1308
|
+
return nil, nil, err
|
|
1309
|
+
end
|
|
1310
|
+
local ok, stack = pcall(func)
|
|
1311
|
+
if not ok then
|
|
1312
|
+
print("Error in stack information: " .. stack)
|
|
1313
|
+
return nil, nil, stack
|
|
1314
|
+
end
|
|
1315
|
+
for _,frame in ipairs(stack) do
|
|
1316
|
+
print(serpent.line(frame[1], {comment = false}))
|
|
1317
|
+
end
|
|
1318
|
+
return stack
|
|
1319
|
+
elseif status == "401" then
|
|
1320
|
+
local _, _, len = string.find(resp, "%s+(%d+)%s*$")
|
|
1321
|
+
len = tonumber(len)
|
|
1322
|
+
local res = len > 0 and client:receive(len) or "Invalid stack information."
|
|
1323
|
+
print("Error in expression: " .. res)
|
|
1324
|
+
return nil, nil, res
|
|
1325
|
+
else
|
|
1326
|
+
print("Unknown error")
|
|
1327
|
+
return nil, nil, "Debugger error: unexpected response after STACK"
|
|
1328
|
+
end
|
|
1329
|
+
elseif command == "output" then
|
|
1330
|
+
local _, _, stream, mode = string.find(params, "^[a-z]+%s+(%w+)%s+([dcr])%s*$")
|
|
1331
|
+
if stream and mode then
|
|
1332
|
+
client:send("OUTPUT "..stream.." "..mode.."\n")
|
|
1333
|
+
local resp = client:receive()
|
|
1334
|
+
local _, _, status = string.find(resp, "^(%d+)%s+%w+%s*$")
|
|
1335
|
+
if status == "200" then
|
|
1336
|
+
print("Stream "..stream.." redirected")
|
|
1337
|
+
outputs[stream] = type(options) == 'table' and options.handler or nil
|
|
1338
|
+
else
|
|
1339
|
+
print("Unknown error")
|
|
1340
|
+
return nil, nil, "Debugger error: can't redirect "..stream
|
|
1341
|
+
end
|
|
1342
|
+
else
|
|
1343
|
+
print("Invalid command")
|
|
1344
|
+
end
|
|
1345
|
+
elseif command == "basedir" then
|
|
1346
|
+
local _, _, dir = string.find(params, "^[a-z]+%s+(.+)$")
|
|
1347
|
+
if dir then
|
|
1348
|
+
dir = string.gsub(dir, "\\", "/") -- convert slash
|
|
1349
|
+
if not string.find(dir, "/$") then dir = dir .. "/" end
|
|
1350
|
+
|
|
1351
|
+
local remdir = dir:match("\t(.+)")
|
|
1352
|
+
if remdir then dir = dir:gsub("/?\t.+", "/") end
|
|
1353
|
+
basedir = dir
|
|
1354
|
+
|
|
1355
|
+
client:send("BASEDIR "..(remdir or dir).."\n")
|
|
1356
|
+
local resp = client:receive()
|
|
1357
|
+
local _, _, status = string.find(resp, "^(%d+)%s+%w+%s*$")
|
|
1358
|
+
if status == "200" then
|
|
1359
|
+
print("New base directory is " .. basedir)
|
|
1360
|
+
else
|
|
1361
|
+
print("Unknown error")
|
|
1362
|
+
return nil, nil, "Debugger error: unexpected response after BASEDIR"
|
|
1363
|
+
end
|
|
1364
|
+
else
|
|
1365
|
+
print(basedir)
|
|
1366
|
+
end
|
|
1367
|
+
elseif command == "help" then
|
|
1368
|
+
print("setb <file> <line> -- sets a breakpoint")
|
|
1369
|
+
print("delb <file> <line> -- removes a breakpoint")
|
|
1370
|
+
print("delallb -- removes all breakpoints")
|
|
1371
|
+
print("setw <exp> -- adds a new watch expression")
|
|
1372
|
+
print("delw <index> -- removes the watch expression at index")
|
|
1373
|
+
print("delallw -- removes all watch expressions")
|
|
1374
|
+
print("run -- runs until next breakpoint")
|
|
1375
|
+
print("step -- runs until next line, stepping into function calls")
|
|
1376
|
+
print("over -- runs until next line, stepping over function calls")
|
|
1377
|
+
print("out -- runs until line after returning from current function")
|
|
1378
|
+
print("listb -- lists breakpoints")
|
|
1379
|
+
print("listw -- lists watch expressions")
|
|
1380
|
+
print("eval <exp> -- evaluates expression on the current context and returns its value")
|
|
1381
|
+
print("exec <stmt> -- executes statement on the current context")
|
|
1382
|
+
print("load <file> -- loads a local file for debugging")
|
|
1383
|
+
print("reload -- restarts the current debugging session")
|
|
1384
|
+
print("stack -- reports stack trace")
|
|
1385
|
+
print("output stdout <d|c|r> -- capture and redirect io stream (default|copy|redirect)")
|
|
1386
|
+
print("basedir [<path>] -- sets the base path of the remote application, or shows the current one")
|
|
1387
|
+
print("exit -- exits debugger")
|
|
1388
|
+
else
|
|
1389
|
+
local _, _, spaces = string.find(params, "^(%s*)$")
|
|
1390
|
+
if not spaces then
|
|
1391
|
+
print("Invalid command")
|
|
1392
|
+
return nil, nil, "Invalid command"
|
|
1393
|
+
end
|
|
1394
|
+
end
|
|
1395
|
+
return file, line
|
|
1396
|
+
end
|
|
1397
|
+
|
|
1398
|
+
-- Starts debugging server
|
|
1399
|
+
local function listen(host, port)
|
|
1400
|
+
host = host or "*"
|
|
1401
|
+
port = port or mobdebug.port
|
|
1402
|
+
|
|
1403
|
+
local socket = require "socket"
|
|
1404
|
+
|
|
1405
|
+
print("Lua Remote Debugger")
|
|
1406
|
+
print("Run the program you wish to debug")
|
|
1407
|
+
|
|
1408
|
+
local server = socket.bind(host, port)
|
|
1409
|
+
local client = server:accept()
|
|
1410
|
+
|
|
1411
|
+
client:send("STEP\n")
|
|
1412
|
+
client:receive()
|
|
1413
|
+
|
|
1414
|
+
local breakpoint = client:receive()
|
|
1415
|
+
local _, _, file, line = string.find(breakpoint, "^202 Paused%s+(.-)%s+(%d+)%s*$")
|
|
1416
|
+
if file and line then
|
|
1417
|
+
print("Paused at file " .. file )
|
|
1418
|
+
print("Type 'help' for commands")
|
|
1419
|
+
else
|
|
1420
|
+
local _, _, size = string.find(breakpoint, "^401 Error in Execution (%d+)%s*$")
|
|
1421
|
+
if size then
|
|
1422
|
+
print("Error in remote application: ")
|
|
1423
|
+
print(client:receive(size))
|
|
1424
|
+
end
|
|
1425
|
+
end
|
|
1426
|
+
|
|
1427
|
+
while true do
|
|
1428
|
+
io.write("> ")
|
|
1429
|
+
local line = io.read("*line")
|
|
1430
|
+
handle(line, client)
|
|
1431
|
+
end
|
|
1432
|
+
end
|
|
1433
|
+
|
|
1434
|
+
local cocreate
|
|
1435
|
+
local function coro()
|
|
1436
|
+
if cocreate then return end -- only set once
|
|
1437
|
+
cocreate = cocreate or coroutine.create
|
|
1438
|
+
coroutine.create = function(f, ...)
|
|
1439
|
+
return cocreate(function(...)
|
|
1440
|
+
require("mobdebug").on()
|
|
1441
|
+
return f(...)
|
|
1442
|
+
end, ...)
|
|
1443
|
+
end
|
|
1444
|
+
end
|
|
1445
|
+
|
|
1446
|
+
local moconew
|
|
1447
|
+
local function moai()
|
|
1448
|
+
if moconew then return end -- only set once
|
|
1449
|
+
moconew = moconew or (MOAICoroutine and MOAICoroutine.new)
|
|
1450
|
+
if not moconew then return end
|
|
1451
|
+
MOAICoroutine.new = function(...)
|
|
1452
|
+
local thread = moconew(...)
|
|
1453
|
+
local mt = getmetatable(thread)
|
|
1454
|
+
local patched = mt.run
|
|
1455
|
+
mt.run = function(self, f, ...)
|
|
1456
|
+
return patched(self, function(...)
|
|
1457
|
+
require("mobdebug").on()
|
|
1458
|
+
return f(...)
|
|
1459
|
+
end, ...)
|
|
1460
|
+
end
|
|
1461
|
+
return thread
|
|
1462
|
+
end
|
|
1463
|
+
end
|
|
1464
|
+
|
|
1465
|
+
-- make public functions available
|
|
1466
|
+
mobdebug.listen = listen
|
|
1467
|
+
mobdebug.loop = loop
|
|
1468
|
+
mobdebug.scratchpad = scratchpad
|
|
1469
|
+
mobdebug.handle = handle
|
|
1470
|
+
mobdebug.connect = connect
|
|
1471
|
+
mobdebug.start = start
|
|
1472
|
+
mobdebug.on = on
|
|
1473
|
+
mobdebug.off = off
|
|
1474
|
+
mobdebug.moai = moai
|
|
1475
|
+
mobdebug.coro = coro
|
|
1476
|
+
mobdebug.line = serpent.line
|
|
1477
|
+
mobdebug.dump = serpent.dump
|
|
1478
|
+
mobdebug.yield = nil -- callback
|
|
1479
|
+
|
|
1480
|
+
-- this is needed to make "require 'modebug'" to work when mobdebug
|
|
1481
|
+
-- module is loaded manually
|
|
1482
|
+
package.loaded.mobdebug = mobdebug
|
|
1483
|
+
|
|
1484
|
+
return mobdebug
|