0
|
1 require "dynload"
|
|
2 require "dyncall"
|
|
3 require "path"
|
|
4
|
|
5 local function makewrapper(addr, signature)
|
|
6 return function(...) return dyncall(addr, signature, ...) end
|
|
7 end
|
|
8
|
|
9 loaded = { }
|
|
10
|
|
11 --- The dynport path is initialized by LDP_PATH environment.
|
|
12 -- @usage Defaults to dynport_syspath.
|
|
13 dynport_path = pathinit("LDP_PATH","?.dynport;/usr/local/share/dynport/?.dynport;/opt/local/share/dynport/?.dynport")
|
|
14
|
|
15 local function find(name)
|
|
16 return pathfind( dynport_path, name, io.open )
|
|
17 end
|
|
18
|
|
19 --[[
|
|
20 local LDP_PATH = "?.dynport;/usr/local/share/dynport/?.dynport;/opt/local/share/dynport/?.dynport"
|
|
21 local path = os.getenv("LDP_PATH") or LDP_PATH
|
|
22
|
|
23 local function find(name)
|
|
24 local replaced = path:gsub("?", name)
|
|
25 local f = nil
|
|
26 local hist = {}
|
|
27 for filename in replaced:gmatch("([^;]+)") do
|
|
28 f = io.open(filename)
|
|
29 if f then break else
|
|
30 table.insert(hist, "\tno file '")
|
|
31 table.insert(hist, filename)
|
|
32 table.insert(hist, "'\n")
|
|
33 end
|
|
34 end
|
|
35 if f then
|
|
36 return f
|
|
37 else
|
|
38 error("dynport '"..name.."' not found:\n"..table.concat(hist), 3)
|
|
39 end
|
|
40 end
|
|
41 ]]
|
|
42
|
|
43
|
|
44 --- Process dynport files.
|
|
45 -- Files will be opened and processed according to the dynport format.
|
|
46 -- Function wrappers and constants will be installed.
|
|
47 -- Structure/Union type information have not been implemented yet.
|
|
48 -- @param name dynport name to lookup.
|
|
49 -- @unit table to use for import.
|
|
50 -- @field _dynport_libs contains.
|
|
51 -- @return unit table with imports.
|
|
52
|
|
53 function dynport_NEW(portname, t)
|
|
54 local t = t or _G
|
|
55 local port = loaded[portname]
|
|
56 if port then return port end
|
|
57 local file, errmsg = searchpath(portname, path)
|
|
58 if not file then error(errmsg) end
|
|
59 end
|
|
60
|
|
61 function dynportImport(name, unit)
|
|
62
|
|
63 local file = find(name)
|
|
64
|
|
65 if not unit._dynport_libs then
|
|
66 unit._dynport_libs = { }
|
|
67 end
|
|
68
|
|
69 local cached = unit._dynport_libs[name]
|
|
70 if cached then return unit end
|
|
71
|
|
72 if not file then
|
|
73 error("dynport "..name.. " not found")
|
|
74 end
|
|
75
|
|
76 local iter = file:lines()
|
|
77
|
|
78 local libs = { }
|
|
79
|
|
80 function dolib()
|
|
81 local libnames = ""
|
|
82 for line in iter do
|
|
83 if line == "." then break end
|
|
84 libnames = line
|
|
85 end
|
|
86 libs[#libs+1] = dynload(libnames)
|
|
87 end
|
|
88
|
|
89 function dofun()
|
|
90 local index = 1
|
|
91 local unresolved = {}
|
|
92 for line in iter do
|
|
93
|
|
94 if line == "." then break end
|
|
95
|
|
96 local pos = line:find("[(]")
|
|
97 local symbol = line:sub(1, pos-1)
|
|
98 local stop = line:find("[;]", pos+1)
|
|
99 local signature = line:sub(pos+1,stop-1)
|
|
100
|
|
101 local addr = dynsym(libs[#libs], symbol)
|
|
102
|
|
103 if type(addr) == "userdata" then
|
|
104 rawset(unit, symbol, makewrapper(addr, signature) )
|
|
105 -- module[symbol] = makewrapper(addr, signature)
|
|
106 else
|
|
107 unresolved[#unresolved] = symbol
|
|
108 end
|
|
109
|
|
110 end
|
|
111
|
|
112 if #unresolved ~= 0 then
|
|
113 print("unresolved symbols:")
|
|
114 print(table.concat(unresolved,"\n"))
|
|
115 end
|
|
116 end
|
|
117
|
|
118 function doconst()
|
|
119 for line in iter do
|
|
120 if line == "." then break end
|
|
121 local pos = line:find("=")
|
|
122 local key = line:sub(1, pos-1)
|
|
123 local value = line:sub(pos+1)
|
|
124 -- module[key] = tonumber(value)
|
|
125 rawset( unit, key, tonumber(value) )
|
|
126 end
|
|
127 end
|
|
128
|
|
129 function dostruct()
|
|
130 for line in iter do
|
|
131 if line == "." then break end
|
|
132 end
|
|
133 end
|
|
134
|
|
135 function dounion()
|
|
136 for line in iter do
|
|
137 if line == "." then break end
|
|
138 end
|
|
139 end
|
|
140
|
|
141 for line in iter do
|
|
142 if line == "." then break
|
|
143 elseif line == ":lib" then dolib()
|
|
144 elseif line == ":fun" then dofun()
|
|
145 elseif line == ":const" then doconst()
|
|
146 elseif line == ":struct" then dostruct()
|
|
147 elseif line == ":union" then dounion()
|
|
148 end
|
|
149 end
|
|
150
|
|
151 unit._dynport_libs[name] = libs
|
|
152
|
|
153 return unit
|
|
154
|
|
155 end
|
|
156
|
|
157 --- Dynamic bind C library Interfaces.
|
|
158 -- @param name dynport name which will be searched by
|
|
159 function dynport(portname)
|
|
160 return dynportImport(portname, _G)
|
|
161 end
|
|
162
|
|
163
|