| [1650] | 1 | -- tolua: basic utility functions | 
|---|
 | 2 | -- Written by Waldemar Celes | 
|---|
 | 3 | -- TeCGraf/PUC-Rio | 
|---|
 | 4 | -- Jul 1998 | 
|---|
 | 5 | -- Last update: Apr 2003 | 
|---|
 | 6 | -- $Id: $ | 
|---|
 | 7 |  | 
|---|
 | 8 | -- This code is free software; you can redistribute it and/or modify it. | 
|---|
 | 9 | -- The software provided hereunder is on an "as is" basis, and | 
|---|
 | 10 | -- the author has no obligation to provide maintenance, support, updates, | 
|---|
 | 11 | -- enhancements, or modifications. | 
|---|
 | 12 |  | 
|---|
 | 13 |  | 
|---|
 | 14 | -- Basic C types and their corresponding Lua types | 
|---|
 | 15 | -- All occurrences of "char*" will be replaced by "_cstring", | 
|---|
 | 16 | -- and all occurrences of "void*" will be replaced by "_userdata" | 
|---|
 | 17 | _basic = { | 
|---|
| [2710] | 18 |     ['void'] = '', | 
|---|
 | 19 |     ['char'] = 'number', | 
|---|
 | 20 |     ['int'] = 'number', | 
|---|
 | 21 |     ['short'] = 'number', | 
|---|
 | 22 |     ['long'] = 'number', | 
|---|
 | 23 |     ['unsigned'] = 'number', | 
|---|
 | 24 |     ['float'] = 'number', | 
|---|
 | 25 |     ['double'] = 'number', | 
|---|
 | 26 |     ['_cstring'] = 'string', | 
|---|
 | 27 |     ['_userdata'] = 'userdata', | 
|---|
 | 28 |     ['char*'] = 'string', | 
|---|
 | 29 |     ['void*'] = 'userdata', | 
|---|
 | 30 |     ['bool'] = 'boolean', | 
|---|
 | 31 |     ['lua_Object'] = 'value', | 
|---|
 | 32 |     ['LUA_VALUE'] = 'value',    -- for compatibility with tolua 4.0 | 
|---|
 | 33 |     ['lua_State*'] = 'state', | 
|---|
 | 34 |     ['_lstate'] = 'state', | 
|---|
 | 35 |     ['lua_Function'] = 'value', | 
|---|
| [1650] | 36 | } | 
|---|
 | 37 |  | 
|---|
 | 38 | _basic_ctype = { | 
|---|
| [2710] | 39 |     number = "lua_Number", | 
|---|
 | 40 |     string = "const char*", | 
|---|
 | 41 |     userdata = "void*", | 
|---|
 | 42 |     boolean = "bool", | 
|---|
 | 43 |     value = "int", | 
|---|
 | 44 |     state = "lua_State*", | 
|---|
| [1650] | 45 | } | 
|---|
 | 46 |  | 
|---|
 | 47 | -- functions the are used to do a 'raw push' of basic types | 
|---|
 | 48 | _basic_raw_push = {} | 
|---|
 | 49 |  | 
|---|
 | 50 | -- List of user defined types | 
|---|
 | 51 | -- Each type corresponds to a variable name that stores its tag value. | 
|---|
 | 52 | _usertype = {} | 
|---|
 | 53 |  | 
|---|
 | 54 | -- List of types that have to be collected | 
|---|
 | 55 | _collect = {} | 
|---|
 | 56 |  | 
|---|
 | 57 | -- List of types | 
|---|
 | 58 | _global_types = {n=0} | 
|---|
 | 59 | _global_types_hash = {} | 
|---|
 | 60 |  | 
|---|
 | 61 | -- list of classes | 
|---|
 | 62 | _global_classes = {} | 
|---|
 | 63 |  | 
|---|
 | 64 | -- List of enum constants | 
|---|
 | 65 | _global_enums = {} | 
|---|
 | 66 |  | 
|---|
 | 67 | -- List of auto renaming | 
|---|
 | 68 | _renaming = {} | 
|---|
 | 69 | function appendrenaming (s) | 
|---|
| [2710] | 70 |     local b,e,old,new = strfind(s,"%s*(.-)%s*@%s*(.-)%s*$") | 
|---|
 | 71 |     if not b then | 
|---|
 | 72 |         error("#Invalid renaming syntax; it should be of the form: pattern@pattern") | 
|---|
 | 73 |     end | 
|---|
 | 74 |     tinsert(_renaming,{old=old, new=new}) | 
|---|
| [1650] | 75 | end | 
|---|
 | 76 |  | 
|---|
 | 77 | function applyrenaming (s) | 
|---|
| [2710] | 78 |     for i=1,getn(_renaming) do | 
|---|
 | 79 |         local m,n = gsub(s,_renaming[i].old,_renaming[i].new) | 
|---|
 | 80 |         if n ~= 0 then | 
|---|
 | 81 |             return m | 
|---|
 | 82 |         end | 
|---|
 | 83 |     end | 
|---|
 | 84 |     return nil | 
|---|
| [1650] | 85 | end | 
|---|
 | 86 |  | 
|---|
 | 87 | -- Error handler | 
|---|
 | 88 | function tolua_error (s,f) | 
|---|
| [2710] | 89 |     if _curr_code then | 
|---|
 | 90 |         print("***curr code for error is "..tostring(_curr_code)) | 
|---|
 | 91 |         print(debug.traceback()) | 
|---|
 | 92 |     end | 
|---|
 | 93 |     local out = _OUTPUT | 
|---|
 | 94 |     _OUTPUT = _STDERR | 
|---|
 | 95 |     if strsub(s,1,1) == '#' then | 
|---|
 | 96 |         write("\n** tolua: "..strsub(s,2)..".\n\n") | 
|---|
 | 97 |         if _curr_code then | 
|---|
 | 98 |             local _,_,s = strfind(_curr_code,"^%s*(.-\n)") -- extract first line | 
|---|
 | 99 |             if s==nil then s = _curr_code end | 
|---|
 | 100 |             s = gsub(s,"_userdata","void*") -- return with 'void*' | 
|---|
 | 101 |             s = gsub(s,"_cstring","char*")  -- return with 'char*' | 
|---|
 | 102 |             s = gsub(s,"_lstate","lua_State*")  -- return with 'lua_State*' | 
|---|
 | 103 |             write("Code being processed:\n"..s.."\n") | 
|---|
 | 104 |         end | 
|---|
 | 105 |     else | 
|---|
 | 106 |         if not f then f = "(f is nil)" end | 
|---|
 | 107 |         print("\n** tolua internal error: "..f..s..".\n\n") | 
|---|
 | 108 |         return | 
|---|
 | 109 |     end | 
|---|
 | 110 |     _OUTPUT = out | 
|---|
| [1650] | 111 | end | 
|---|
 | 112 |  | 
|---|
 | 113 | function warning (msg) | 
|---|
| [2710] | 114 |     local out = _OUTPUT | 
|---|
 | 115 |     _OUTPUT = _STDERR | 
|---|
 | 116 |     write("\n** tolua warning: "..msg..".\n\n") | 
|---|
 | 117 |     _OUTPUT = out | 
|---|
| [1650] | 118 | end | 
|---|
 | 119 |  | 
|---|
 | 120 | -- register an user defined type: returns full type | 
|---|
 | 121 | function regtype (t) | 
|---|
| [2710] | 122 |     --if isbasic(t) then | 
|---|
 | 123 |     --    return t | 
|---|
 | 124 |     --end | 
|---|
 | 125 |     local ft = findtype(t) | 
|---|
| [1650] | 126 |  | 
|---|
| [2710] | 127 |     if not _usertype[ft] then | 
|---|
 | 128 |         return appendusertype(t) | 
|---|
 | 129 |     end | 
|---|
 | 130 |     return ft | 
|---|
| [1650] | 131 | end | 
|---|
 | 132 |  | 
|---|
 | 133 | -- return type name: returns full type | 
|---|
 | 134 | function typevar(type) | 
|---|
| [2710] | 135 |     if type == '' or type == 'void' then | 
|---|
 | 136 |         return type | 
|---|
 | 137 |     else | 
|---|
 | 138 |         local ft = findtype(type) | 
|---|
 | 139 |         if ft then | 
|---|
 | 140 |             return ft | 
|---|
 | 141 |         end | 
|---|
 | 142 |         _usertype[type] = type | 
|---|
 | 143 |         return type | 
|---|
 | 144 |     end | 
|---|
| [1650] | 145 | end | 
|---|
 | 146 |  | 
|---|
 | 147 | -- check if basic type | 
|---|
 | 148 | function isbasic (type) | 
|---|
| [2710] | 149 |     local t = gsub(type,'const ','') | 
|---|
 | 150 |     local m,t = applytypedef('', t) | 
|---|
 | 151 |     local b = _basic[t] | 
|---|
 | 152 |     if b then | 
|---|
 | 153 |         return b,_basic_ctype[b] | 
|---|
 | 154 |     end | 
|---|
 | 155 |     return nil | 
|---|
| [1650] | 156 | end | 
|---|
 | 157 |  | 
|---|
 | 158 | -- split string using a token | 
|---|
 | 159 | function split (s,t) | 
|---|
| [2710] | 160 |     local l = {n=0} | 
|---|
 | 161 |     local f = function (s) | 
|---|
 | 162 |         l.n = l.n + 1 | 
|---|
 | 163 |         l[l.n] = s | 
|---|
 | 164 |         return "" | 
|---|
 | 165 |     end | 
|---|
 | 166 |     local p = "%s*(.-)%s*"..t.."%s*" | 
|---|
 | 167 |     s = gsub(s,"^%s+","") | 
|---|
 | 168 |     s = gsub(s,"%s+$","") | 
|---|
 | 169 |     s = gsub(s,p,f) | 
|---|
 | 170 |     l.n = l.n + 1 | 
|---|
 | 171 |     l[l.n] = gsub(s,"(%s%s*)$","") | 
|---|
 | 172 |     return l | 
|---|
| [1650] | 173 | end | 
|---|
 | 174 |  | 
|---|
 | 175 | -- splits a string using a pattern, considering the spacial cases of C code (templates, function parameters, etc) | 
|---|
 | 176 | -- pattern can't contain the '^' (as used to identify the begining of the line) | 
|---|
 | 177 | -- also strips whitespace | 
|---|
 | 178 | function split_c_tokens(s, pat) | 
|---|
 | 179 |  | 
|---|
| [2710] | 180 |     s = string.gsub(s, "^%s*", "") | 
|---|
 | 181 |     s = string.gsub(s, "%s*$", "") | 
|---|
| [1650] | 182 |  | 
|---|
| [2710] | 183 |     local token_begin = 1 | 
|---|
 | 184 |     local token_end = 1 | 
|---|
 | 185 |     local ofs = 1 | 
|---|
 | 186 |     local ret = {n=0} | 
|---|
| [1650] | 187 |  | 
|---|
| [2710] | 188 |     function add_token(ofs) | 
|---|
| [1650] | 189 |  | 
|---|
| [2710] | 190 |         local t = string.sub(s, token_begin, ofs) | 
|---|
 | 191 |         t = string.gsub(t, "^%s*", "") | 
|---|
 | 192 |         t = string.gsub(t, "%s*$", "") | 
|---|
 | 193 |         ret.n = ret.n + 1 | 
|---|
 | 194 |         ret[ret.n] = t | 
|---|
 | 195 |     end | 
|---|
| [1650] | 196 |  | 
|---|
| [2710] | 197 |     while ofs <= string.len(s) do | 
|---|
| [1650] | 198 |  | 
|---|
| [2710] | 199 |         local sub = string.sub(s, ofs, -1) | 
|---|
 | 200 |         local b,e = string.find(sub, "^"..pat) | 
|---|
 | 201 |         if b then | 
|---|
 | 202 |             add_token(ofs-1) | 
|---|
 | 203 |             ofs = ofs+e | 
|---|
 | 204 |             token_begin = ofs | 
|---|
 | 205 |         else | 
|---|
 | 206 |             local char = string.sub(s, ofs, ofs) | 
|---|
 | 207 |             if char == "(" or char == "<" then | 
|---|
| [1650] | 208 |  | 
|---|
| [2710] | 209 |                 local block | 
|---|
 | 210 |                 if char == "(" then block = "^%b()" end | 
|---|
 | 211 |                 if char == "<" then block = "^%b<>" end | 
|---|
| [1650] | 212 |  | 
|---|
| [2710] | 213 |                 b,e = string.find(sub, block) | 
|---|
 | 214 |                 if not b then | 
|---|
 | 215 |                     -- unterminated block? | 
|---|
 | 216 |                     ofs = ofs+1 | 
|---|
 | 217 |                 else | 
|---|
 | 218 |                     ofs = ofs + e | 
|---|
 | 219 |                 end | 
|---|
| [1650] | 220 |  | 
|---|
| [2710] | 221 |             else | 
|---|
 | 222 |                 ofs = ofs+1 | 
|---|
 | 223 |             end | 
|---|
 | 224 |         end | 
|---|
| [1650] | 225 |  | 
|---|
| [2710] | 226 |     end | 
|---|
 | 227 |     add_token(ofs) | 
|---|
 | 228 |     --if ret.n == 0 then | 
|---|
| [1650] | 229 |  | 
|---|
| [2710] | 230 |     --    ret.n=1 | 
|---|
 | 231 |     --    ret[1] = "" | 
|---|
 | 232 |     --end | 
|---|
| [1650] | 233 |  | 
|---|
| [2710] | 234 |     return ret | 
|---|
| [1650] | 235 |  | 
|---|
 | 236 | end | 
|---|
 | 237 |  | 
|---|
 | 238 | -- concatenate strings of a table | 
|---|
 | 239 | function concat (t,f,l,jstr) | 
|---|
| [2710] | 240 |     jstr = jstr or " " | 
|---|
 | 241 |     local s = '' | 
|---|
 | 242 |     local i=f | 
|---|
 | 243 |     while i<=l do | 
|---|
 | 244 |         s = s..t[i] | 
|---|
 | 245 |         i = i+1 | 
|---|
 | 246 |         if i <= l then s = s..jstr end | 
|---|
 | 247 |     end | 
|---|
 | 248 |     return s | 
|---|
| [1650] | 249 | end | 
|---|
 | 250 |  | 
|---|
 | 251 | -- concatenate all parameters, following output rules | 
|---|
 | 252 | function concatparam (line, ...) | 
|---|
| [2710] | 253 |     local i=1 | 
|---|
 | 254 |     while i<=arg.n do | 
|---|
 | 255 |         if _cont and not strfind(_cont,'[%(,"]') and | 
|---|
 | 256 |             strfind(arg[i],"^[%a_~]") then | 
|---|
 | 257 |             line = line .. ' ' | 
|---|
 | 258 |         end | 
|---|
 | 259 |         line = line .. arg[i] | 
|---|
 | 260 |         if arg[i] ~= '' then | 
|---|
 | 261 |             _cont = strsub(arg[i],-1,-1) | 
|---|
 | 262 |         end | 
|---|
 | 263 |         i = i+1 | 
|---|
 | 264 |     end | 
|---|
 | 265 |     if strfind(arg[arg.n],"[%/%)%;%{%}]$") then | 
|---|
 | 266 |         _cont=nil line = line .. '\n' | 
|---|
 | 267 |     end | 
|---|
 | 268 |     return line | 
|---|
| [1650] | 269 | end | 
|---|
 | 270 |  | 
|---|
 | 271 | -- output line | 
|---|
 | 272 | function output (...) | 
|---|
| [2710] | 273 |     local i=1 | 
|---|
 | 274 |     while i<=arg.n do | 
|---|
 | 275 |         if _cont and not strfind(_cont,'[%(,"]') and | 
|---|
 | 276 |             strfind(arg[i],"^[%a_~]") then | 
|---|
 | 277 |             write(' ') | 
|---|
 | 278 |         end | 
|---|
 | 279 |         write(arg[i]) | 
|---|
 | 280 |         if arg[i] ~= '' then | 
|---|
 | 281 |             _cont = strsub(arg[i],-1,-1) | 
|---|
 | 282 |         end | 
|---|
 | 283 |         i = i+1 | 
|---|
 | 284 |     end | 
|---|
 | 285 |     if strfind(arg[arg.n],"[%/%)%;%{%}]$") then | 
|---|
 | 286 |         _cont=nil write('\n') | 
|---|
 | 287 |     end | 
|---|
| [1650] | 288 | end | 
|---|
 | 289 |  | 
|---|
 | 290 | function get_property_methods(ptype, name) | 
|---|
 | 291 |  | 
|---|
| [2710] | 292 |     if get_property_methods_hook and get_property_methods_hook(ptype,name) then | 
|---|
 | 293 |         return get_property_methods_hook(ptype, name) | 
|---|
 | 294 |     end | 
|---|
| [1650] | 295 |  | 
|---|
| [2710] | 296 |     if ptype == "default" then -- get_name, set_name | 
|---|
 | 297 |         return "get_"..name, "set_"..name | 
|---|
 | 298 |     end | 
|---|
| [1650] | 299 |  | 
|---|
| [2710] | 300 |     if ptype == "qt" then -- name, setName | 
|---|
 | 301 |         return name, "set"..string.upper(string.sub(name, 1, 1))..string.sub(name, 2, -1) | 
|---|
 | 302 |     end | 
|---|
| [1650] | 303 |  | 
|---|
| [2710] | 304 |     if ptype == "overload" then -- name, name | 
|---|
 | 305 |         return name,name | 
|---|
 | 306 |     end | 
|---|
| [1650] | 307 |  | 
|---|
| [2710] | 308 |     return nil | 
|---|
| [1650] | 309 | end | 
|---|
 | 310 |  | 
|---|
 | 311 | -------------- the hooks | 
|---|
 | 312 |  | 
|---|
 | 313 | -- called right after processing the $[ichl]file directives, | 
|---|
 | 314 | -- right before processing anything else | 
|---|
 | 315 | -- takes the package object as the parameter | 
|---|
 | 316 | function preprocess_hook(p) | 
|---|
| [2710] | 317 |     -- p.code has all the input code from the pkg | 
|---|
| [1650] | 318 | end | 
|---|
 | 319 |  | 
|---|
 | 320 |  | 
|---|
 | 321 | -- called for every $ifile directive | 
|---|
 | 322 | -- takes a table with a string called 'code' inside, the filename, and any extra arguments | 
|---|
 | 323 | -- passed to $ifile. no return value | 
|---|
 | 324 | function include_file_hook(t, filename, ...) | 
|---|
 | 325 |  | 
|---|
 | 326 | end | 
|---|
 | 327 |  | 
|---|
 | 328 | -- called after processing anything that's not code (like '$renaming', comments, etc) | 
|---|
 | 329 | -- and right before parsing the actual code. | 
|---|
 | 330 | -- takes the Package object with all the code on the 'code' key. no return value | 
|---|
 | 331 | function preparse_hook(package) | 
|---|
 | 332 |  | 
|---|
 | 333 | end | 
|---|
 | 334 |  | 
|---|
 | 335 |  | 
|---|
 | 336 | -- called after writing all the output. | 
|---|
 | 337 | -- takes the Package object | 
|---|
 | 338 | function post_output_hook(package) | 
|---|
 | 339 |  | 
|---|
 | 340 | end | 
|---|
 | 341 |  | 
|---|
 | 342 |  | 
|---|
 | 343 | -- called from 'get_property_methods' to get the methods to retrieve a property | 
|---|
 | 344 | -- according to its type | 
|---|
 | 345 | function get_property_methods_hook(property_type, name) | 
|---|
 | 346 |  | 
|---|
 | 347 | end | 
|---|
 | 348 |  | 
|---|
 | 349 | -- called from ClassContainer:doparse with the string being parsed | 
|---|
 | 350 | -- return nil, or a substring | 
|---|
 | 351 | function parser_hook(s) | 
|---|
 | 352 |  | 
|---|
| [2710] | 353 |     return nil | 
|---|
| [1650] | 354 | end | 
|---|
 | 355 |  | 
|---|
 | 356 |  | 
|---|