2

How Can I tell if line number x in a Lua script will respond to the Lua line hook?

Example:

 1 first = 1
 2 
 3 function test ( data )
 4  if first == 0 then
 5    print ("\r\n")
 6  end
 7  print(data)
 8  --[[
 9  first = 0
10  ]]
11 end
12
13 test()
14

Line 2,6,8,9,10,12 and 14 does not call a line hook. After I have loaded and executed the script, can I some how, from C/C++, get a table of the executable line numbers?

Max Kielland
  • 5,627
  • 9
  • 60
  • 95

2 Answers2

2

lua_getinfo can return a table of valid lines if you include L in what.

lhf
  • 70,581
  • 9
  • 108
  • 149
  • meh, that's a nice and quick solution for my useless pile of Lua code... :) – Kamiccolo Dec 12 '13 at 18:59
  • That was the first thing I tried before posting, but I couldn't get i tto work. lua_getstack() returned 0 (failed)... – Max Kielland Dec 12 '13 at 19:08
  • 1
    @MaxKielland, this works just fine in Lua : `for k in pairs(debug.getinfo(test,"L").activelines) do print(k) end` – lhf Dec 13 '13 at 00:38
  • @lhf Thank you, but I need this in C/C++. I have managed to use the lua_getinfo() to retrieve a function pointer if I'm in the function, and have it to fetch me the line numbers for that function. But I need to do this for the whole script and it isn't safe to do it in a hook because not all functions might be called during the "compile stage" (running the script for the first time). I discovered Lua's existence just a week ago, so I'm very new at this... – Max Kielland Dec 13 '13 at 02:01
  • @lhf ...This is what I need to do: Get all line numbers that can be executed, meaning also nested functions, both global and local, without having to run all functions in the script first. Isn't this information in the chunk already, after I run the script once (with no code in the main, only globals and function declarations)? As a last resort, I will have to parse the script code instead... – Max Kielland Dec 13 '13 at 02:01
  • @MaxKielland, this information is per function The script only contains the definitions of the functions, not their bodies. See the output of `luac -l -p` on your script. – lhf Dec 13 '13 at 02:04
  • @lhf thank you for the info. This is exactly the info I want. I guess I will have to look in luac.c to see how 'they' do it ;) – Max Kielland Dec 13 '13 at 02:31
  • Okay I mark this as the solution because I have found the code I was looking for in the LuaC.c code. Thank you for the tip. – Max Kielland Jan 12 '14 at 00:18
1

Some code sample:

local exec_lines = {}

local function exec_line_counter(event, line)
    table.insert(exec_lines, line)$
end

local function count_exec_lines(lua_file)
    local external_chunk = loadfile(lua_file)

    debug.sethook(exec_line_counter, "l")
    external_chunk()
    debug.sethook()

    -- Removing `debug.sethook()` lines:
    table.remove(exec_lines, 1)
    table.remove(exec_lines, #exec_lines)
end

count_exec_lines("test.lua")

Output of:

table.sort(exec_lines)
for i, num in ipairs(exec_lines) do
    print(num)
end

is

1

3

4

7

11

11 <--- not sure why this duplicates. Lack of return? Or because following tailcall?

13

NOTE: it would log only lines being parsed. In Your test case, it does not cover 5th and 6th line, because first not being 0.

Another way of doing this and solving noted case - just simply parsing Lua source: counting and skipping lines which consists only of Lua comments:

  • --lines

  • --[[ blocks ]]

EDIT: ah, shoot, edited Your question of doing this with C/C++. Hooking functions can be done with plain C API too. Might make an example if You didn't get a basic idea from an my answer already made :)

Community
  • 1
  • 1
Kamiccolo
  • 7,758
  • 3
  • 34
  • 47
  • Thank you for the nice try, I see how you think, but as you pointed out, it doesn't cover code not run due to states. Parsing the script file would be my last resort. It assumes only what lane are executable, not what the compiler actually did. However in my own tests line 6 is never executed, but line 11 is, so `end` keywords are not executed in some situations... – Max Kielland Dec 12 '13 at 18:42