| 172 | } |
| 173 | |
| 174 | bool Debugger::GetStacks(std::vector<Stack> &stacks) { |
| 175 | if (!currentL) { |
| 176 | return false; |
| 177 | } |
| 178 | |
| 179 | auto prevCurrentL = currentL; |
| 180 | auto L = currentL; |
| 181 | |
| 182 | int totalLevel = 0; |
| 183 | while (true) { |
| 184 | int level = 0; |
| 185 | while (true) { |
| 186 | lua_Debug ar{}; |
| 187 | if (!lua_getstack(L, level, &ar)) { |
| 188 | break; |
| 189 | } |
| 190 | if (!lua_getinfo(L, "nSlu", &ar)) { |
| 191 | continue; |
| 192 | } |
| 193 | // C++ 17 only return T& |
| 194 | stacks.emplace_back(); |
| 195 | auto &stack = stacks.back(); |
| 196 | stack.file = GetFile(&ar); |
| 197 | stack.functionName = getDebugName(&ar) == nullptr ? "" : getDebugName(&ar); |
| 198 | stack.level = totalLevel++; |
| 199 | stack.line = getDebugCurrentLine(&ar); |
| 200 | |
| 201 | // get variables |
| 202 | { |
| 203 | for (int i = 1;; i++) { |
| 204 | const char *name = lua_getlocal(L, &ar, i); |
| 205 | if (name == nullptr) { |
| 206 | break; |
| 207 | } |
| 208 | if (name[0] == '(') { |
| 209 | lua_pop(L, 1); |
| 210 | continue; |
| 211 | } |
| 212 | |
| 213 | // add local variable |
| 214 | auto var = stack.variableArena->Alloc(); |
| 215 | var->name = name; |
| 216 | SetVariableArena(stack.variableArena.get()); |
| 217 | GetVariable(L, var, -1, 1); |
| 218 | ClearVariableArenaRef(); |
| 219 | lua_pop(L, 1); |
| 220 | stack.localVariables.push_back(var); |
| 221 | } |
| 222 | |
| 223 | if (lua_getinfo(L, "f", &ar)) { |
| 224 | const int fIdx = lua_gettop(L); |
| 225 | for (int i = 1;; i++) { |
| 226 | const char *name = lua_getupvalue(L, fIdx, i); |
| 227 | if (!name) { |
| 228 | break; |
| 229 | } |
| 230 | |
| 231 | // add up variable |
no test coverage detected