Modules with standalone main program

classic Classic list List threaded Threaded
60 messages Options
123
Reply | Threaded
Open this post in threaded view
|

Re: Modules with standalone main program

Albert Chan
On Feb 26, 2018, at 2:35 AM, Dirk Laurie <[hidden email]> wrote:

> 2018-02-26 5:43 GMT+02:00 Paul K <[hidden email]>:
>>> what if later versions of dofile allow optional command-line args ?
>>
>> We'll cross this bridge when we get there. For now this logic should
>> work with all Lua 5.1+ versions.
>
> Why is it better to use debug.getlocal than "'..."?
>

using ... from unknown source is dangerous, ... can be anything

A.lua: loadfile "B.lua" "A"  -- running B standalone
          if package.loading(...) then print "requiring A" else print "standalone A"end

B.lua: if package.loading(...) then print "requiring B" else print "standalone B" end

lua> require "A"
requiring "B"   -- wrong !!! tested package.loading "A"
requiring "A"

-- replaced (...) with actual modname, we get
lua> require "A"
standalone B
requiring A




Reply | Threaded
Open this post in threaded view
|

Re: Modules with standalone main program

Dirk Laurie-2
2018-02-26 16:10 GMT+02:00 albertmcchan <[hidden email]>:

> On Feb 26, 2018, at 2:35 AM, Dirk Laurie <[hidden email]> wrote:
>
>> 2018-02-26 5:43 GMT+02:00 Paul K <[hidden email]>:
>>>> what if later versions of dofile allow optional command-line args ?
>>>
>>> We'll cross this bridge when we get there. For now this logic should
>>> work with all Lua 5.1+ versions.
>>
>> Why is it better to use debug.getlocal than "'..."?
>>
>
> using ... from unknown source is dangerous, ... can be anything
>
> A.lua: loadfile "B.lua" "A"  -- running B standalone
>           if package.loading(...) then print "requiring A" else print "standalone A"end
>
> B.lua: if package.loading(...) then print "requiring B" else print "standalone B" end
>
> lua> require "A"
> requiring "B"   -- wrong !!! tested package.loading "A"
> requiring "A"
>
> -- replaced (...) with actual modname, we get
> lua> require "A"
> standalone B
> requiring A

All of whch TL;DR attempts to demonstrate why "..." may fail, but does
not answer my question, which is "why is debug.getlocal better?"

Reply | Threaded
Open this post in threaded view
|

Re: Modules with standalone main program

Albert Chan
On Feb 26, 2018, at 10:37 AM, Dirk Laurie <[hidden email]> wrote:

> 2018-02-26 16:10 GMT+02:00 albertmcchan <[hidden email]>:
>>
>> using ... from unknown source is dangerous, ... can be anything
>>
>> A.lua: loadfile "B.lua" "A"  -- running B standalone
>>      if package.loading(...) then print "requiring A" else print "standalone A"end
>>
>> B.lua: if package.loading(...) then print "requiring B" else print "standalone B" end
>>
>> lua> require "A"
>> requiring "B"   -- wrong !!! tested package.loading "A"
>> requiring "A"
>>
>> -- replaced (...) with actual modname, we get
>> lua> require "A"
>> standalone B
>> requiring A
>
> All of whch TL;DR attempts to demonstrate why "..." may fail, but does
> not answer my question, which is "why is debug.getlocal better?"
>

No ... I don't think debug.getlocal is better

I replace package.loading(...) with getlocal test for above:

if pcall(debug.getlocal, 4, 1) then
  print(select('#', ...) == 0 and "dofile mod" or "requiring mod")
else
  print "standalone mod"
end

-- this is what I get:
c:\lua> lua A.lua
requiring B -- wrong !!!
standalone A

lua> require "A"
requiring B  -- wrong !!!
requiring A

I don't like indirect test, even if it work (sometimes?)
Direct test with package.loading "mod" is better.

Reply | Threaded
Open this post in threaded view
|

Re: Modules with standalone main program

Roberto Ierusalimschy
In reply to this post by Tony Papadimitriou
I must confess I do not understand what "fail-proof method" means in this
discussion.

'require' is a regular function, with no special rights. When a program
calls 'require', it does not even know whether it is actually calling
The Original 'require'.  Whatever The Original 'require' does, other
code can do too, if it wants to pretend the module is being "required".

If someone does 'loadfile "mod.lua" "mod"', it seems clear it wants
to mimic 'require'. What is wrong with that?

I can understand the need for a "fool-proof" method, instead of a
"fail-proof" method. So, will anyone do 'loadfile "mod.lua" "mod"'
without noticing the extra unrequested argument? Would that be
a realistic concern?

-- Roberto

Reply | Threaded
Open this post in threaded view
|

Re: Modules with standalone main program

Albert Chan
On Feb 26, 2018, at 12:46 PM, Roberto Ierusalimschy <[hidden email]> wrote:

> I must confess I do not understand what "fail-proof method" means in this
> discussion.

my guess to a fail-proof method is similar to python:

if __name__ == '__main__':
   print "running code standalone"

my lua equivalent:

if not package.loading "mod" then
   print "running code standalone"
end

> If someone does 'loadfile "mod.lua" "mod"', it seems clear it wants
> to mimic 'require'. What is wrong with that?

I would guess that he did not wanted to mimic require.
Otherwise, he would do (require "mod").func "mod"

It is more likely some code not meant to be cached, and he
wanted to run the stand-alone code.  Example:

lua> loadfile "stat.lua" "stat"  -- print statistics of file "stat"


> I can understand the need for a "fool-proof" method, instead of a
> "fail-proof" method. So, will anyone do 'loadfile "mod.lua" "mod"'
> without noticing the extra unrequested argument? Would that be
> a realistic concern?
>
> -- Roberto

what is your recommendation for "fool-proof" method ?



Reply | Threaded
Open this post in threaded view
|

Re: Modules with standalone main program

Roberto Ierusalimschy
>
> if __name__ == '__main__':
>    print "running code standalone"
>
> my lua equivalent:
>
> if not package.loading "mod" then
>    print "running code standalone"
> end

This looks like a fail to me:

  package.loading = function () return true end; dofile("mod.lua")


> It is more likely some code not meant to be cached, and he
> wanted to run the stand-alone code.  Example:
>
> lua> loadfile "stat.lua" "stat"  -- print statistics of file "stat"

The question is to know whether a *module* was called by require,
not a stand-alone code that expects regular arguments to work.
Why anyone would call that with 'require'?


> what is your recommendation for "fool-proof" method ?

What Dirk suggested since the beginning: check whether the first
argument is the module name.

-- Roberto

Reply | Threaded
Open this post in threaded view
|

Re: Modules with standalone main program

Albert Chan
On Feb 26, 2018, at 3:06 PM, Roberto Ierusalimschy <[hidden email]> wrote:

>>
>> if __name__ == '__main__':
>>   print "running code standalone"
>>
>> my lua equivalent:
>>
>> if not package.loading "mod" then
>>   print "running code standalone"
>> end
>
> This looks like a fail to me:
>
>  package.loading = function () return true end; dofile("mod.lua")

you are not playing fair :-(

Deleting my package.loading function and replacing
with another that always eval to true ?




Reply | Threaded
Open this post in threaded view
|

Re: Renaming Lua modules (was Re: Modules with standalone main program)

Sean Conner
In reply to this post by Soni "They/Them" L.
It was thus said that the Great Soni They/Them L. once stated:
>
> dlopen(NULL, ...) is a thing. Read about it.

  What you said is ambiguous.  It could mean

        dlopen(NULL), ...) is a thing.  I have read about it.

or

        dlopen(NULL), ...) is a thing.  You should read about it.

  With that said, yes, I am aware of dlopen(NULL,...).  

> It means the symbols need
> to be exported during linking, even if the linking is static. It just
> means you have dynamic lookup of "static"-ish symbols. It's complicated.

  Yes.  But the presence of dlopen(NULL) in the code does *NOT*
automatically cause the symbol information to be included in the final
executable.

> If you're turning them straight into a statically linked library, you
> can still do it but I'm not sure how. (I mean the linker has to find the
> symbols somewhere, right?)

  Yes.  In the object file itself:

        % cat c1.c
        extern int printf(char const *,...);
       
        int A(int x)
        {
          printf("%d\n",x);
          return x;
        }
        % gcc -c c1.c
        % readelf -a c1.o
          [ output snipped ]

        Symbol table '.symtab' contains 10 entries:
           Num:    Value  Size Type    Bind   Vis      Ndx Name
             0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
             1: 00000000     0 FILE    LOCAL  DEFAULT  ABS c1.c
             2: 00000000     0 SECTION LOCAL  DEFAULT    1
             3: 00000000     0 SECTION LOCAL  DEFAULT    3
             4: 00000000     0 SECTION LOCAL  DEFAULT    4
             5: 00000000     0 SECTION LOCAL  DEFAULT    5
             6: 00000000     0 SECTION LOCAL  DEFAULT    6
             7: 00000000     0 SECTION LOCAL  DEFAULT    7
             8: 00000000    30 FUNC    GLOBAL DEFAULT    1 A
             9: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND printf

        ...
        %

> >which involves adding some new entries to the package.searchers array (I
> >update package.loaders but that's because I'm using Lua 5.1 in that
> >particular project).  Another way when statically linking in C based Lua
> >modules is to populate the luaopen_() calls in the package.preload array.
>
> Assuming you're turning pre-built shared objects into statically linked
> libraries, this is still trivial.

  I'm not sure how you think this is done, or where.  Yes, it's easy, but it
involves writing C code, not linker magic.

> >>Interesting. So C modules could be renameable if they supported what I
> >>proposed.
> >   Again, how?
>
> Because they can rely on the passed-in names rather than relying on
> hardcoded names.

  Again, I think you have a misunderstanding about how this works.  You have
this in Lua:

        local foo = require "foo"

require() will first look in package.loaded for a "foo" entry.  Not finding
it there, it will then call the functions in the package.searchers array.
The first will attempt to find the "foo" entry in package.preload.  If that
one fails, the next will attempt to look for "foo.lua" (or "foo/init.lua")
using the paths in package.path.  So now we get to the searcher for C based
Lua modules.  It attempts to locate "foo.so" (or "foo.dll" on Windows).

  Okay, it finds a "foo.so".  It loads it via dlopen().  It then needs the
address of the entry point of the module, and it's here were the problem
manifests itself---what is the symbol name?

  It can't be "luaopen".  While what will work on Linux (and probably Mac
OS-X and maybe even Windows, I don't know) there apparently *are* systems
out there with dynamic library support that can't handle the same symbol
from multiple dynamic objects (per an email from Roberto).  It will also
have problems when compiling the modules statically (it will require a
source change).

  The solution Roberto came up with is, look for "luaopen_foo"---in other
words, append the module name to the end of "luaopen_" (and change any "."
in the module name to "_") and look for *that* symbol.  If I simply change
the name of "foo.so" to "bar.so" and try to do:

        local bar = require "bar"

it will fail, because "bar.so" does not contain the symbol "luaopen_bar".
Renaming the dynamic object does *NOT* change any of the symbols defined
inside the dynamic object, which is why I keep asking you "how".  If the
entry point isn't found, Lua can't even pass in the module name and file to
it.  

  Now, Lua 5.3 *DOES* contain package.loadlib(), which is a wrapper around
dlopen()/dlsym().  So keeping in mind the limitations (there must be a
unique symbol identifying the entry point of a C module), if you can come up
with a way to rename a C-based Lua module and still find that unique symbol
*WITHOUT RECOMPILING THE MODULE*, then by all means, go ahead.  I'd love to
see the solution.

  -spc


Reply | Threaded
Open this post in threaded view
|

Re: Modules with standalone main program

Dirk Laurie-2
In reply to this post by Albert Chan
2018-02-26 22:46 GMT+02:00 albertmcchan <[hidden email]>:

> On Feb 26, 2018, at 3:06 PM, Roberto Ierusalimschy <[hidden email]> wrote:
>
>>>
>>> if __name__ == '__main__':
>>>   print "running code standalone"
>>>
>>> my lua equivalent:
>>>
>>> if not package.loading "mod" then
>>>   print "running code standalone"
>>> end
>>
>> This looks like a fail to me:
>>
>>  package.loading = function () return true end; dofile("mod.lua")
>
> you are not playing fair :-(
>
> Deleting my package.loading function and replacing
> with another that always eval to true ?

You changed the rules first by monkey-patching 'require'. Why should
the undocumented 'package.loading' be a holy cow if the
well-documented 'require' has already been slaughtered?

There is a canonical way to have your own package loader: just put it
in 'package.preload'. You are not monkey-patching then, you are
exploiting a documented mechanism that has been supplied for the very
purpose.

Reply | Threaded
Open this post in threaded view
|

Re: Renaming Lua modules (was Re: Modules with standalone main program)

Dirk Laurie-2
In reply to this post by Sean Conner
2018-02-27 0:04 GMT+02:00 Sean Conner <[hidden email]>:
[... 100+ lines]

Wat? No footnotes?

Reply | Threaded
Open this post in threaded view
|

Re: Renaming Lua modules (was Re: Modules with standalone main program)

Sean Conner
It was thus said that the Great Dirk Laurie once stated:
> 2018-02-27 0:04 GMT+02:00 Sean Conner <[hidden email]>:
> [... 100+ lines]
>
> Wat? No footnotes?

  What?  No footnotes?  I must have forgotten them! [1]

  -spc

[1] No, not really.


Reply | Threaded
Open this post in threaded view
|

Re: Modules with standalone main program

Albert Chan
In reply to this post by Dirk Laurie-2
On Feb 26, 2018, at 10:01 PM, Dirk Laurie <[hidden email]> wrote:

> You changed the rules first by monkey-patching 'require'. Why should
> the undocumented 'package.loading' be a holy cow if the
> well-documented 'require' has already been slaughtered?

just to be clear, patching require is to fix a bug.

package.loading function does not need to touch any lua c code.
It is just as easy to test against the userdata sentinel.

if mod.lua return false, require "mod" will set package.loaded.mod to false.
--> require 'mod' can potientially load mod.lua multiple times.

I read the original Roberto package proposal dated 9/17/2004,
it will not allow false (or nil) into package.loaded cache table:

https://marc.info/?l=lua-l&m=113878469246850&w=2

for some reason, translated c implementation is slightly different.

Since I am fixing require, I just use false as the sentinel,
and code package.loading function in lua instead of c.


Reply | Threaded
Open this post in threaded view
|

Re: Renaming Lua modules (was Re: Modules with standalone main program)

Soni "They/Them" L.
In reply to this post by Sean Conner


On 2018-02-26 07:04 PM, Sean Conner wrote:

> It was thus said that the Great Soni They/Them L. once stated:
>> dlopen(NULL, ...) is a thing. Read about it.
>    What you said is ambiguous.  It could mean
>
> dlopen(NULL), ...) is a thing.  I have read about it.
>
> or
>
> dlopen(NULL), ...) is a thing.  You should read about it.
>
>    With that said, yes, I am aware of dlopen(NULL,...).
>
>> It means the symbols need
>> to be exported during linking, even if the linking is static. It just
>> means you have dynamic lookup of "static"-ish symbols. It's complicated.
>    Yes.  But the presence of dlopen(NULL) in the code does *NOT*
> automatically cause the symbol information to be included in the final
> executable.
>
>> If you're turning them straight into a statically linked library, you
>> can still do it but I'm not sure how. (I mean the linker has to find the
>> symbols somewhere, right?)
>    Yes.  In the object file itself:
>
> % cat c1.c
> extern int printf(char const *,...);
>
> int A(int x)
> {
>  printf("%d\n",x);
>  return x;
> }
> % gcc -c c1.c
> % readelf -a c1.o
>  [ output snipped ]
>
> Symbol table '.symtab' contains 10 entries:
>   Num:    Value  Size Type    Bind   Vis      Ndx Name
>     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
>     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS c1.c
>     2: 00000000     0 SECTION LOCAL  DEFAULT    1
>     3: 00000000     0 SECTION LOCAL  DEFAULT    3
>     4: 00000000     0 SECTION LOCAL  DEFAULT    4
>     5: 00000000     0 SECTION LOCAL  DEFAULT    5
>     6: 00000000     0 SECTION LOCAL  DEFAULT    6
>     7: 00000000     0 SECTION LOCAL  DEFAULT    7
>     8: 00000000    30 FUNC    GLOBAL DEFAULT    1 A
>     9: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND printf
>
> ...
> %
>
>>> which involves adding some new entries to the package.searchers array (I
>>> update package.loaders but that's because I'm using Lua 5.1 in that
>>> particular project).  Another way when statically linking in C based Lua
>>> modules is to populate the luaopen_() calls in the package.preload array.
>> Assuming you're turning pre-built shared objects into statically linked
>> libraries, this is still trivial.
>    I'm not sure how you think this is done, or where.  Yes, it's easy, but it
> involves writing C code, not linker magic.
>
>>>> Interesting. So C modules could be renameable if they supported what I
>>>> proposed.
>>>    Again, how?
>> Because they can rely on the passed-in names rather than relying on
>> hardcoded names.
>    Again, I think you have a misunderstanding about how this works.  You have
> this in Lua:
>
> local foo = require "foo"
>
> require() will first look in package.loaded for a "foo" entry.  Not finding
> it there, it will then call the functions in the package.searchers array.
> The first will attempt to find the "foo" entry in package.preload.  If that
> one fails, the next will attempt to look for "foo.lua" (or "foo/init.lua")
> using the paths in package.path.  So now we get to the searcher for C based
> Lua modules.  It attempts to locate "foo.so" (or "foo.dll" on Windows).
>
>    Okay, it finds a "foo.so".  It loads it via dlopen().  It then needs the
> address of the entry point of the module, and it's here were the problem
> manifests itself---what is the symbol name?
>
>    It can't be "luaopen".  While what will work on Linux (and probably Mac
> OS-X and maybe even Windows, I don't know) there apparently *are* systems
> out there with dynamic library support that can't handle the same symbol
> from multiple dynamic objects (per an email from Roberto).  It will also
> have problems when compiling the modules statically (it will require a
> source change).
>
>    The solution Roberto came up with is, look for "luaopen_foo"---in other
> words, append the module name to the end of "luaopen_" (and change any "."
> in the module name to "_") and look for *that* symbol.  If I simply change
> the name of "foo.so" to "bar.so" and try to do:
>
> local bar = require "bar"
>
> it will fail, because "bar.so" does not contain the symbol "luaopen_bar".
> Renaming the dynamic object does *NOT* change any of the symbols defined
> inside the dynamic object, which is why I keep asking you "how".  If the
> entry point isn't found, Lua can't even pass in the module name and file to
> it.
>
>    Now, Lua 5.3 *DOES* contain package.loadlib(), which is a wrapper around
> dlopen()/dlsym().  So keeping in mind the limitations (there must be a
> unique symbol identifying the entry point of a C module), if you can come up
> with a way to rename a C-based Lua module and still find that unique symbol
> *WITHOUT RECOMPILING THE MODULE*, then by all means, go ahead.  I'd love to
> see the solution.
>
>    -spc
>
>

Since I can access the symbol table (by reading the module with io.open
and looking at all of its symbols), I can probably write something that
finds the common prefix for all luaopen_* and omits it when doing
requires. This should solve the problem?

Luckily I don't need my package manager to support non-POSIX systems
with dlopen functions.

--
Disclaimer: these emails may be made public at any given time, with or without reason. If you don't agree with this, DO NOT REPLY.


Reply | Threaded
Open this post in threaded view
|

Re: Modules with standalone main program

Soni "They/Them" L.
In reply to this post by Albert Chan


On 2018-02-27 12:42 AM, albertmcchan wrote:

> On Feb 26, 2018, at 10:01 PM, Dirk Laurie <[hidden email]> wrote:
>
>> You changed the rules first by monkey-patching 'require'. Why should
>> the undocumented 'package.loading' be a holy cow if the
>> well-documented 'require' has already been slaughtered?
> just to be clear, patching require is to fix a bug.
>
> package.loading function does not need to touch any lua c code.
> It is just as easy to test against the userdata sentinel.
>
> if mod.lua return false, require "mod" will set package.loaded.mod to false.
> --> require 'mod' can potientially load mod.lua multiple times.
>
> I read the original Roberto package proposal dated 9/17/2004,
> it will not allow false (or nil) into package.loaded cache table:
>
> https://marc.info/?l=lua-l&m=113878469246850&w=2
>
> for some reason, translated c implementation is slightly different.
>
> Since I am fixing require, I just use false as the sentinel,
> and code package.loading function in lua instead of c.
>
>

Here's an idea:

if debug.getinfo(2).func == require then
     -- required
elseif debug.getinfo(2).func == dofile then
     -- dofiled
else
     -- loadfiled, luaed, etc
end

(also try my lua script: debug.getinfo(2).func())

--
Disclaimer: these emails may be made public at any given time, with or without reason. If you don't agree with this, DO NOT REPLY.


Reply | Threaded
Open this post in threaded view
|

Re: Modules with standalone main program

Albert Chan

On Feb 27, 2018, at 8:29 AM, "Soni \"They/Them\" L." <[hidden email]> wrote:

>
> Here's an idea:
>
> if debug.getinfo(2).func == require then
>     -- required
> elseif debug.getinfo(2).func == dofile then
>     -- dofiled
> else
>     -- loadfiled, luaed, etc
> end
>
> (also try my lua script: debug.getinfo(2).func())
>

It work ! ... How ?
why 4 changed to 2, and 1 changed to nil ?

I were trying things out, what does below meant  ?
lua> =debug.getinfo(2)
nil
lua> =(debug.getinfo(2))
table: 004AEFE0
lua>=debug.getinfo(2).func
function: 003D4708
lua>=debug.getinfo(2).func()  -- crashed !



Reply | Threaded
Open this post in threaded view
|

Re: Modules with standalone main program

Albert Chan
In reply to this post by Soni "They/Them" L.
On Feb 27, 2018, at 8:29 AM, "Soni \"They/Them\" L." <[hidden email]> wrote:

> Here's an idea:
>
> if debug.getinfo(2).func == require then
>     -- required
> elseif debug.getinfo(2).func == dofile then
>     -- dofiled
> else
>     -- loadfiled, luaed, etc
> end

Since debug.getinfo check the stack, can I wrap the code like this
(changing 2 to 3 correct ?)

function package.loading()
  return debug.getinfo(3).func == require
end
Reply | Threaded
Open this post in threaded view
|

Re: Modules with standalone main program

Soni "They/Them" L.


On 2018-02-27 12:12 PM, albertmcchan wrote:

> On Feb 27, 2018, at 8:29 AM, "Soni \"They/Them\" L." <[hidden email]> wrote:
>
>> Here's an idea:
>>
>> if debug.getinfo(2).func == require then
>>      -- required
>> elseif debug.getinfo(2).func == dofile then
>>      -- dofiled
>> else
>>      -- loadfiled, luaed, etc
>> end
> Since debug.getinfo check the stack, can I wrap the code like this
> (changing 2 to 3 correct ?)
>
> function package.loading()
>    return debug.getinfo(3).func == require
> end

Untested, but:

function package.loading()
   local i = 3
   local x = debug.getinfo(2)
   local n = x.source
   while debug.getinfo(i).source == n do
     i = i + 1
   end
   return debug.getinfo(i).func == require
end

(this supports modules such as "return (function(...)
print(package.loading()) end)(...)")

--
Disclaimer: these emails may be made public at any given time, with or without reason. If you don't agree with this, DO NOT REPLY.


Reply | Threaded
Open this post in threaded view
|

Re: Renaming Lua modules (was Re: Modules with standalone main program)

Sean Conner
In reply to this post by Soni "They/Them" L.
It was thus said that the Great Soni They/Them L. once stated:

> On 2018-02-26 07:04 PM, Sean Conner wrote:
>
> >   Now, Lua 5.3 *DOES* contain package.loadlib(), which is a wrapper
> >around dlopen()/dlsym().  So keeping in mind the limitations (there must
> >be a unique symbol identifying the entry point of a C module), if you can
> >come up with a way to rename a C-based Lua module and still find that
> >unique symbol *WITHOUT RECOMPILING THE MODULE*, then by all means, go
> >ahead.  I'd love to see the solution.
>
> Since I can access the symbol table (by reading the module with io.open
> and looking at all of its symbols), I can probably write something that
> finds the common prefix for all luaopen_* and omits it when doing
> requires. This should solve the problem?

  I suppose.  You'll need the ELF specification for Linux and the Mach-O
specification for Mac OS-X.  But in theory that should be possible.

  -spc


Reply | Threaded
Open this post in threaded view
|

Re: Renaming Lua modules (was Re: Modules with standalone main program)

Jay Carlson
On Feb 27, 2018, at 11:37 AM, Sean Conner <[hidden email]> wrote:

> It was thus said that the Great Soni They/Them L. once stated:
>>
>> Since I can access the symbol table (by reading the module with io.open
>> and looking at all of its symbols), I can probably write something that
>> finds the common prefix for all luaopen_* and omits it when doing
>> requires. This should solve the problem?
>
>  I suppose.  You'll need the ELF specification for Linux and the Mach-O
> specification for Mac OS-X.  But in theory that should be possible.

https://github.com/bogdanm/luaelf

"LuaELF is a Lua 5.1 library for parsing ELF files. It is written almost completely in Lua, using C modules only when absolutely needed (for example when bitwise operations are involved). It uses OOP to represent different entities of an ELF file as objects."

--
Jay
Reply | Threaded
Open this post in threaded view
|

Re: Modules with standalone main program

Albert Chan
In reply to this post by Soni "They/Them" L.
On Feb 27, 2018, at 10:19 AM, "Soni \"They/Them\" L." <[hidden email]> wrote:

> On 2018-02-27 12:12 PM, albertmcchan wrote:
>>
>> Since debug.getinfo check the stack, can I wrap the code like this
>>
>> function package.loading()
>>   return debug.getinfo(3).func == require
>> end
>
> Untested, but:
>
> function package.loading()
>   local i = 3
>   local x = debug.getinfo(2)
>   local n = x.source
>   while debug.getinfo(i).source == n do
>     i = i + 1
>   end
>   return debug.getinfo(i).func == require
> end
>
> (this supports modules such as "return (function(...) print(package.loading()) end)(...)")
>

It work !

I just use the simpler version (i=3), and save the result if it really
need to go "deep" into the stack (say, first line in mod.lua)

It even work with old module(...) setup, by NOT looking the cache table.

And, less typing, thus less error !
Before, I use package.loading "mod", but it wil fail if user do require "mod.lua"
And worse, I might misspell the "mod", and it just check the wrong thing.

And, it satisfy my desire for explicit test for require "mod.lua"
-- package.loading was called from mod.lua
-- it actually test if require called mod.lua

if I understand correctly about the stacks:
stack 1 = package.loading
stack 2 = what called package.loading = mod.lua
stack 3 = what called mod.lua, and is it require ?

Thanks.



123