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