| [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 |  | 
|---|