ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/include/cfperl.h
Revision: 1.81
Committed: Sun Jul 1 05:00:18 2007 UTC (16 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.80: +11 -12 lines
Log Message:
- upgrade crossfire trt to the GPL version 3 (hopefully correctly).
- add a single file covered by the GNU Affero General Public License
  (which is not yet released, so I used the current draft, which is
  legally a bit wavy, but its likely better than nothing as it expresses
  direct intent by the authors, and we can upgrade as soon as it has been
  released).
  * this should ensure availability of source code for the server at least
    and hopefully also archetypes and maps even when modified versions
    are not being distributed, in accordance of section 13 of the agplv3.

File Contents

# Content
1 /*
2 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 *
4 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen
7 *
8 * Crossfire TRT is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 * The authors can be reached via e-mail to <crossfire@schmorp.de>
22 */
23
24 //
25 // cfperl.h perl interface
26 //
27 #ifndef CFPERL_H__
28 #define CFPERL_H__
29
30 #include <cstdarg>
31 #include <cstdio>
32 #include <bitset>
33
34 using namespace std;
35
36 #include <EXTERN.h>
37 #include <perl.h>
38 #include <XSUB.h>
39
40 #include <EventAPI.h>
41 #include <CoroAPI.h>
42
43 #include "util.h"
44 #include "keyword.h"
45 #include "dynbuf.h"
46 #include "callback.h"
47
48 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
49
50 // optimisations/workaround for functions requiring my_perl in scope (anti-bloat)
51 #undef localtime
52 #undef srand48
53 #undef drand48
54 #undef srandom
55 #undef readdir
56 #undef getprotobyname
57 #undef gethostbyname
58 #undef ctime
59 #undef strerror
60
61 // same here, massive symbol spamming
62 #undef do_open
63 #undef do_close
64 #undef ref
65 #undef seed
66
67 // perl bug #40256: perl does overwrite those with reentrant versions
68 // but does not initialise their state structures.
69 #undef random
70 #undef crypt
71
72 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
73
74 // some macros to simplify perl in-calls
75
76 #define CHECK_ERROR \
77 if (SvTRUE (ERRSV)) \
78 LOG (llevError, "runtime error in %s: %s\n", __func__, SvPVutf8_nolen (ERRSV));
79
80 #define CALL_BEGIN(args) dSP; ENTER; SAVETMPS; PUSHMARK (SP); EXTEND (SP, args)
81 #define CALL_ARG_SV(sv) PUSHs (sv_2mortal (sv)) // separate because no refcount inc
82 #define CALL_ARG(expr) PUSHs (sv_2mortal (to_sv (expr)))
83 #define CALL_CALL(name, flags) PUTBACK; int count = call_pv (name, (flags) | G_EVAL); SPAGAIN;
84 #define CALL_END CHECK_ERROR; FREETMPS; LEAVE
85
86 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
87
88 void cfperl_init ();
89 void cfperl_main ();
90 void cfperl_emergency_save ();
91 void cfperl_cleanup (int make_core);
92 void cfperl_make_book (object *book, int level);
93 void cfperl_send_msg (client *ns, int color, const char *type, const char *msg);
94
95 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
96
97 extern tstamp runtime; // virtual server time, excluding time jumps and lag
98 extern tstamp NOW; // real time of current server tick
99
100 enum event_klass
101 {
102 KLASS_NONE,
103 KLASS_GLOBAL,
104 KLASS_ATTACHABLE,
105 KLASS_CLIENT,
106 KLASS_PLAYER,
107 KLASS_OBJECT,
108 KLASS_MAP,
109 KLASS_COMMAND,
110 };
111
112 enum event_type
113 {
114 # define def(klass,name) EVENT_ ## klass ## _ ## name,
115 # include "eventinc.h"
116 # undef def
117 NUM_EVENT_TYPES
118 };
119
120 // in which global events or per-type events are we interested
121 extern bitset<NUM_EVENT_TYPES> ev_want_event;
122 extern bitset<NUM_TYPES> ev_want_type;
123
124 #define ARG_AV(o) DT_AV , static_cast<AV *> (o)
125 #define ARG_INT(v) DT_INT , static_cast<int> (v)
126 #define ARG_INT64(v) DT_INT64 , static_cast<sint64> (v)
127 #define ARG_DOUBLE(v) DT_DOUBLE, static_cast<double> (v)
128 #define ARG_STRING(v) DT_STRING, static_cast<const char *> (v)
129 #define ARG_DATA(s,l) DT_DATA , static_cast<const void *> (s), int (l)
130 #define ARG_OBJECT(o) DT_OBJECT, (void *)(static_cast<object *> (o))
131 #define ARG_MAP(o) DT_MAP , (void *)(static_cast<maptile *> (o))
132 #define ARG_PLAYER(o) DT_PLAYER, (void *)(static_cast<player *> (o))
133 #define ARG_ARCH(o) DT_ARCH , (void *)(static_cast<archetype *> (o))
134 #define ARG_CLIENT(o) DT_CLIENT, (void *)(static_cast<client *> (o))
135 #define ARG_PARTY(o) DT_PARTY , (void *)(static_cast<party *> (o))
136 #define ARG_REGION(o) DT_REGION, (void *)(static_cast<region *> (o))
137
138 // the ", ## __VA_ARGS" is, unfortunately, a gnu-cpp extension
139 #define INVOKE(obj,event, ...) (expect_false ((obj)->should_invoke (event)) ? (obj)->invoke (event, ## __VA_ARGS__, DT_END) : 0)
140 #define INVOKE_GLOBAL(event, ...) INVOKE (&gbl_ev, EVENT_ ## GLOBAL ## _ ## event, ## __VA_ARGS__)
141 #define INVOKE_ATTACHABLE(event, obj, ...) INVOKE (obj , EVENT_ ## ATTACHABLE ## _ ## event, ## __VA_ARGS__)
142 #define INVOKE_OBJECT(event, obj, ...) INVOKE (obj , EVENT_ ## OBJECT ## _ ## event, ## __VA_ARGS__)
143 #define INVOKE_CLIENT(event, obj, ...) INVOKE (obj , EVENT_ ## CLIENT ## _ ## event, ## __VA_ARGS__)
144 #define INVOKE_PLAYER(event, obj, ...) INVOKE (obj , EVENT_ ## PLAYER ## _ ## event, ## __VA_ARGS__)
145 #define INVOKE_MAP(event, obj, ...) INVOKE (obj , EVENT_ ## MAP ## _ ## event, ## __VA_ARGS__)
146
147 //TODO should index into @result
148 #define RESULT(idx,type) cfperl_result_ ## type (idx)
149 #define RESULT_DOUBLE(idx) RESULT(idx, DOUBLE)
150 #define RESULT_INT(idx) RESULT(idx, INT)
151
152 double cfperl_result_DOUBLE (int idx);
153 int cfperl_result_INT (int idx);
154
155 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
156
157 INTERFACE_CLASS (attachable)
158 struct attachable
159 {
160 static MGVTBL vtbl;
161
162 static unordered_vector<attachable *> mortals;
163 MTH static void check_mortals ();
164
165 enum {
166 F_DESTROYED = 0x01,
167 F_DEBUG_TRACE = 0x02,
168 };
169
170 // object is delete'd after the refcount reaches 0
171 int ACC (RW, flags);
172 mutable int ACC (RW, refcnt);
173
174 MTH void refcnt_inc () const { ++refcnt; }
175 MTH void refcnt_dec () const { --refcnt; }
176
177 MTH int refcnt_cnt () const;
178 // check wether the object has died and destroy
179 MTH void refcnt_chk () { if (expect_false (refcnt <= 0)) do_check (); }
180
181 // destroy the object unless it was already destroyed
182 // this politely asks everybody interested the reduce
183 // the refcount to 0 as soon as possible.
184 MTH void destroy ();
185
186 // return wether an object was destroyed already
187 MTH bool destroyed () const { return flags & F_DESTROYED; }
188
189 virtual void gather_callbacks (AV *&callbacks, event_type event) const;
190
191 #if 0
192 private:
193 static refcounted *rc_first;
194 refcounted *rc_next;
195 #endif
196
197 HV *self; // CF+ perl self
198 AV *cb; // CF+ callbacks
199 shstr attach; // generic extension attachment information
200
201 void sever_self (); // sever this object from its self, if it has one.
202 void optimise (); // possibly save some memory by destroying unneeded data
203
204 attachable ()
205 : flags (0), refcnt (0), self (0), cb (0), attach (0)
206 {
207 }
208
209 attachable (const attachable &src)
210 : flags (0), refcnt (0), self (0), cb (0), attach (src.attach)
211 {
212 }
213
214 virtual ~attachable ();
215
216 attachable &operator =(const attachable &src);
217
218 // used to _quickly_ device wether to shortcut the evaluation
219 bool should_invoke (event_type event)
220 {
221 return ev_want_event [event] || cb;
222 }
223
224 bool invoke (event_type event, ...);
225
226 MTH void instantiate ();
227 void reattach ();
228
229 protected:
230 // do the real refcount checking work
231 void do_check ();
232
233 // the method that does the real destroy work
234 virtual void do_destroy ();
235 };
236
237 // the global object is a pseudo object that cares for the global events
238 struct global : attachable
239 {
240 void gather_callbacks (AV *&callbacks, event_type event) const;
241 };
242
243 extern struct global gbl_ev;
244
245 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
246
247 struct object_freezer : dynbuf_text
248 {
249 AV *av;
250
251 object_freezer ();
252 ~object_freezer ();
253
254 void put (attachable *ext);
255
256 // used only for user-defined key-value pairs
257 void put (const shstr &k, const shstr &v)
258 {
259 add (k);
260
261 if (expect_true (v))
262 add (' '), add (v);
263
264 add ('\n');
265 }
266
267 template<typename T>
268 void put_kw_string (keyword k, const T &v)
269 {
270 int klen = keyword_len [k];
271 int vlen = v ? strlen (v) + 1 : 0;
272
273 char *p = (char *)alloc (klen + vlen + 1);
274
275 memcpy (p, keyword_str [k], klen); p += klen;
276
277 if (expect_true (v))
278 {
279 *p++ = ' '; vlen--;
280 memcpy (p, v, vlen); p += vlen;
281 }
282
283 *p = '\n';
284 }
285
286 void put (keyword k, const char *v = 0)
287 {
288 put_kw_string (k, v);
289 }
290
291 void put (keyword k, const shstr &v)
292 {
293 put_kw_string (k, v);
294 }
295
296 void put (keyword k, double v)
297 {
298 force (MAX_KEYWORD_LEN + 2 + 32);
299 fadd (keyword_str [k], keyword_len [k]);
300 fadd (' ');
301 falloc (sprintf (ptr, "%.7g", v));
302 fadd ('\n');
303 }
304
305 void put_(keyword k, sint64 v)
306 {
307 force (MAX_KEYWORD_LEN + 2 + sint64_digits);
308 fadd (keyword_str [k], keyword_len [k]);
309 fadd (' ');
310 add (v);
311 fadd ('\n');
312 }
313
314 void put_(keyword k, sint32 v)
315 {
316 force (MAX_KEYWORD_LEN + 2 + sint32_digits);
317 fadd (keyword_str [k], keyword_len [k]);
318 fadd (' ');
319 add (v);
320 fadd ('\n');
321 }
322
323 void put (keyword k, float v) { put (k, (double)v); }
324 void put (keyword k, signed char v) { put_(k, (sint32)v); }
325 void put (keyword k, unsigned char v) { put_(k, (sint32)v); }
326 void put (keyword k, signed short v) { put_(k, (sint32)v); }
327 void put (keyword k, unsigned short v) { put_(k, (sint32)v); }
328 void put (keyword k, signed int v) { put_(k, (sint32)v); }
329 void put (keyword k, unsigned int v) { put_(k, (sint64)v); }
330 void put (keyword k, signed long v) { put_(k, (sint64)v); }
331 void put (keyword k, unsigned long v) { put_(k, (sint64)v); }
332 void put (keyword k, signed long long v) { put_(k, (sint64)v); }
333 void put (keyword k, unsigned long long v) { put_(k, (sint64)v); }
334
335 void put (keyword kbeg, keyword kend, const shstr &v)
336 {
337 force (MAX_KEYWORD_LEN + 1);
338 fadd (keyword_str [kbeg], keyword_len [kbeg]); fadd ('\n');
339
340 if (expect_true (v))
341 {
342 add (v);
343 add ('\n');
344 }
345
346 force (MAX_KEYWORD_LEN + 1);
347 fadd (keyword_str [kend], keyword_len [kend]); fadd ('\n');
348 }
349
350 void put (keyword k, archetype *v);
351 void put (keyword k, treasurelist *v);
352 void put (keyword k, faceinfo *v);
353
354 template<typename T>
355 void put (keyword k, const refptr<T> &v)
356 {
357 put (k, (T *)v);
358 }
359
360 bool save (const char *path);
361 char *as_string (); // like strdup
362
363 operator bool () { return !!av; }
364 };
365
366 struct object_thawer
367 {
368 char *line; // current beginning of line
369 SV *text; // text part
370 AV *av; // perl part
371 int linenum;
372 keyword kw;
373 char *kw_str; // the keyword parsed, as string
374 char *value; // the value, or 0 if no value
375 char *value_nn; // the value, or the empty string if no value
376 const char *name;
377
378 operator bool () { return !!text; }
379
380 object_thawer (const char *path = 0);
381 object_thawer (const char *data, AV *perlav);
382 ~object_thawer ();
383
384 void get (attachable *obj, int oid);
385
386 // parse next line
387 void next ();
388 // skip the current key-value (usually fetch next line, for
389 // multiline-fields, skips till the corresponding end-kw
390 void skip ();
391
392 char *get_str () { return value; } // may be 0
393 void get_ml (keyword kend, shstr &sh);
394
395 void get_ornull (shstr &sh) const { sh = value; }
396 void get (shstr &sh) const { sh = value; } // might want to check for non-null here
397
398 bool get_bool () const { return *value_nn == '1'; }
399 sint32 get_sint32 () const;
400 sint64 get_sint64 () const { return strtoll (value_nn, 0, 10); }
401 double get_double () const { return strtod (value_nn, 0); }
402
403 void get (float &v) { v = get_double (); }
404 void get (double &v) { v = get_double (); }
405
406 void get (bool &i) { i = get_bool (); }
407 void get (sint8 &i) { i = get_sint32 (); }
408 void get (uint8 &i) { i = get_sint32 (); }
409 void get (sint16 &i) { i = get_sint32 (); }
410 void get (uint16 &i) { i = get_sint32 (); }
411 void get (sint32 &i) { i = get_sint32 (); }
412
413 void get (uint32 &i) { i = get_sint64 (); }
414 void get (sint64 &i) { i = get_sint64 (); }
415
416 bool parse_error (const char *type = 0, const char *name = 0, bool skip = true);
417 };
418
419 //TODO: remove
420 char *fgets (char *s, int n, object_thawer &thawer);
421
422 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
423
424 struct coroapi {
425 static struct CoroAPI *GCoroAPI;
426
427 static int nready () { return CORO_NREADY; }
428 static int cede () { return CORO_CEDE ; }
429
430 static tstamp next_cede;
431 static int cede_counter;
432
433 static void do_cede_every ();
434 static void do_cede_to_tick ();
435 static void do_cede_to_tick_every ();
436
437 static void cede_every (int count)
438 {
439 if (expect_false (++cede_counter >= count))
440 do_cede_every ();
441 }
442
443 static bool cede_to_tick ()
444 {
445 if (expect_true (now () < next_cede))
446 return false;
447
448 do_cede_to_tick ();
449 return true;
450 }
451
452 static bool cede_to_tick_every (int count)
453 {
454 if (expect_true (++cede_counter < count))
455 return false;
456
457 return cede_to_tick ();
458 }
459
460 static void wait_for_tick ();
461 static void wait_for_tick_begin ();
462 };
463
464 struct watcher_base
465 {
466 static struct EventAPI *GEventAPI;
467 };
468
469 template<class base>
470 struct watcher : watcher_base
471 {
472 base *pe;
473
474 void start (bool repeat = false) { GEventAPI->start ((pe_watcher *)pe, repeat); }
475 void stop (bool cancel_events = false) { GEventAPI->stop ((pe_watcher *)pe, cancel_events); }
476 void now () { GEventAPI->now ((pe_watcher *)pe); }
477 void suspend () { GEventAPI->suspend ((pe_watcher *)pe); }
478 void resume () { GEventAPI->resume ((pe_watcher *)pe); }
479
480 void prio (int new_prio) { ((pe_watcher *)pe)->prio = new_prio; }
481
482 ~watcher ()
483 {
484 cancel ();
485 }
486
487 private:
488 void cancel () { GEventAPI->cancel ((pe_watcher *)pe); } // private
489 };
490
491 struct iw : watcher<pe_idle>, callback<void (iw &)>
492 {
493 template<class O, class M>
494 iw (O object, M method)
495 : callback<void (iw &)> (object, method)
496 {
497 alloc ();
498 }
499
500 private:
501 void alloc ();
502 };
503
504 struct iow : watcher<pe_io>, callback<void (iow &, int)>
505 {
506 template<class O, class M>
507 iow (O object, M method)
508 : callback<void (iow &, int)> (object, method)
509 {
510 alloc ();
511 }
512
513 void fd (int fd);
514 int poll ();
515 void poll (int events);
516
517 private:
518 void alloc ();
519 };
520
521 #endif
522