| [1650] | 1 | -- tolua: declaration class | 
|---|
 | 2 | -- Written by Waldemar Celes | 
|---|
 | 3 | -- TeCGraf/PUC-Rio | 
|---|
 | 4 | -- Jul 1998 | 
|---|
 | 5 | -- $Id: $ | 
|---|
 | 6 |  | 
|---|
 | 7 | -- This code is free software; you can redistribute it and/or modify it. | 
|---|
 | 8 | -- The software provided hereunder is on an "as is" basis, and | 
|---|
 | 9 | -- the author has no obligation to provide maintenance, support, updates, | 
|---|
 | 10 | -- enhancements, or modifications. | 
|---|
 | 11 |  | 
|---|
 | 12 |  | 
|---|
 | 13 | -- Declaration class | 
|---|
 | 14 | -- Represents variable, function, or argument declaration. | 
|---|
 | 15 | -- Stores the following fields: | 
|---|
 | 16 | --  mod  = type modifiers | 
|---|
 | 17 | --  type = type | 
|---|
 | 18 | --  ptr  = "*" or "&", if representing a pointer or a reference | 
|---|
 | 19 | --  name = name | 
|---|
 | 20 | --  dim  = dimension, if a vector | 
|---|
 | 21 | --  def  = default value, if any (only for arguments) | 
|---|
 | 22 | --  ret  = "*" or "&", if value is to be returned (only for arguments) | 
|---|
 | 23 | classDeclaration = { | 
|---|
 | 24 |  mod = '', | 
|---|
 | 25 |  type = '', | 
|---|
 | 26 |  ptr = '', | 
|---|
 | 27 |  name = '', | 
|---|
 | 28 |  dim = '', | 
|---|
 | 29 |  ret = '', | 
|---|
 | 30 |  def = '' | 
|---|
 | 31 | } | 
|---|
 | 32 | classDeclaration.__index = classDeclaration | 
|---|
 | 33 | setmetatable(classDeclaration,classFeature) | 
|---|
 | 34 |  | 
|---|
 | 35 | -- Create an unique variable name | 
|---|
 | 36 | function create_varname () | 
|---|
 | 37 |  if not _varnumber then _varnumber = 0 end | 
|---|
 | 38 |  _varnumber = _varnumber + 1 | 
|---|
 | 39 |  return "tolua_var_".._varnumber | 
|---|
 | 40 | end | 
|---|
 | 41 |  | 
|---|
 | 42 | -- Check declaration name | 
|---|
 | 43 | -- It also identifies default values | 
|---|
 | 44 | function classDeclaration:checkname () | 
|---|
 | 45 |  | 
|---|
 | 46 |  if strsub(self.name,1,1) == '[' and not findtype(self.type) then | 
|---|
 | 47 |   self.name = self.type..self.name | 
|---|
 | 48 |   local m = split(self.mod,'%s%s*') | 
|---|
 | 49 |   self.type = m[m.n] | 
|---|
 | 50 |   self.mod = concat(m,1,m.n-1) | 
|---|
 | 51 |  end | 
|---|
 | 52 |  | 
|---|
 | 53 |  local t = split(self.name,'=') | 
|---|
 | 54 |  if t.n==2 then | 
|---|
 | 55 |   self.name = t[1] | 
|---|
 | 56 |   self.def = find_enum_var(t[t.n]) | 
|---|
 | 57 |  end | 
|---|
 | 58 |  | 
|---|
 | 59 |  local b,e,d = strfind(self.name,"%[(.-)%]") | 
|---|
 | 60 |  if b then | 
|---|
 | 61 |   self.name = strsub(self.name,1,b-1) | 
|---|
 | 62 |   self.dim = find_enum_var(d) | 
|---|
 | 63 |  end | 
|---|
 | 64 |  | 
|---|
 | 65 |  | 
|---|
 | 66 |  if self.type ~= '' and self.type ~= 'void' and self.name == '' then | 
|---|
 | 67 |   self.name = create_varname() | 
|---|
 | 68 |  elseif self.kind=='var' then | 
|---|
 | 69 |   if self.type=='' and self.name~='' then | 
|---|
 | 70 |    self.type = self.type..self.name | 
|---|
 | 71 |    self.name = create_varname() | 
|---|
 | 72 |   elseif findtype(self.name) then | 
|---|
 | 73 |    if self.type=='' then self.type = self.name | 
|---|
 | 74 |    else self.type = self.type..' '..self.name end | 
|---|
 | 75 |    self.name = create_varname() | 
|---|
 | 76 |   end | 
|---|
 | 77 |  end | 
|---|
 | 78 |  | 
|---|
 | 79 |  -- adjust type of string | 
|---|
 | 80 |  if self.type == 'char' and self.dim ~= '' then | 
|---|
 | 81 |          self.type = 'char*' | 
|---|
 | 82 |  end | 
|---|
 | 83 |  | 
|---|
 | 84 |         if self.kind and self.kind == 'var' then | 
|---|
 | 85 |                 self.name = string.gsub(self.name, ":.*$", "") -- ??? | 
|---|
 | 86 |         end | 
|---|
 | 87 | end | 
|---|
 | 88 |  | 
|---|
 | 89 | -- Check declaration type | 
|---|
 | 90 | -- Substitutes typedef's. | 
|---|
 | 91 | function classDeclaration:checktype () | 
|---|
 | 92 |  | 
|---|
 | 93 |  -- check if there is a pointer to basic type | 
|---|
 | 94 |  local basic = isbasic(self.type) | 
|---|
 | 95 |  if self.kind == 'func' and basic=='number' and string.find(self.ptr, "%*") then | 
|---|
 | 96 |         self.type = '_userdata' | 
|---|
 | 97 |         self.ptr = "" | 
|---|
 | 98 |  end | 
|---|
 | 99 |  if basic and self.ptr~='' then | 
|---|
 | 100 |   self.ret = self.ptr | 
|---|
 | 101 |   self.ptr = nil | 
|---|
 | 102 |   if isbasic(self.type) == 'number' then | 
|---|
 | 103 |         self.return_userdata = true | 
|---|
 | 104 |   end | 
|---|
 | 105 |  end | 
|---|
 | 106 |  | 
|---|
 | 107 |  -- check if there is array to be returned | 
|---|
 | 108 |  if self.dim~='' and self.ret~='' then | 
|---|
 | 109 |    error('#invalid parameter: cannot return an array of values') | 
|---|
 | 110 |  end | 
|---|
 | 111 |  -- restore 'void*' and 'string*' | 
|---|
 | 112 |  if self.type == '_userdata' then self.type = 'void*' | 
|---|
 | 113 |  elseif self.type == '_cstring' then self.type = 'char*' | 
|---|
 | 114 |  elseif self.type == '_lstate' then self.type = 'lua_State*' | 
|---|
 | 115 |  end | 
|---|
 | 116 |  | 
|---|
 | 117 |  -- resolve types inside the templates | 
|---|
 | 118 |  if self.type then | 
|---|
 | 119 |          self.type = resolve_template_types(self.type) | 
|---|
 | 120 |  end | 
|---|
 | 121 |  | 
|---|
 | 122 | -- | 
|---|
 | 123 | -- -- if returning value, automatically set default value | 
|---|
 | 124 | -- if self.ret ~= '' and self.def == '' then | 
|---|
 | 125 | --  self.def = '0' | 
|---|
 | 126 | -- end | 
|---|
 | 127 | -- | 
|---|
 | 128 |  | 
|---|
 | 129 | end | 
|---|
 | 130 |  | 
|---|
 | 131 | function resolve_template_types(type) | 
|---|
 | 132 |  | 
|---|
 | 133 |         if isbasic(type) then | 
|---|
 | 134 |                 return type | 
|---|
 | 135 |         end | 
|---|
 | 136 |         local b,_,m = string.find(type, "(%b<>)") | 
|---|
 | 137 |         if b then | 
|---|
 | 138 |  | 
|---|
 | 139 |                 m = split_c_tokens(string.sub(m, 2, -2), ",") | 
|---|
 | 140 |                 for i=1, table.getn(m) do | 
|---|
 | 141 |                         m[i] = string.gsub(m[i],"%s*([%*&])", "%1") | 
|---|
 | 142 |                         m[i] = findtype(m[i]) or m[i] | 
|---|
 | 143 |                         m[i] = resolve_template_types(m[i]) | 
|---|
 | 144 |                 end | 
|---|
 | 145 |  | 
|---|
 | 146 |                 local b,i | 
|---|
 | 147 |                 type,b,i = break_template(type) | 
|---|
 | 148 |                 local template_part = "<"..string.gsub(concat(m, 1, m.n), " ", ",")..">" | 
|---|
 | 149 |                 type = rebuild_template(type, b, template_part) | 
|---|
 | 150 |                 type = string.gsub(type, ">>", "> >") | 
|---|
 | 151 |         end | 
|---|
 | 152 |         return type | 
|---|
 | 153 | end | 
|---|
 | 154 |  | 
|---|
 | 155 | function break_template(s) | 
|---|
 | 156 |         local b,e,timpl = string.find(s, "(%b<>)") | 
|---|
 | 157 |         if timpl then | 
|---|
 | 158 |                 s = string.gsub(s, "%b<>", "") | 
|---|
 | 159 |                 return s, b, timpl | 
|---|
 | 160 |         else | 
|---|
 | 161 |                 return s, 0, nil | 
|---|
 | 162 |         end | 
|---|
 | 163 | end | 
|---|
 | 164 |  | 
|---|
 | 165 | function rebuild_template(s, b, timpl) | 
|---|
 | 166 |  | 
|---|
 | 167 |         if b == 0 then | 
|---|
 | 168 |                 return s | 
|---|
 | 169 |         end | 
|---|
 | 170 |  | 
|---|
 | 171 |         return string.sub(s, 1, b-1)..timpl..string.sub(s, b, -1) | 
|---|
 | 172 | end | 
|---|
 | 173 |  | 
|---|
 | 174 | -- Print method | 
|---|
 | 175 | function classDeclaration:print (ident,close) | 
|---|
 | 176 |  print(ident.."Declaration{") | 
|---|
 | 177 |  print(ident.." mod  = '"..self.mod.."',") | 
|---|
 | 178 |  print(ident.." type = '"..self.type.."',") | 
|---|
 | 179 |  print(ident.." ptr  = '"..self.ptr.."',") | 
|---|
 | 180 |  print(ident.." name = '"..self.name.."',") | 
|---|
 | 181 |  print(ident.." dim  = '"..self.dim.."',") | 
|---|
 | 182 |  print(ident.." def  = '"..self.def.."',") | 
|---|
 | 183 |  print(ident.." ret  = '"..self.ret.."',") | 
|---|
 | 184 |  print(ident.."}"..close) | 
|---|
 | 185 | end | 
|---|
 | 186 |  | 
|---|
 | 187 | -- check if array of values are returned to Lua | 
|---|
 | 188 | function classDeclaration:requirecollection (t) | 
|---|
 | 189 |  if self.mod ~= 'const' and | 
|---|
 | 190 |             self.dim and self.dim ~= '' and | 
|---|
 | 191 |                                  not isbasic(self.type) and | 
|---|
 | 192 |                                  self.ptr == '' then | 
|---|
 | 193 |                 local type = gsub(self.type,"%s*const%s+","") | 
|---|
 | 194 |                 t[type] = "tolua_collect_" .. clean_template(type) | 
|---|
 | 195 |                 return true | 
|---|
 | 196 |         end | 
|---|
 | 197 |         return false | 
|---|
 | 198 | end | 
|---|
 | 199 |  | 
|---|
 | 200 | -- declare tag | 
|---|
 | 201 | function classDeclaration:decltype () | 
|---|
 | 202 |  | 
|---|
 | 203 |         self.type = typevar(self.type) | 
|---|
 | 204 |         if strfind(self.mod,'const') then | 
|---|
 | 205 |                 self.type = 'const '..self.type | 
|---|
 | 206 |                 self.mod = gsub(self.mod,'const%s*','') | 
|---|
 | 207 |         end | 
|---|
 | 208 | end | 
|---|
 | 209 |  | 
|---|
 | 210 |  | 
|---|
 | 211 | -- output type checking | 
|---|
 | 212 | function classDeclaration:outchecktype (narg) | 
|---|
 | 213 |  local def | 
|---|
 | 214 |  local t = isbasic(self.type) | 
|---|
 | 215 |  if self.def~='' then | 
|---|
 | 216 |   def = 1 | 
|---|
 | 217 |  else | 
|---|
 | 218 |   def = 0 | 
|---|
 | 219 |  end | 
|---|
 | 220 |  if self.dim ~= '' then | 
|---|
 | 221 |         --if t=='string' then | 
|---|
 | 222 |         --      return 'tolua_isstringarray(tolua_S,'..narg..','..def..',&tolua_err)' | 
|---|
 | 223 |         --else | 
|---|
 | 224 |         return 'tolua_istable(tolua_S,'..narg..',0,&tolua_err)' | 
|---|
 | 225 |         --end | 
|---|
 | 226 |  elseif t then | 
|---|
 | 227 |         return 'tolua_is'..t..'(tolua_S,'..narg..','..def..',&tolua_err)' | 
|---|
 | 228 |  else | 
|---|
 | 229 |   return 'tolua_isusertype(tolua_S,'..narg..',"'..self.type..'",'..def..',&tolua_err)' | 
|---|
 | 230 |  end | 
|---|
 | 231 | end | 
|---|
 | 232 |  | 
|---|
 | 233 | function classDeclaration:builddeclaration (narg, cplusplus) | 
|---|
 | 234 |  local array = self.dim ~= '' and tonumber(self.dim)==nil | 
|---|
 | 235 |         local line = "" | 
|---|
 | 236 |  local ptr = '' | 
|---|
 | 237 |         local mod | 
|---|
 | 238 |         local type = self.type | 
|---|
 | 239 |  if self.dim ~= '' then | 
|---|
 | 240 |          type = gsub(self.type,'const%s+','')  -- eliminates const modifier for arrays | 
|---|
 | 241 |  end | 
|---|
 | 242 |  if self.ptr~='' and not isbasic(type) then ptr = '*' end | 
|---|
 | 243 |  line = concatparam(line," ",self.mod,type,ptr) | 
|---|
 | 244 |  if array then | 
|---|
 | 245 |   line = concatparam(line,'*') | 
|---|
 | 246 |  end | 
|---|
 | 247 |  line = concatparam(line,self.name) | 
|---|
 | 248 |  if self.dim ~= '' then | 
|---|
 | 249 |   if tonumber(self.dim)~=nil then | 
|---|
 | 250 |    line = concatparam(line,'[',self.dim,'];') | 
|---|
 | 251 |   else | 
|---|
 | 252 |         if cplusplus then | 
|---|
 | 253 |                 line = concatparam(line,' = new',type,ptr,'['..self.dim..'];') | 
|---|
 | 254 |         else | 
|---|
 | 255 |                 line = concatparam(line,' = (',type,ptr,'*)', | 
|---|
 | 256 |                 'malloc((',self.dim,')*sizeof(',type,ptr,'));') | 
|---|
 | 257 |         end | 
|---|
 | 258 |   end | 
|---|
 | 259 |  else | 
|---|
 | 260 |   local t = isbasic(type) | 
|---|
 | 261 |   line = concatparam(line,' = ') | 
|---|
 | 262 |   if t == 'state' then | 
|---|
 | 263 |         line = concatparam(line, 'tolua_S;') | 
|---|
 | 264 |   else | 
|---|
 | 265 |         --print("t is "..tostring(t)..", ptr is "..tostring(self.ptr)) | 
|---|
 | 266 |         if t == 'number' and string.find(self.ptr, "%*") then | 
|---|
 | 267 |                 t = 'userdata' | 
|---|
 | 268 |         end | 
|---|
 | 269 |         if not t and ptr=='' then line = concatparam(line,'*') end | 
|---|
 | 270 |         line = concatparam(line,'((',self.mod,type) | 
|---|
 | 271 |         if not t then | 
|---|
 | 272 |                 line = concatparam(line,'*') | 
|---|
 | 273 |         end | 
|---|
 | 274 |         line = concatparam(line,') ') | 
|---|
 | 275 |                         if isenum(type) then | 
|---|
 | 276 |                         line = concatparam(line,'(int) ') | 
|---|
 | 277 |                         end | 
|---|
 | 278 |         local def = 0 | 
|---|
 | 279 |         if self.def ~= '' then | 
|---|
 | 280 |                 def = self.def | 
|---|
 | 281 |                 if (ptr == '' or self.ptr == '&') and not t then | 
|---|
 | 282 |                         def = "(void*)&(const "..type..")"..def | 
|---|
 | 283 |                 end | 
|---|
 | 284 |         end | 
|---|
 | 285 |         if t then | 
|---|
 | 286 |         line = concatparam(line,'tolua_to'..t,'(tolua_S,',narg,',',def,'));') | 
|---|
 | 287 |         else | 
|---|
 | 288 |         line = concatparam(line,'tolua_tousertype(tolua_S,',narg,',',def,'));') | 
|---|
 | 289 |         end | 
|---|
 | 290 |   end | 
|---|
 | 291 |  end | 
|---|
 | 292 |         return line | 
|---|
 | 293 | end | 
|---|
 | 294 |  | 
|---|
 | 295 | -- Declare variable | 
|---|
 | 296 | function classDeclaration:declare (narg) | 
|---|
 | 297 |  if self.dim ~= '' and tonumber(self.dim)==nil then | 
|---|
 | 298 |          output('#ifdef __cplusplus\n') | 
|---|
 | 299 |                 output(self:builddeclaration(narg,true)) | 
|---|
 | 300 |                 output('#else\n') | 
|---|
 | 301 |                 output(self:builddeclaration(narg,false)) | 
|---|
 | 302 |          output('#endif\n') | 
|---|
 | 303 |         else | 
|---|
 | 304 |                 output(self:builddeclaration(narg,false)) | 
|---|
 | 305 |         end | 
|---|
 | 306 | end | 
|---|
 | 307 |  | 
|---|
 | 308 | -- Get parameter value | 
|---|
 | 309 | function classDeclaration:getarray (narg) | 
|---|
 | 310 |  if self.dim ~= '' then | 
|---|
 | 311 |          local type = gsub(self.type,'const ','') | 
|---|
 | 312 |   output('  {') | 
|---|
 | 313 |          output('#ifndef TOLUA_RELEASE\n') | 
|---|
 | 314 |   local def; if self.def~='' then def=1 else def=0 end | 
|---|
 | 315 |                 local t = isbasic(type) | 
|---|
 | 316 |                 if (t) then | 
|---|
 | 317 |    output('   if (!tolua_is'..t..'array(tolua_S,',narg,',',self.dim,',',def,',&tolua_err))') | 
|---|
 | 318 |                 else | 
|---|
 | 319 |    output('   if (!tolua_isusertypearray(tolua_S,',narg,',"',type,'",',self.dim,',',def,',&tolua_err))') | 
|---|
 | 320 |                 end | 
|---|
 | 321 |   output('    goto tolua_lerror;') | 
|---|
 | 322 |   output('   else\n') | 
|---|
 | 323 |          output('#endif\n') | 
|---|
 | 324 |   output('   {') | 
|---|
 | 325 |   output('    int i;') | 
|---|
 | 326 |   output('    for(i=0; i<'..self.dim..';i++)') | 
|---|
 | 327 |   local t = isbasic(type) | 
|---|
 | 328 |   local ptr = '' | 
|---|
 | 329 |   if self.ptr~='' then ptr = '*' end | 
|---|
 | 330 |   output('   ',self.name..'[i] = ') | 
|---|
 | 331 |   if not t and ptr=='' then output('*') end | 
|---|
 | 332 |   output('((',type) | 
|---|
 | 333 |   if not t then | 
|---|
 | 334 |    output('*') | 
|---|
 | 335 |   end | 
|---|
 | 336 |   output(') ') | 
|---|
 | 337 |   local def = 0 | 
|---|
 | 338 |   if self.def ~= '' then def = self.def end | 
|---|
 | 339 |   if t then | 
|---|
 | 340 |    output('tolua_tofield'..t..'(tolua_S,',narg,',i+1,',def,'));') | 
|---|
 | 341 |   else | 
|---|
 | 342 |    output('tolua_tofieldusertype(tolua_S,',narg,',i+1,',def,'));') | 
|---|
 | 343 |   end | 
|---|
 | 344 |   output('   }') | 
|---|
 | 345 |   output('  }') | 
|---|
 | 346 |  end | 
|---|
 | 347 | end | 
|---|
 | 348 |  | 
|---|
 | 349 | -- Get parameter value | 
|---|
 | 350 | function classDeclaration:setarray (narg) | 
|---|
 | 351 |  if not strfind(self.type,'const%s+') and self.dim ~= '' then | 
|---|
 | 352 |          local type = gsub(self.type,'const ','') | 
|---|
 | 353 |   output('  {') | 
|---|
 | 354 |   output('   int i;') | 
|---|
 | 355 |   output('   for(i=0; i<'..self.dim..';i++)') | 
|---|
 | 356 |   local t,ct = isbasic(type) | 
|---|
 | 357 |   if t then | 
|---|
 | 358 |    output('    tolua_pushfield'..t..'(tolua_S,',narg,',i+1,(',ct,')',self.name,'[i]);') | 
|---|
 | 359 |   else | 
|---|
 | 360 |    if self.ptr == '' then | 
|---|
 | 361 |      output('   {') | 
|---|
 | 362 |      output('#ifdef __cplusplus\n') | 
|---|
 | 363 |      output('    void* tolua_obj = new',type,'(',self.name,'[i]);') | 
|---|
 | 364 |      output('    tolua_pushfieldusertype_and_takeownership(tolua_S,',narg,',i+1,tolua_obj,"',type,'");') | 
|---|
 | 365 |      output('#else\n') | 
|---|
 | 366 |      output('    void* tolua_obj = tolua_copy(tolua_S,(void*)&',self.name,'[i],sizeof(',type,'));') | 
|---|
 | 367 |      output('    tolua_pushfieldusertype(tolua_S,',narg,',i+1,tolua_obj,"',type,'");') | 
|---|
 | 368 |      output('#endif\n') | 
|---|
 | 369 |      output('   }') | 
|---|
 | 370 |    else | 
|---|
 | 371 |     output('   tolua_pushfieldusertype(tolua_S,',narg,',i+1,(void*)',self.name,'[i],"',type,'");') | 
|---|
 | 372 |    end | 
|---|
 | 373 |   end | 
|---|
 | 374 |   output('  }') | 
|---|
 | 375 |  end | 
|---|
 | 376 | end | 
|---|
 | 377 |  | 
|---|
 | 378 | -- Free dynamically allocated array | 
|---|
 | 379 | function classDeclaration:freearray () | 
|---|
 | 380 |  if self.dim ~= '' and tonumber(self.dim)==nil then | 
|---|
 | 381 |          output('#ifdef __cplusplus\n') | 
|---|
 | 382 |                 output('  delete []',self.name,';') | 
|---|
 | 383 |          output('#else\n') | 
|---|
 | 384 |   output('  free(',self.name,');') | 
|---|
 | 385 |          output('#endif\n') | 
|---|
 | 386 |  end | 
|---|
 | 387 | end | 
|---|
 | 388 |  | 
|---|
 | 389 | -- Pass parameter | 
|---|
 | 390 | function classDeclaration:passpar () | 
|---|
 | 391 |  if self.ptr=='&' and not isbasic(self.type) then | 
|---|
 | 392 |   output('*'..self.name) | 
|---|
 | 393 |  elseif self.ret=='*' then | 
|---|
 | 394 |   output('&'..self.name) | 
|---|
 | 395 |  else | 
|---|
 | 396 |   output(self.name) | 
|---|
 | 397 |  end | 
|---|
 | 398 | end | 
|---|
 | 399 |  | 
|---|
 | 400 | -- Return parameter value | 
|---|
 | 401 | function classDeclaration:retvalue () | 
|---|
 | 402 |  if self.ret ~= '' then | 
|---|
 | 403 |   local t,ct = isbasic(self.type) | 
|---|
 | 404 |   if t and t~='' then | 
|---|
 | 405 |    output('   tolua_push'..t..'(tolua_S,(',ct,')'..self.name..');') | 
|---|
 | 406 |   else | 
|---|
 | 407 |    output('   tolua_pushusertype(tolua_S,(void*)'..self.name..',"',self.type,'");') | 
|---|
 | 408 |   end | 
|---|
 | 409 |   return 1 | 
|---|
 | 410 |  end | 
|---|
 | 411 |  return 0 | 
|---|
 | 412 | end | 
|---|
 | 413 |  | 
|---|
 | 414 | -- Internal constructor | 
|---|
 | 415 | function _Declaration (t) | 
|---|
 | 416 |  | 
|---|
 | 417 |  setmetatable(t,classDeclaration) | 
|---|
 | 418 |  t:buildnames() | 
|---|
 | 419 |  t:checkname() | 
|---|
 | 420 |  t:checktype() | 
|---|
 | 421 |  local ft = findtype(t.type) or t.type | 
|---|
 | 422 |  if not isenum(ft) then | 
|---|
 | 423 |         t.mod, t.type = applytypedef(t.mod, ft) | 
|---|
 | 424 |  end | 
|---|
 | 425 |  | 
|---|
 | 426 |  if t.kind=="var" and (string.find(t.mod, "tolua_property%s") or string.find(t.mod, "tolua_property$")) then | 
|---|
 | 427 |         t.mod = string.gsub(t.mod, "tolua_property", "tolua_property__"..get_property_type()) | 
|---|
 | 428 |  end | 
|---|
 | 429 |  | 
|---|
 | 430 |  return t | 
|---|
 | 431 | end | 
|---|
 | 432 |  | 
|---|
 | 433 | -- Constructor | 
|---|
 | 434 | -- Expects the string declaration. | 
|---|
 | 435 | -- The kind of declaration can be "var" or "func". | 
|---|
 | 436 | function Declaration (s,kind,is_parameter) | 
|---|
 | 437 |  | 
|---|
 | 438 |  -- eliminate spaces if default value is provided | 
|---|
 | 439 |  s = gsub(s,"%s*=%s*","=") | 
|---|
 | 440 |  s = gsub(s, "%s*<", "<") | 
|---|
 | 441 |  | 
|---|
 | 442 |  local defb,tmpdef | 
|---|
 | 443 |  defb,_,tmpdef = string.find(s, "(=.*)$") | 
|---|
 | 444 |  if defb then | 
|---|
 | 445 |         s = string.gsub(s, "=.*$", "") | 
|---|
 | 446 |  else | 
|---|
 | 447 |         tmpdef = '' | 
|---|
 | 448 |  end | 
|---|
 | 449 |  if kind == "var" then | 
|---|
 | 450 |   -- check the form: void | 
|---|
 | 451 |   if s == '' or s == 'void' then | 
|---|
 | 452 |    return _Declaration{type = 'void', kind = kind, is_parameter = is_parameter} | 
|---|
 | 453 |   end | 
|---|
 | 454 |  end | 
|---|
 | 455 |  | 
|---|
 | 456 |  -- check the form: mod type*& name | 
|---|
 | 457 |  local t = split_c_tokens(s,'%*%s*&') | 
|---|
 | 458 |  if t.n == 2 then | 
|---|
 | 459 |   if kind == 'func' then | 
|---|
 | 460 |    error("#invalid function return type: "..s) | 
|---|
 | 461 |   end | 
|---|
 | 462 |   --local m = split(t[1],'%s%s*') | 
|---|
 | 463 |   local m = split_c_tokens(t[1],'%s+') | 
|---|
 | 464 |   return _Declaration{ | 
|---|
 | 465 |    name = t[2]..tmpdef, | 
|---|
 | 466 |    ptr = '*', | 
|---|
 | 467 |    ret = '&', | 
|---|
 | 468 |    --type = rebuild_template(m[m.n], tb, timpl), | 
|---|
 | 469 |    type = m[m.n], | 
|---|
 | 470 |    mod = concat(m,1,m.n-1), | 
|---|
 | 471 |    is_parameter = is_parameter, | 
|---|
 | 472 |    kind = kind | 
|---|
 | 473 |   } | 
|---|
 | 474 |  end | 
|---|
 | 475 |  | 
|---|
 | 476 |  -- check the form: mod type** name | 
|---|
 | 477 |  t = split_c_tokens(s,'%*%s*%*') | 
|---|
 | 478 |  if t.n == 2 then | 
|---|
 | 479 |   if kind == 'func' then | 
|---|
 | 480 |    error("#invalid function return type: "..s) | 
|---|
 | 481 |   end | 
|---|
 | 482 |   --local m = split(t[1],'%s%s*') | 
|---|
 | 483 |   local m = split_c_tokens(t[1],'%s+') | 
|---|
 | 484 |   return _Declaration{ | 
|---|
 | 485 |    name = t[2]..tmpdef, | 
|---|
 | 486 |    ptr = '*', | 
|---|
 | 487 |    ret = '*', | 
|---|
 | 488 |    --type = rebuild_template(m[m.n], tb, timpl), | 
|---|
 | 489 |    type = m[m.n], | 
|---|
 | 490 |    mod = concat(m,1,m.n-1), | 
|---|
 | 491 |    is_parameter = is_parameter, | 
|---|
 | 492 |    kind = kind | 
|---|
 | 493 |   } | 
|---|
 | 494 |  end | 
|---|
 | 495 |  | 
|---|
 | 496 |  -- check the form: mod type& name | 
|---|
 | 497 |  t = split_c_tokens(s,'&') | 
|---|
 | 498 |  if t.n == 2 then | 
|---|
 | 499 |   --local m = split(t[1],'%s%s*') | 
|---|
 | 500 |   local m = split_c_tokens(t[1],'%s+') | 
|---|
 | 501 |   return _Declaration{ | 
|---|
 | 502 |    name = t[2]..tmpdef, | 
|---|
 | 503 |    ptr = '&', | 
|---|
 | 504 |    --type = rebuild_template(m[m.n], tb, timpl), | 
|---|
 | 505 |    type = m[m.n], | 
|---|
 | 506 |    mod = concat(m,1,m.n-1), | 
|---|
 | 507 |    is_parameter = is_parameter, | 
|---|
 | 508 |    kind = kind | 
|---|
 | 509 |   } | 
|---|
 | 510 |  end | 
|---|
 | 511 |  | 
|---|
 | 512 |  -- check the form: mod type* name | 
|---|
 | 513 |  local s1 = gsub(s,"(%b\[\])",function (n) return gsub(n,'%*','\1') end) | 
|---|
 | 514 |  t = split_c_tokens(s1,'%*') | 
|---|
 | 515 |  if t.n == 2 then | 
|---|
 | 516 |   t[2] = gsub(t[2],'\1','%*') -- restore * in dimension expression | 
|---|
 | 517 |   --local m = split(t[1],'%s%s*') | 
|---|
 | 518 |   local m = split_c_tokens(t[1],'%s+') | 
|---|
 | 519 |   return _Declaration{ | 
|---|
 | 520 |    name = t[2]..tmpdef, | 
|---|
 | 521 |    ptr = '*', | 
|---|
 | 522 |    type = m[m.n], | 
|---|
 | 523 |    --type = rebuild_template(m[m.n], tb, timpl), | 
|---|
 | 524 |    mod = concat(m,1,m.n-1)   , | 
|---|
 | 525 |    is_parameter = is_parameter, | 
|---|
 | 526 |    kind = kind | 
|---|
 | 527 |   } | 
|---|
 | 528 |  end | 
|---|
 | 529 |  | 
|---|
 | 530 |  if kind == 'var' then | 
|---|
 | 531 |   -- check the form: mod type name | 
|---|
 | 532 |   --t = split(s,'%s%s*') | 
|---|
 | 533 |   t = split_c_tokens(s,'%s+') | 
|---|
 | 534 |   local v | 
|---|
 | 535 |   if findtype(t[t.n]) then v = create_varname() else v = t[t.n]; t.n = t.n-1 end | 
|---|
 | 536 |   return _Declaration{ | 
|---|
 | 537 |    name = v..tmpdef, | 
|---|
 | 538 |    --type = rebuild_template(t[t.n], tb, timpl), | 
|---|
 | 539 |    type = t[t.n], | 
|---|
 | 540 |    mod = concat(t,1,t.n-1), | 
|---|
 | 541 |    is_parameter = is_parameter, | 
|---|
 | 542 |    kind = kind | 
|---|
 | 543 |   } | 
|---|
 | 544 |  | 
|---|
 | 545 |  else -- kind == "func" | 
|---|
 | 546 |  | 
|---|
 | 547 |   -- check the form: mod type name | 
|---|
 | 548 |   --t = split(s,'%s%s*') | 
|---|
 | 549 |   t = split_c_tokens(s,'%s+') | 
|---|
 | 550 |   local v = t[t.n]  -- last word is the function name | 
|---|
 | 551 |   local tp,md | 
|---|
 | 552 |   if t.n>1 then | 
|---|
 | 553 |    tp = t[t.n-1] | 
|---|
 | 554 |    md = concat(t,1,t.n-2) | 
|---|
 | 555 |   end | 
|---|
 | 556 |   --if tp then tp = rebuild_template(tp, tb, timpl) end | 
|---|
 | 557 |   return _Declaration{ | 
|---|
 | 558 |    name = v, | 
|---|
 | 559 |    type = tp, | 
|---|
 | 560 |    mod = md, | 
|---|
 | 561 |    is_parameter = is_parameter, | 
|---|
 | 562 |    kind = kind | 
|---|
 | 563 |   } | 
|---|
 | 564 |  end | 
|---|
 | 565 |  | 
|---|
 | 566 | end | 
|---|
 | 567 |  | 
|---|