debuglib.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. package lua
  2. import (
  3. "fmt"
  4. "strings"
  5. )
  6. func OpenDebug(L *LState) int {
  7. dbgmod := L.RegisterModule(DebugLibName, debugFuncs)
  8. L.Push(dbgmod)
  9. return 1
  10. }
  11. var debugFuncs = map[string]LGFunction{
  12. "getfenv": debugGetFEnv,
  13. "getinfo": debugGetInfo,
  14. "getlocal": debugGetLocal,
  15. "getmetatable": debugGetMetatable,
  16. "getupvalue": debugGetUpvalue,
  17. "setfenv": debugSetFEnv,
  18. "setlocal": debugSetLocal,
  19. "setmetatable": debugSetMetatable,
  20. "setupvalue": debugSetUpvalue,
  21. "traceback": debugTraceback,
  22. }
  23. func debugGetFEnv(L *LState) int {
  24. L.Push(L.GetFEnv(L.CheckAny(1)))
  25. return 1
  26. }
  27. func debugGetInfo(L *LState) int {
  28. L.CheckTypes(1, LTFunction, LTNumber)
  29. arg1 := L.Get(1)
  30. what := L.OptString(2, "Slunf")
  31. var dbg *Debug
  32. var fn LValue
  33. var err error
  34. var ok bool
  35. switch lv := arg1.(type) {
  36. case *LFunction:
  37. dbg = &Debug{}
  38. fn, err = L.GetInfo(">"+what, dbg, lv)
  39. case LNumber:
  40. dbg, ok = L.GetStack(int(lv))
  41. if !ok {
  42. L.Push(LNil)
  43. return 1
  44. }
  45. fn, err = L.GetInfo(what, dbg, LNil)
  46. }
  47. if err != nil {
  48. L.Push(LNil)
  49. return 1
  50. }
  51. tbl := L.NewTable()
  52. if len(dbg.Name) > 0 {
  53. tbl.RawSetString("name", LString(dbg.Name))
  54. } else {
  55. tbl.RawSetString("name", LNil)
  56. }
  57. tbl.RawSetString("what", LString(dbg.What))
  58. tbl.RawSetString("source", LString(dbg.Source))
  59. tbl.RawSetString("currentline", LNumber(dbg.CurrentLine))
  60. tbl.RawSetString("nups", LNumber(dbg.NUpvalues))
  61. tbl.RawSetString("linedefined", LNumber(dbg.LineDefined))
  62. tbl.RawSetString("lastlinedefined", LNumber(dbg.LastLineDefined))
  63. tbl.RawSetString("func", fn)
  64. L.Push(tbl)
  65. return 1
  66. }
  67. func debugGetLocal(L *LState) int {
  68. level := L.CheckInt(1)
  69. idx := L.CheckInt(2)
  70. dbg, ok := L.GetStack(level)
  71. if !ok {
  72. L.ArgError(1, "level out of range")
  73. }
  74. name, value := L.GetLocal(dbg, idx)
  75. if len(name) > 0 {
  76. L.Push(LString(name))
  77. L.Push(value)
  78. return 2
  79. }
  80. L.Push(LNil)
  81. return 1
  82. }
  83. func debugGetMetatable(L *LState) int {
  84. L.Push(L.GetMetatable(L.CheckAny(1)))
  85. return 1
  86. }
  87. func debugGetUpvalue(L *LState) int {
  88. fn := L.CheckFunction(1)
  89. idx := L.CheckInt(2)
  90. name, value := L.GetUpvalue(fn, idx)
  91. if len(name) > 0 {
  92. L.Push(LString(name))
  93. L.Push(value)
  94. return 2
  95. }
  96. L.Push(LNil)
  97. return 1
  98. }
  99. func debugSetFEnv(L *LState) int {
  100. L.SetFEnv(L.CheckAny(1), L.CheckAny(2))
  101. return 0
  102. }
  103. func debugSetLocal(L *LState) int {
  104. level := L.CheckInt(1)
  105. idx := L.CheckInt(2)
  106. value := L.CheckAny(3)
  107. dbg, ok := L.GetStack(level)
  108. if !ok {
  109. L.ArgError(1, "level out of range")
  110. }
  111. name := L.SetLocal(dbg, idx, value)
  112. if len(name) > 0 {
  113. L.Push(LString(name))
  114. } else {
  115. L.Push(LNil)
  116. }
  117. return 1
  118. }
  119. func debugSetMetatable(L *LState) int {
  120. L.CheckTypes(2, LTNil, LTTable)
  121. obj := L.Get(1)
  122. mt := L.Get(2)
  123. L.SetMetatable(obj, mt)
  124. L.SetTop(1)
  125. return 1
  126. }
  127. func debugSetUpvalue(L *LState) int {
  128. fn := L.CheckFunction(1)
  129. idx := L.CheckInt(2)
  130. value := L.CheckAny(3)
  131. name := L.SetUpvalue(fn, idx, value)
  132. if len(name) > 0 {
  133. L.Push(LString(name))
  134. } else {
  135. L.Push(LNil)
  136. }
  137. return 1
  138. }
  139. func debugTraceback(L *LState) int {
  140. msg := ""
  141. level := L.OptInt(2, 1)
  142. ls := L
  143. if L.GetTop() > 0 {
  144. if s, ok := L.Get(1).(LString); ok {
  145. msg = string(s)
  146. }
  147. if l, ok := L.Get(1).(*LState); ok {
  148. ls = l
  149. msg = ""
  150. }
  151. }
  152. traceback := strings.TrimSpace(ls.stackTrace(level))
  153. if len(msg) > 0 {
  154. traceback = fmt.Sprintf("%s\n%s", msg, traceback)
  155. }
  156. L.Push(LString(traceback))
  157. return 1
  158. }