~ubuntu-branches/debian/sid/freeciv/sid

« back to all changes in this revision

Viewing changes to dependencies/toluaxx/src/bin/lua/tlx_function.lua

  • Committer: Bazaar Package Importer
  • Author(s): Clint Adams, Karl Goetz, Clint Adams
  • Date: 2010-02-23 22:09:02 UTC
  • mfrom: (7.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20100223220902-s3spqi1x4e190y0t
[ Karl Goetz ]
* Remove civserver files in /etc/ggzd/ (Closes: 523772, 517787)
* Adding ${misc:Depends} to all binary packages (lintian warnings)

[ Clint Adams ]
* New upstream version.
  - Drop data_dsc_use_bindir.diff (binary pathnames have changed).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
-- tolua: function class
 
2
-- Written by Waldemar Celes
 
3
-- TeCGraf/PUC-Rio
 
4
-- Jul 1998
 
5
-- $Id: tlx_function.lua 13010 2007-06-22 21:18:04Z wsimpson $
 
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
 
 
14
-- Function class
 
15
-- Represents a function or a class method.
 
16
-- The following fields are stored:
 
17
--  mod  = type modifiers
 
18
--  type = type
 
19
--  ptr  = "*" or "&", if representing a pointer or a reference
 
20
--  name = name
 
21
--  lname = lua name
 
22
--  args  = list of argument declarations
 
23
--  const = if it is a method receiving a const "this".
 
24
classFunction = {
 
25
   mod = '',
 
26
   type = '',
 
27
   ptr = '',
 
28
   name = '',
 
29
   args = {n=0},
 
30
   const = '',
 
31
   last_overload_error = true,
 
32
   last_overload_rmfun = false
 
33
}
 
34
classFunction.__index = classFunction
 
35
setmetatable(classFunction,classFeature)
 
36
 
 
37
-- declare tags
 
38
function classFunction:decltype ()
 
39
   self.type = typevar(self.type)
 
40
   if strfind(self.mod,'const') then
 
41
      self.type = 'const '..self.type
 
42
      self.mod = gsub(self.mod,'const','')
 
43
   end
 
44
   local i=1
 
45
   while self.args[i] do
 
46
      self.args[i]:decltype()
 
47
      i = i+1
 
48
   end
 
49
end
 
50
 
 
51
 
 
52
-- Write binding function
 
53
-- Outputs C/C++ binding function.
 
54
function classFunction:supcode (local_constructor)
 
55
   local overload = strsub(self.cname,-2,-1) - 1  -- indicate overloaded func
 
56
   local nret = 0      -- number of returned values
 
57
   local class = self:inclass()
 
58
   local _,_,static = strfind(self.mod,'^%s*(static)')
 
59
   if class then
 
60
      if self.name == 'new' and self.parent.flags.pure_virtual then
 
61
         -- no constructor for classes with pure virtual methods
 
62
         return
 
63
      end
 
64
      
 
65
      if local_constructor then
 
66
         output("/* method: new_local of class ",class," */")
 
67
      else
 
68
         output("/* method:",self.name," of class ",class," */")
 
69
      end
 
70
   else
 
71
      output("/* function:",self.name," */")
 
72
   end
 
73
   
 
74
   if local_constructor then
 
75
      output("#ifndef TOLUA_DISABLE_"..self.cname.."_local")
 
76
      output("\nstatic int",self.cname.."_local","(lua_State* tolua_S)")
 
77
   else
 
78
      output("#ifndef TOLUA_DISABLE_"..self.cname)
 
79
      output("\nstatic int",self.cname,"(lua_State* tolua_S)")
 
80
   end
 
81
   output("{")
 
82
   
 
83
   -- check types
 
84
   if overload < 0 then
 
85
      --output('#ifndef TOLUA_RELEASE\n')
 
86
   end
 
87
   output(' tolua_Error tolua_err;')
 
88
   output(' if (\n')
 
89
   -- check self
 
90
   local narg
 
91
   if class then narg=2 else narg=1 end
 
92
   if class then
 
93
      local func = 'tolua_isusertype'
 
94
      local type = self.parent.type
 
95
      if self.name=='new' or static~=nil then
 
96
         func = 'tolua_isusertable'
 
97
         type = self.parent.type
 
98
      end
 
99
      if self.const ~= '' then
 
100
         type = "const "..type
 
101
      end
 
102
      output('     !'..func..'(tolua_S,1,"'..type..'",0,&tolua_err) ||\n')
 
103
   end
 
104
   -- check args
 
105
   if self.args[1].type ~= 'void' then
 
106
      local i=1
 
107
      while self.args[i] do
 
108
         local btype = isbasic(self.args[i].type)
 
109
         if btype ~= 'value' and btype ~= 'state' then
 
110
            output('     !'..self.args[i]:outchecktype(narg)..' ||\n')
 
111
         end
 
112
         if btype ~= 'state' then
 
113
            narg = narg+1
 
114
         end
 
115
         i = i+1
 
116
      end
 
117
   end
 
118
   -- check end of list
 
119
   output('     !tolua_isnoobj(tolua_S,'..narg..',&tolua_err)\n )')
 
120
   output('  goto tolua_lerror;')
 
121
   
 
122
   output(' else\n')
 
123
   if overload < 0 then
 
124
      --output('#endif\n')
 
125
   end
 
126
   output(' {')
 
127
   
 
128
   -- declare self, if the case
 
129
   local narg
 
130
   if class then narg=2 else narg=1 end
 
131
   if class and self.name~='new' and static==nil then
 
132
      output(' ',self.const,self.parent.type,'*','self = ')
 
133
      output('(',self.const,self.parent.type,'*) ')
 
134
      output('tolua_tousertype(tolua_S,1,0);')
 
135
   elseif static then
 
136
      _,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)')
 
137
   end
 
138
   -- declare parameters
 
139
   if self.args[1].type ~= 'void' then
 
140
      local i=1
 
141
      while self.args[i] do
 
142
         self.args[i]:declare(narg)
 
143
         if isbasic(self.args[i].type) ~= "state" then
 
144
            narg = narg+1
 
145
         end
 
146
         i = i+1
 
147
      end
 
148
   end
 
149
   
 
150
   -- check self
 
151
   if class and self.name~='new' and static==nil then
 
152
      --output('#ifndef TOLUA_RELEASE\n')
 
153
      output('  if (!self) tolua_error(tolua_S,"invalid \'self\' in function \''..self.name..'\'",NULL);');
 
154
      --output('#endif\n')
 
155
   end
 
156
   
 
157
   -- get array element values
 
158
   if class then narg=2 else narg=1 end
 
159
   if self.args[1].type ~= 'void' then
 
160
      local i=1
 
161
      while self.args[i] do
 
162
         self.args[i]:getarray(narg)
 
163
         narg = narg+1
 
164
         i = i+1
 
165
      end
 
166
   end
 
167
   
 
168
   local out = string.find(self.mod, "tolua_outside")
 
169
   -- call function
 
170
   if class and self.name=='delete' then
 
171
      output('  delete self;')
 
172
   elseif class and self.name == 'operator&[]' then
 
173
      if flags['1'] then -- for compatibility with tolua5 ?
 
174
         output('  self->operator[](',self.args[1].name,'-1) = ',self.args[2].name,';')
 
175
      else
 
176
         output('  self->operator[](',self.args[1].name,') = ',self.args[2].name,';')
 
177
      end
 
178
   else
 
179
      output('  {')
 
180
      if self.type ~= '' and self.type ~= 'void' then
 
181
         output('  ',self.mod,self.type,self.ptr,'tolua_ret = ')
 
182
         output('(',self.mod,self.type,self.ptr,') ')
 
183
      else
 
184
         output('  ')
 
185
      end
 
186
      if class and self.name=='new' then
 
187
         output('new',self.type,'(')
 
188
      elseif class and static then
 
189
         if out then
 
190
            output(self.name,'(')
 
191
         else
 
192
            output(class..'::'..self.name,'(')
 
193
         end
 
194
      elseif class then
 
195
         if out then
 
196
            output(self.name,'(')
 
197
         else
 
198
            if self.cast_operator then
 
199
               output('static_cast<',self.mod,self.type,self.ptr,'>(*self')
 
200
            else 
 
201
               output('self->'..self.name,'(')
 
202
            end
 
203
         end
 
204
      else
 
205
         output(self.name,'(')
 
206
      end
 
207
      
 
208
      if out and not static then
 
209
         output('self')
 
210
         if self.args[1] and self.args[1].name ~= '' then
 
211
            output(',')
 
212
         end
 
213
      end
 
214
      -- write parameters
 
215
      local i=1
 
216
      while self.args[i] do
 
217
         self.args[i]:passpar()
 
218
         i = i+1
 
219
         if self.args[i] then
 
220
            output(',')
 
221
         end
 
222
      end
 
223
      
 
224
      if class and self.name == 'operator[]' and flags['1'] then
 
225
         output('-1);')
 
226
      else
 
227
         output(');')
 
228
      end
 
229
 
 
230
      -- return values
 
231
      if self.type ~= '' and self.type ~= 'void' then
 
232
         nret = nret + 1
 
233
         local t,ct = isbasic(self.type)
 
234
         if t then
 
235
            if self.rets.dnil then
 
236
               output('   if(tolua_ret=='..self.rets.def..')   ')
 
237
               if self.try_overload_nil and overload >= 0 then
 
238
                  output('goto tolua_lerror;')
 
239
               else
 
240
                  output('tolua_pushnil(tolua_S);')
 
241
               end
 
242
               output('   else')
 
243
            end
 
244
            if self.cast_operator and _basic_raw_push[t] then
 
245
               output('   ',_basic_raw_push[t],'(tolua_S,(',ct,')tolua_ret);')
 
246
            else
 
247
               output('   tolua_push'..t..'(tolua_S,(',ct,')tolua_ret);')
 
248
            end
 
249
         else
 
250
            if self.try_overload_nil and overload >= 0 then
 
251
               output('   if(tolua_ret==NULL)   goto tolua_lerror;')
 
252
            end
 
253
            t = self.type
 
254
            new_t = string.gsub(t, "const%s+", "")
 
255
            if self.ptr == '' then
 
256
               output('   {')
 
257
               output('#ifdef __cplusplus\n')
 
258
               output('    void* tolua_obj = new',new_t,'(tolua_ret);')
 
259
               output('    tolua_pushusertype_and_takeownership(tolua_S,tolua_obj,"',t,'");')
 
260
               output('#else\n')
 
261
               output('    void* tolua_obj = tolua_copy(tolua_S,(void*)&tolua_ret,sizeof(',t,'));')
 
262
               output('    tolua_pushusertype_and_takeownership(tolua_S,tolua_obj,"',t,'");')
 
263
               output('#endif\n')
 
264
               output('   }')
 
265
            elseif self.ptr == '&' then
 
266
               output('   tolua_pushusertype(tolua_S,(void*)&tolua_ret,"',t,'");')
 
267
            else
 
268
               if local_constructor then
 
269
                  output('   tolua_pushusertype_and_takeownership(tolua_S,(void *)tolua_ret,"',t,'");')
 
270
               else
 
271
                  output('   tolua_pushusertype(tolua_S,(void*)tolua_ret,"',t,'");')
 
272
               end
 
273
            end
 
274
         end
 
275
      end
 
276
      local i=1
 
277
      while self.args[i] do
 
278
         if self.args.n==2 then
 
279
            if self.try_overload_nil and overload >= 0 then
 
280
               self.args[i].try_overload_nil=true
 
281
            end
 
282
         end
 
283
         nret = nret + self.args[i]:retvalue()
 
284
         i = i+1
 
285
      end
 
286
      output('  }')
 
287
 
 
288
      -- set array element values
 
289
      if class then narg=2 else narg=1 end
 
290
      if self.args[1].type ~= 'void' then
 
291
         local i=1
 
292
         while self.args[i] do
 
293
            self.args[i]:setarray(narg)
 
294
            narg = narg+1
 
295
            i = i+1
 
296
         end
 
297
      end
 
298
 
 
299
      -- free dynamically allocated array
 
300
      if self.args[1].type ~= 'void' then
 
301
         local i=1
 
302
         while self.args[i] do
 
303
            self.args[i]:freearray()
 
304
            i = i+1
 
305
         end
 
306
      end
 
307
   end
 
308
 
 
309
   output(' }')
 
310
   output(' return '..nret..';')
 
311
 
 
312
   -- call overloaded function or generate error
 
313
   if overload < 0 then
 
314
      if self.last_overload_error then
 
315
         --output('#ifndef TOLUA_RELEASE\n')
 
316
         output('tolua_lerror:\n')
 
317
         output('  tolua_error(tolua_S,"#ferror in function \''..self.lname..'\'.",&tolua_err);')
 
318
         output('  return 0;')
 
319
         --output('#endif\n')
 
320
      else
 
321
         --output('#ifndef TOLUA_RELEASE\n')
 
322
         output('tolua_lerror:\n')
 
323
         --if self.last_overload_rmfun then
 
324
         --   output('  lua_remove(tolua_S,2);\n')
 
325
         --   output('  return '..tostring(narg-1)..';')
 
326
         --else
 
327
         output('  return '..tostring(narg-1)..';\n')
 
328
         --end
 
329
         --output('#endif\n')
 
330
      end
 
331
   else
 
332
      local _local = ""
 
333
      if local_constructor then
 
334
         _local = "_local"
 
335
      end
 
336
      output('tolua_lerror:\n')
 
337
      output('  return '..strsub(self.cname,1,-3)..format("%02d",overload).._local..'(tolua_S);')
 
338
   end
 
339
   output('}')
 
340
   output('#endif //#ifndef TOLUA_DISABLE\n')
 
341
   output('\n')
 
342
 
 
343
   -- recursive call to write local constructor
 
344
   if class and self.name=='new' and not local_constructor then
 
345
      self:supcode(1)
 
346
   end
 
347
 
 
348
end
 
349
 
 
350
 
 
351
-- register function
 
352
function classFunction:register (pre)
 
353
   if not self:check_public_access() then return end
 
354
 
 
355
   if self.name == 'new' and self.parent.flags.pure_virtual then
 
356
      -- no constructor for classes with pure virtual methods
 
357
      return
 
358
   end
 
359
 
 
360
   output(pre..'tolua_function(tolua_S,"'..self.lname..'",'..self.cname..');')
 
361
   if self.name == 'new' then
 
362
      output(pre..'tolua_function(tolua_S,"new_local",'..self.cname..'_local);')
 
363
      output(pre..'tolua_function(tolua_S,".call",'..self.cname..'_local);')
 
364
      --output(' tolua_set_call_event(tolua_S,'..self.cname..'_local, "'..self.parent.type..'");')
 
365
   end
 
366
end
 
367
 
 
368
-- Print method
 
369
function classFunction:print (ident,close)
 
370
   print(ident.."Function{")
 
371
   print(ident.." mod  = '"..self.mod.."',")
 
372
   print(ident.." type = '"..self.type.."',")
 
373
   print(ident.." ptr  = '"..self.ptr.."',")
 
374
   print(ident.." name = '"..self.name.."',")
 
375
   print(ident.." lname = '"..self.lname.."',")
 
376
   print(ident.." const = '"..self.const.."',")
 
377
   print(ident.." cname = '"..self.cname.."',")
 
378
   print(ident.." lname = '"..self.lname.."',")
 
379
   print(ident.." args = {")
 
380
   local i=1
 
381
   while self.args[i] do
 
382
      self.args[i]:print(ident.."  ",",")
 
383
      i = i+1
 
384
   end
 
385
   print(ident.." },")
 
386
   print(ident.." rets=")
 
387
   self.rets:print(ident.."  ",",")
 
388
   print(ident.."}"..close)
 
389
end
 
390
 
 
391
-- check if it returns an object by value
 
392
function classFunction:requirecollection (t)
 
393
   local r = false
 
394
   if self.type ~= '' and not isbasic(self.type) and self.ptr=='' then
 
395
      local type = gsub(self.type,"%s*const%s+","")
 
396
      t[type] = "tolua_collect_" .. clean_template(type)
 
397
      r = true
 
398
   end
 
399
   local i=1
 
400
   while self.args[i] do
 
401
      r = self.args[i]:requirecollection(t) or r
 
402
      i = i+1
 
403
   end
 
404
   return r
 
405
end
 
406
 
 
407
-- determine lua function name overload
 
408
function classFunction:overload ()
 
409
   return self.parent:overload(self.lname)
 
410
end
 
411
 
 
412
 
 
413
function param_object(par) -- returns true if the parameter has an object as its default value
 
414
   if not string.find(par, '=') then return false end -- it has no default value
 
415
   local _,_,def = string.find(par, "=(.*)$")
 
416
   if string.find(par, "|") then -- a list of flags
 
417
      return true
 
418
   end
 
419
   if string.find(par, "%*") then -- it's a pointer with a default value
 
420
      if string.find(par, '=%s*new') then -- it's a pointer with an instance as default parameter.. is that valid?
 
421
         return true
 
422
      end
 
423
      return false -- default value is 'NULL' or something
 
424
   end
 
425
 
 
426
   if string.find(par, "[%(&]") then
 
427
      return true
 
428
   end -- default value is a constructor call (most likely for a const reference)
 
429
   --if string.find(par, "&") then
 
430
   --   if string.find(def, ":") or string.find(def, "^%s*new%s+") then
 
431
   --           -- it's a reference with default to something like Class::member, or 'new Class'
 
432
   --           return true
 
433
   --   end
 
434
   --end
 
435
 
 
436
   return false -- ?
 
437
end
 
438
 
 
439
function strip_last_arg(all_args, last_arg) -- strips the default value from the last argument
 
440
   local _,_,s_arg = string.find(last_arg, "^([^=]+)")
 
441
   last_arg = string.gsub(last_arg, "([%%%(%)])", "%%%1");
 
442
   all_args = string.gsub(all_args, "%s*,%s*"..last_arg.."%s*%)%s*$", ")")
 
443
   return all_args, s_arg
 
444
end
 
445
 
 
446
 
 
447
 
 
448
-- Internal constructor
 
449
function _Function (t)
 
450
   setmetatable(t,classFunction)
 
451
 
 
452
   if t.const ~= 'const' and t.const ~= '' then
 
453
      error("#invalid 'const' specification")
 
454
   end
 
455
 
 
456
   append(t)
 
457
   if t:inclass() then
 
458
      --print ('t.name is '..t.name..', parent.name is '..t.parent.name)
 
459
      if string.gsub(t.name, "%b<>", "") == string.gsub(t.parent.original_name or t.parent.name, "%b<>", "") then
 
460
         t.name = 'new'
 
461
         t.lname = 'new'
 
462
         t.parent._new = true
 
463
         t.type = t.parent.name
 
464
         t.ptr = '*'
 
465
      elseif string.gsub(t.name, "%b<>", "") == '~'..string.gsub(t.parent.original_name or t.parent.name, "%b<>", "") then
 
466
         t.name = 'delete'
 
467
         t.lname = 'delete'
 
468
         t.parent._delete = true
 
469
      end
 
470
   end
 
471
   t.cname = t:cfuncname("tolua")..t:overload(t)
 
472
   return t
 
473
end
 
474
 
 
475
-- Constructor
 
476
-- Expects three strings: one representing the function declaration,
 
477
-- another representing the argument list, and the third representing
 
478
-- the "const" or empty string.
 
479
function Function (d,a,c,r)
 
480
   --local t = split(strsub(a,2,-2),',') -- eliminate braces
 
481
   --local t = split_params(strsub(a,2,-2))
 
482
   if not flags['W'] and string.find(a, "%.%.%.%s*%)") then
 
483
      warning("Functions with variable arguments (`...') are not supported. Ignoring "..d..a..c)
 
484
      return nil
 
485
   end
 
486
 
 
487
   r=r or ""
 
488
   local i=1
 
489
   local l = {n=0}
 
490
 
 
491
   a = string.gsub(a, "%s*([%(%)])%s*", "%1")
 
492
   local t,strip,last = strip_pars(strsub(a,2,-2));
 
493
   if strip then
 
494
      --local ns = string.sub(strsub(a,1,-2), 1, -(string.len(last)+1))
 
495
      local ns = join(t, ",", 1, last-1)
 
496
 
 
497
      ns = "("..string.gsub(ns, "%s*,%s*$", "")..')'
 
498
      --ns = strip_defaults(ns)
 
499
 
 
500
      Function(d, ns, c)
 
501
      for i=1,last do
 
502
         t[i] = string.gsub(t[i], "=.*$", "")
 
503
      end
 
504
   end
 
505
 
 
506
   while t[i] do
 
507
      l.n = l.n+1
 
508
      l[l.n] = Declaration(t[i],'var',true)
 
509
      i = i+1
 
510
   end
 
511
   local f = Declaration(d,'func')
 
512
   f.args = l
 
513
   f.const = c
 
514
   f.rets = Declaration(f.type..r,'var',true)
 
515
   return _Function(f)
 
516
end
 
517
 
 
518
function join(t, sep, first, last)
 
519
   first = first or 1
 
520
   last = last or table.getn(t)
 
521
   local lsep = ""
 
522
   local ret = ""
 
523
   local loop = false
 
524
   for i = first,last do
 
525
      ret = ret..lsep..t[i]
 
526
      lsep = sep
 
527
      loop = true
 
528
   end
 
529
   if not loop then
 
530
      return ""
 
531
   end
 
532
   return ret
 
533
end
 
534
 
 
535
function strip_pars(s)
 
536
   local t = split_c_tokens(s, ',')
 
537
   local strip = false
 
538
   local last
 
539
 
 
540
   for i=t.n,1,-1 do
 
541
 
 
542
      if not strip and param_object(t[i]) then
 
543
         last = i
 
544
         strip = true
 
545
      end
 
546
      --if strip then
 
547
      --        t[i] = string.gsub(t[i], "=.*$", "")
 
548
      --end
 
549
   end
 
550
 
 
551
   return t,strip,last
 
552
end
 
553
 
 
554
function strip_defaults(s)
 
555
   s = string.gsub(s, "^%(", "")
 
556
   s = string.gsub(s, "%)$", "")
 
557
 
 
558
   local t = split_c_tokens(s, ",")
 
559
   local sep, ret = "",""
 
560
   for i=1,t.n do
 
561
      t[i] = string.gsub(t[i], "=.*$", "")
 
562
      ret = ret..sep..t[i]
 
563
      sep = ","
 
564
   end
 
565
 
 
566
   return "("..ret..")"
 
567
end
 
568
 
 
569