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