rufus-lua-win 5.1.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|