Extract function body - lua

How can I extract function body (as a string)? For example I call C function, extract function from stack, check if type is LUA_TFUNCTION and what do I need to do to get its body?

When the function is on the stack, it has already been compiled. The best you can try to do is a lua_dump and then decode the bytecode.

You can call lua_getinfo with a string parameter of "S", then check the "source" member of the lua_Debug structure. If that string starts with '#', it's a filename, and you'll need to re-read the file if you want the source (Lua only read the file incrementally to load the function and never saved it as a string). Otherwise, its contents will be the string loaded as the chunk the function was defined in.
Note that in either case the source returned will be the entire chunk that defined the function in question. You can narrow the string down to only that function using the other fields defined in the structure: note, however, that this is not a guarantee that you will be able to load that string back in to get the same behavior (the function definition may refer to variables defined in an outer scope, for instance).

The Debug library can do this. The Lua C API doesn't have it, you'd want to call a Lua function for this purpose.

Related

In Lua, access the evaluated value of a C function addressed via a userdata table

I have a piece of lua code that is called from a C program that passes it a table.
The table contains a table which has a field that LUA reports is of type "function".
I want to invoke that function and get its return value, but the following just causes a crash (????stack corruption????):
function myFunc (tableIn)
local interface = tableIn["interface"] -- type(interface) is table
local targetFunc = interface["targetFunc"] -- type(targetFunc) is function
local value = targetFunc()
...
end
I'm therefore assuming that I need to pass one or more parameters to targetFunc(...) but I have no idea what targetFunc() is expecting and I don't have access to the documentation or code for targetFunc - which I'm also guessing is written in C.
I've seen the thread lua - get the list of parameter names of a function, from outside the function and run the code as suggested - but that just seems to return "*temporary".
The question: is there some "standard" way of calling a C routine from LUA - or is there any other programmatic way (even a one-off) of finding out how many and what type of parameters targetFunc(...) needs.
Even an answer of "no - you need to see the code / doc for targetFunc(...)" would help!
Thanks in advance...

How does tostring, concat and using the object directly have different results?

I'm using an version of Lua 5.1 in a game called Kingdoms of Amalur. This is havocscript but afaik, havocscript is lua. Now there is a custom type called ui64 that the game has and a custom package that injects a hook that I added to the game.
If I do the following:
module("playerdodge_hook", package.seeall)
function save_to_file(filename, data)
if io then
io.output(filename)
io.write(data)
io.flush()
end
end
function dodge_hook()
local x = SIMTYPE_ID("longbow_unique11a")
save_to_file("type", type(x))
save_to_file("directly", x)
save_to_file("tostring", tostring(x))
save_to_file("concat", "" .. x)
end
The output of the files are the following:
type
ui64
Directly
Sin
tostring
0
concat (does not exist)
I am no expert in Lua, but i'm trying to understand how this works. As I would like to be able to print debug information and save this externally.
Edit:
Short answer is the game's engine used a proprietary override the io write method.
Amalur has different types, and the ui64 is actually a pointer to some memory inaccessible to lua/havok script, but the library allows manipulation. And basically when a ui64 is passed in raw to write calls the localization for the Type or Actor or whatever the internal object represented.
had an altered version of io library that when it received an ui64 would interrogate the
First, I want to say that I could not use actual io.write as io is not loaded into the engine but I have a similar method that I can use to write text to an ini entry, however, every time I call the write method it overrides the content of my personal entry regardless of if I change the key.
The basic gist of the issue is that the game Kingdoms of Amalur havok engine has a custom write/(and pretty much any other way to display text) routine.
The ui64 data type is more or less a pointer to an object that exists in havok or c. However, the engine offers an api that can take these pointers and call various routines.
Passing the ui64 to the write method would make the game invoke into it's localization tables and output the localized name to the screen for this particular Type. Thus longbow_unique11a is Sin.
Since my goal was to try to get the actual localized name and dump them all plus other data, I came up with a workaround.
Essentially, the game allows you to name crafted items, and when it does so it populates the name with a default entry and so some by decompiling some methods I was able to come up a routine to build my string like so::
function dump_item_names(tbl)
local callback = function(text, canceled)
op = {}
for i = 1,#tbl do
local actor = tbl[i]
local typeId = get_hex_of_raw_id(actor)
WINDOW.populate_edit_box(name_win.m_editbox, actor)
local name = WINDOW.get_editbox_text(name_win.m_editbox)
op[#op + 1] = typeId .. ',' .. name
end
save_to_file("items.txt", table.concat(op,'\n'))
end
name_win.launch(SL(357894144), tbl[1], true, 100, callback, false)
end
So yeah, not really a lua problem so much as a havok problem and me not understanding a foreign game engine that I'm hacking.

Lua functions: how to use tables as function arguments and self-document the code

When I have functions which take many arguments it's sometimes useful to pass a single table as an argument instead of many local variables.
function example_1(arg_one, arg_two, arg_three)
end
becomes
function example_2(arg_table)
arg_table.arg_one, arg_table.arg_two, arg_table.arg_three
end
The problem is, when calling the function somewhere else in code, it's hard to remember what arg_table needs to consist of. There are plenty of code-completion plugins for many editors which will help you with remembering the arguments for the example_1 function, but not for example_2.
Is there any way to write the example_2 function with a table parameter in a way that is still a table, but also shows the necessary parameters for the function inside the ()?
something like this (which does not work):
function example_2(arg_table = {arg_one, arg_two, arg_three})
end
Write your formal parameter list and documentation with separate parameters, as usual. Then document that if the first (and only) actual argument is a table, the effective arguments will be taken from the table using the formal parameter names as string keys.
You can keep the function parameters as they are and pass a table for convenience.
For example:
function example(arg_one, arg_two, arg_three)
-- do stuff
end
local tbl = {"value for arg_one", "value for arg_two", "value for arg_three"}
example(table.unpack(tbl))
Note that this doesnt work for tables with named keys.

What does the function state.tokenize in 'CodeMirror' mean?

I want to know the function performed by tokenize in codemirror.
codemirror highlights text by calling a tokenizer function, passing it a context ("state"), and a pointer to the current location in the file that needs to be highlighted ("stream"). The job of this function is to advance the stream past the next token, and to return the type of the token. This is described fairly well in the codemirror api documentation here: http://codemirror.net/doc/manual.html#modeapi
In the case of xml.js (which you referenced in a comment), it has multiple tokenizer functions. Depending on the context, it will set the "tokenize" attribute of the state to refer to one of the tokenizer functions. Then it will use whichever function is pointed by by state.tokenize to find the next token in the stream.

How to create userdata for C in Lua scripts

SWIG considers C's enum as userdata. (I checked the source it generated. Perhaps a bug?). Then, I need to create userdata inside the Lua scripts itself... Any good ways?
Then, I need to create userdata inside the Lua scripts itself.
No. You want to create one of the enumerator values within Lua. You do that pretty much as you would in C: use the enumerator's name. This is an object that has the value of the enumerator. However SWIG's Lua component decides to marshal this is irrelevant; just use the name in your Lua code.

Resources