Prepare new Release
[tcc4lua.git] / loader.lua
blobda42bd10891365ed679de00e98e33dbaaaef5370
1 -- Copyright (c) 2006-2007 Jérôme Vuarand
2 --
3 -- Permission is hereby granted, free of charge, to any person obtaining a copy
4 -- of this software and associated documentation files (the "Software"), to deal
5 -- in the Software without restriction, including without limitation the rights
6 -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 -- copies of the Software, and to permit persons to whom the Software is
8 -- furnished to do so, subject to the following conditions:
9 --
10 -- The above copyright notice and this permission notice shall be included in
11 -- all copies or substantial portions of the Software.
13 -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 -- THE SOFTWARE.
21 module(..., package.seeall)
23 local luatcc = require(_PACKAGE:sub(1,-2))
25 local function new_context()
26 local context = luatcc.new()
27 context:add_include_path('/usr/include/lua5.1')
28 -- context:add_library_path('/usr/lib/lua/5.1')
29 return context
30 end
32 local function load(modulename)
33 -- Read source
34 local filename
35 local file
36 local errmsg = ""
37 for path in string.gmatch(package.tccpath..";", "([^;]*);") do
38 filename = string.gsub(path, "%?", (string.gsub(modulename, "%.", "\\")))
39 file = io.open(filename)
40 if file then
41 break
42 end
43 errmsg = errmsg.."\n\tno file '"..filename.."'"
44 end
45 if not file then
46 return errmsg
47 end
48 local source = file:read("*a")
49 -- Get luatcc pragma commands
50 local commands = {}
51 for command,argstr in string.gmatch(source, "luatcc[%s]*([a-z_]*)%(([^)]*)%)") do
52 commands[command] = commands[command] or {}
53 local args = {}
54 for arg in string.gmatch(argstr..",", "([^,]*),") do
55 table.insert(args, arg)
56 end
57 table.insert(commands[command], args)
58 end
59 -- Interpret pragma commands
60 -- use_library
61 local libdeps = {}
62 if commands.use_library then
63 for _,args in ipairs(commands.use_library) do
64 local libdep = args[1]
65 table.insert(libdeps, libdep)
66 end
67 end
69 local context = new_context()
70 local result,success,errmsg
71 -- Compile file
72 result,success,errmsg = pcall(context.compile, context, source, filename)
73 if not result then
74 error("error loading module '"..modulename.."' from file '"..filename.."':\n\t"..success, 0)
75 end
76 assert(success, errmsg)
77 -- Add libraries
78 for _,libdep in ipairs(libdeps) do
79 result,success,errmsg = pcall(context.add_library, context, libdep)
80 if not result then
81 error("error loading module '"..modulename.."' from file '"..filename.."':\n\t"..success, 0)
82 end
83 assert(success, errmsg)
84 end
85 -- Relocate binary code
86 result,success,errmsg = pcall(context.relocate, context)
87 if not result then
88 error("error loading module '"..modulename.."' from file '"..filename.."':\n\t"..success, 0)
89 end
90 assert(success, errmsg)
91 -- Extract symbol
92 local chunk
93 result,chunk,errmsg = pcall(context.get_symbol, context, "luaopen_"..string.gsub(modulename, "%.", "_"))
94 if not result then
95 error("error loading module '"..modulename.."' from file '"..filename.."':\n\t"..chunk, 0)
96 end
97 assert(chunk, errmsg)
98 return chunk
99 end
101 table.insert(package.loaders, load)
102 package.tccpath = package.tccpath or "./?.c"