| 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 = { | 
|---|
| 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', | 
|---|
| 36 | } | 
|---|
| 37 |  | 
|---|
| 38 | _basic_ctype = { | 
|---|
| 39 |     number = "lua_Number", | 
|---|
| 40 |     string = "const char*", | 
|---|
| 41 |     userdata = "void*", | 
|---|
| 42 |     boolean = "bool", | 
|---|
| 43 |     value = "int", | 
|---|
| 44 |     state = "lua_State*", | 
|---|
| 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) | 
|---|
| 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}) | 
|---|
| 75 | end | 
|---|
| 76 |  | 
|---|
| 77 | function applyrenaming (s) | 
|---|
| 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 | 
|---|
| 85 | end | 
|---|
| 86 |  | 
|---|
| 87 | -- Error handler | 
|---|
| 88 | function tolua_error (s,f) | 
|---|
| 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 | 
|---|
| 111 | end | 
|---|
| 112 |  | 
|---|
| 113 | function warning (msg) | 
|---|
| 114 |     local out = _OUTPUT | 
|---|
| 115 |     _OUTPUT = _STDERR | 
|---|
| 116 |     write("\n** tolua warning: "..msg..".\n\n") | 
|---|
| 117 |     _OUTPUT = out | 
|---|
| 118 | end | 
|---|
| 119 |  | 
|---|
| 120 | -- register an user defined type: returns full type | 
|---|
| 121 | function regtype (t) | 
|---|
| 122 |     --if isbasic(t) then | 
|---|
| 123 |     --    return t | 
|---|
| 124 |     --end | 
|---|
| 125 |     local ft = findtype(t) | 
|---|
| 126 |  | 
|---|
| 127 |     if not _usertype[ft] then | 
|---|
| 128 |         return appendusertype(t) | 
|---|
| 129 |     end | 
|---|
| 130 |     return ft | 
|---|
| 131 | end | 
|---|
| 132 |  | 
|---|
| 133 | -- return type name: returns full type | 
|---|
| 134 | function typevar(type) | 
|---|
| 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 | 
|---|
| 145 | end | 
|---|
| 146 |  | 
|---|
| 147 | -- check if basic type | 
|---|
| 148 | function isbasic (type) | 
|---|
| 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 | 
|---|
| 156 | end | 
|---|
| 157 |  | 
|---|
| 158 | -- split string using a token | 
|---|
| 159 | function split (s,t) | 
|---|
| 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 | 
|---|
| 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 |  | 
|---|
| 180 |     s = string.gsub(s, "^%s*", "") | 
|---|
| 181 |     s = string.gsub(s, "%s*$", "") | 
|---|
| 182 |  | 
|---|
| 183 |     local token_begin = 1 | 
|---|
| 184 |     local token_end = 1 | 
|---|
| 185 |     local ofs = 1 | 
|---|
| 186 |     local ret = {n=0} | 
|---|
| 187 |  | 
|---|
| 188 |     function add_token(ofs) | 
|---|
| 189 |  | 
|---|
| 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 | 
|---|
| 196 |  | 
|---|
| 197 |     while ofs <= string.len(s) do | 
|---|
| 198 |  | 
|---|
| 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 | 
|---|
| 208 |  | 
|---|
| 209 |                 local block | 
|---|
| 210 |                 if char == "(" then block = "^%b()" end | 
|---|
| 211 |                 if char == "<" then block = "^%b<>" end | 
|---|
| 212 |  | 
|---|
| 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 | 
|---|
| 220 |  | 
|---|
| 221 |             else | 
|---|
| 222 |                 ofs = ofs+1 | 
|---|
| 223 |             end | 
|---|
| 224 |         end | 
|---|
| 225 |  | 
|---|
| 226 |     end | 
|---|
| 227 |     add_token(ofs) | 
|---|
| 228 |     --if ret.n == 0 then | 
|---|
| 229 |  | 
|---|
| 230 |     --    ret.n=1 | 
|---|
| 231 |     --    ret[1] = "" | 
|---|
| 232 |     --end | 
|---|
| 233 |  | 
|---|
| 234 |     return ret | 
|---|
| 235 |  | 
|---|
| 236 | end | 
|---|
| 237 |  | 
|---|
| 238 | -- concatenate strings of a table | 
|---|
| 239 | function concat (t,f,l,jstr) | 
|---|
| 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 | 
|---|
| 249 | end | 
|---|
| 250 |  | 
|---|
| 251 | -- concatenate all parameters, following output rules | 
|---|
| 252 | function concatparam (line, ...) | 
|---|
| 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 | 
|---|
| 269 | end | 
|---|
| 270 |  | 
|---|
| 271 | -- output line | 
|---|
| 272 | function output (...) | 
|---|
| 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 | 
|---|
| 288 | end | 
|---|
| 289 |  | 
|---|
| 290 | function get_property_methods(ptype, name) | 
|---|
| 291 |  | 
|---|
| 292 |     if get_property_methods_hook and get_property_methods_hook(ptype,name) then | 
|---|
| 293 |         return get_property_methods_hook(ptype, name) | 
|---|
| 294 |     end | 
|---|
| 295 |  | 
|---|
| 296 |     if ptype == "default" then -- get_name, set_name | 
|---|
| 297 |         return "get_"..name, "set_"..name | 
|---|
| 298 |     end | 
|---|
| 299 |  | 
|---|
| 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 | 
|---|
| 303 |  | 
|---|
| 304 |     if ptype == "overload" then -- name, name | 
|---|
| 305 |         return name,name | 
|---|
| 306 |     end | 
|---|
| 307 |  | 
|---|
| 308 |     return nil | 
|---|
| 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) | 
|---|
| 317 |     -- p.code has all the input code from the pkg | 
|---|
| 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 |  | 
|---|
| 353 |     return nil | 
|---|
| 354 | end | 
|---|
| 355 |  | 
|---|
| 356 |  | 
|---|