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

# User Rev Content
1 root 1.74 /*
2 root 1.81 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 root 1.74 *
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 root 1.81 * 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 root 1.74 *
13 root 1.81 * 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 root 1.74 *
18 root 1.81 * 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 root 1.74 *
21     * The authors can be reached via e-mail to <crossfire@schmorp.de>
22     */
23    
24 root 1.1 //
25     // cfperl.h perl interface
26     //
27 root 1.2 #ifndef CFPERL_H__
28     #define CFPERL_H__
29    
30 root 1.64 #include <cstdarg>
31 root 1.16 #include <cstdio>
32 root 1.64 #include <bitset>
33 root 1.16
34     using namespace std;
35    
36     #include <EXTERN.h>
37     #include <perl.h>
38 root 1.20 #include <XSUB.h>
39 root 1.16
40 root 1.36 #include <EventAPI.h>
41 root 1.42 #include <CoroAPI.h>
42 root 1.36
43 root 1.42 #include "util.h"
44     #include "keyword.h"
45     #include "dynbuf.h"
46 root 1.36 #include "callback.h"
47    
48 root 1.42 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
49    
50 root 1.16 // 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 root 1.39 // same here, massive symbol spamming
62     #undef do_open
63     #undef do_close
64 root 1.42 #undef ref
65 root 1.44 #undef seed
66 root 1.39
67 root 1.16 // 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 root 1.42 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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 root 1.7 void cfperl_init ();
89     void cfperl_main ();
90 root 1.50 void cfperl_emergency_save ();
91 root 1.55 void cfperl_cleanup (int make_core);
92 root 1.65 void cfperl_make_book (object *book, int level);
93 root 1.80 void cfperl_send_msg (client *ns, int color, const char *type, const char *msg);
94 root 1.7
95 root 1.42 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
96    
97 root 1.79 extern tstamp runtime; // virtual server time, excluding time jumps and lag
98     extern tstamp NOW; // real time of current server tick
99 root 1.42
100 root 1.6 enum event_klass
101     {
102 root 1.11 KLASS_NONE,
103 root 1.3 KLASS_GLOBAL,
104 root 1.41 KLASS_ATTACHABLE,
105 root 1.40 KLASS_CLIENT,
106 root 1.3 KLASS_PLAYER,
107     KLASS_OBJECT,
108     KLASS_MAP,
109 root 1.33 KLASS_COMMAND,
110 root 1.3 };
111    
112 root 1.6 enum event_type
113     {
114 root 1.7 # define def(klass,name) EVENT_ ## klass ## _ ## name,
115 root 1.2 # include "eventinc.h"
116     # undef def
117 root 1.4 NUM_EVENT_TYPES
118 root 1.2 };
119    
120 root 1.64 // 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 root 1.41 #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 root 1.3
138     // the ", ## __VA_ARGS" is, unfortunately, a gnu-cpp extension
139 root 1.66 #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 root 1.3
147 root 1.7 //TODO should index into @result
148     #define RESULT(idx,type) cfperl_result_ ## type (idx)
149 root 1.33 #define RESULT_DOUBLE(idx) RESULT(idx, DOUBLE)
150     #define RESULT_INT(idx) RESULT(idx, INT)
151 root 1.7
152 root 1.34 double cfperl_result_DOUBLE (int idx);
153     int cfperl_result_INT (int idx);
154 root 1.7
155 root 1.42 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
156    
157 root 1.47 INTERFACE_CLASS (attachable)
158 root 1.41 struct attachable
159 root 1.6 {
160 root 1.42 static MGVTBL vtbl;
161    
162 root 1.41 static unordered_vector<attachable *> mortals;
163 root 1.47 MTH static void check_mortals ();
164 root 1.41
165     enum {
166 root 1.54 F_DESTROYED = 0x01,
167     F_DEBUG_TRACE = 0x02,
168 root 1.41 };
169    
170     // object is delete'd after the refcount reaches 0
171 pippijn 1.58 int ACC (RW, flags);
172 root 1.47 mutable int ACC (RW, refcnt);
173 root 1.41
174 root 1.47 MTH void refcnt_inc () const { ++refcnt; }
175     MTH void refcnt_dec () const { --refcnt; }
176 root 1.41
177 root 1.49 MTH int refcnt_cnt () const;
178 root 1.41 // check wether the object has died and destroy
179 root 1.75 MTH void refcnt_chk () { if (expect_false (refcnt <= 0)) do_check (); }
180 root 1.41
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 root 1.47 MTH void destroy ();
185 root 1.41
186     // return wether an object was destroyed already
187 root 1.47 MTH bool destroyed () const { return flags & F_DESTROYED; }
188 root 1.41
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 root 1.35 AV *cb; // CF+ callbacks
199 root 1.21 shstr attach; // generic extension attachment information
200 root 1.6
201 root 1.52 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 root 1.8
204 root 1.41 attachable ()
205     : flags (0), refcnt (0), self (0), cb (0), attach (0)
206 root 1.8 {
207     }
208 root 1.22
209 root 1.41 attachable (const attachable &src)
210     : flags (0), refcnt (0), self (0), cb (0), attach (src.attach)
211 root 1.22 {
212     }
213    
214 root 1.41 virtual ~attachable ();
215    
216     attachable &operator =(const attachable &src);
217    
218 root 1.66 // used to _quickly_ device wether to shortcut the evaluation
219     bool should_invoke (event_type event)
220 root 1.64 {
221 root 1.66 return ev_want_event [event] || cb;
222 root 1.64 }
223    
224 root 1.66 bool invoke (event_type event, ...);
225    
226 root 1.48 MTH void instantiate ();
227 root 1.41 void reattach ();
228 root 1.24
229 root 1.41 protected:
230     // do the real refcount checking work
231     void do_check ();
232 root 1.25
233 root 1.41 // the method that does the real destroy work
234     virtual void do_destroy ();
235 root 1.6 };
236    
237 root 1.41 // the global object is a pseudo object that cares for the global events
238     struct global : attachable
239 root 1.6 {
240 root 1.41 void gather_callbacks (AV *&callbacks, event_type event) const;
241 root 1.6 };
242    
243 root 1.41 extern struct global gbl_ev;
244    
245 root 1.42 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
246    
247 root 1.63 struct object_freezer : dynbuf_text
248 root 1.7 {
249 root 1.17 AV *av;
250 root 1.12
251 root 1.17 object_freezer ();
252 root 1.8 ~object_freezer ();
253    
254 root 1.41 void put (attachable *ext);
255 root 1.15
256 root 1.29 // used only for user-defined key-value pairs
257     void put (const shstr &k, const shstr &v)
258 root 1.20 {
259     add (k);
260    
261 root 1.66 if (expect_true (v))
262 root 1.22 add (' '), add (v);
263 root 1.20
264     add ('\n');
265     }
266    
267 root 1.29 template<typename T>
268 root 1.78 void put_kw_string (keyword k, const T &v)
269 root 1.20 {
270     int klen = keyword_len [k];
271 root 1.22 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 root 1.66 if (expect_true (v))
278 root 1.22 {
279 root 1.29 *p++ = ' '; vlen--;
280 root 1.22 memcpy (p, v, vlen); p += vlen;
281     }
282    
283     *p = '\n';
284     }
285    
286 root 1.45 void put (keyword k, const char *v = 0)
287 root 1.29 {
288 root 1.78 put_kw_string (k, v);
289 root 1.29 }
290    
291 root 1.22 void put (keyword k, const shstr &v)
292     {
293 root 1.78 put_kw_string (k, v);
294 root 1.20 }
295 root 1.19
296 root 1.20 void put (keyword k, double v)
297     {
298 root 1.69 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 root 1.20 }
304    
305     void put_(keyword k, sint64 v)
306     {
307 root 1.69 force (MAX_KEYWORD_LEN + 2 + sint64_digits);
308     fadd (keyword_str [k], keyword_len [k]);
309     fadd (' ');
310 root 1.20 add (v);
311 root 1.69 fadd ('\n');
312 root 1.20 }
313    
314     void put_(keyword k, sint32 v)
315     {
316 root 1.69 force (MAX_KEYWORD_LEN + 2 + sint32_digits);
317     fadd (keyword_str [k], keyword_len [k]);
318     fadd (' ');
319 root 1.20 add (v);
320 root 1.69 fadd ('\n');
321 root 1.20 }
322    
323 root 1.72 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 root 1.23 void put (keyword kbeg, keyword kend, const shstr &v)
336 root 1.20 {
337 root 1.69 force (MAX_KEYWORD_LEN + 1);
338     fadd (keyword_str [kbeg], keyword_len [kbeg]); fadd ('\n');
339 root 1.20
340 root 1.66 if (expect_true (v))
341 root 1.20 {
342     add (v);
343     add ('\n');
344     }
345    
346 root 1.69 force (MAX_KEYWORD_LEN + 1);
347     fadd (keyword_str [kend], keyword_len [kend]); fadd ('\n');
348 root 1.20 }
349    
350 root 1.78 void put (keyword k, archetype *v);
351     void put (keyword k, treasurelist *v);
352     void put (keyword k, faceinfo *v);
353 root 1.18
354 root 1.32 template<typename T>
355     void put (keyword k, const refptr<T> &v)
356     {
357     put (k, (T *)v);
358     }
359    
360 root 1.47 bool save (const char *path);
361 root 1.31 char *as_string (); // like strdup
362 root 1.17
363 root 1.16 operator bool () { return !!av; }
364 root 1.7 };
365    
366 root 1.17 struct object_thawer
367 root 1.7 {
368 root 1.66 char *line; // current beginning of line
369 root 1.21 SV *text; // text part
370     AV *av; // perl part
371 root 1.53 int linenum;
372 root 1.56 keyword kw;
373 root 1.66 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 root 1.47 const char *name;
377 root 1.21
378     operator bool () { return !!text; }
379 root 1.16
380 root 1.47 object_thawer (const char *path = 0);
381 root 1.30 object_thawer (const char *data, AV *perlav);
382 root 1.8 ~object_thawer ();
383    
384 root 1.41 void get (attachable *obj, int oid);
385 root 1.15
386 root 1.56 // parse next line
387 root 1.57 void next ();
388     // skip the current key-value (usually fetch next line, for
389 root 1.73 // multiline-fields, skips till the corresponding end-kw
390 root 1.57 void skip ();
391    
392     char *get_str () { return value; } // may be 0
393 root 1.66 void get_ml (keyword kend, shstr &sh);
394 root 1.17
395 root 1.56 void get_ornull (shstr &sh) const { sh = value; }
396 root 1.66 void get (shstr &sh) const { sh = value; } // might want to check for non-null here
397 root 1.21
398 root 1.66 bool get_bool () const { return *value_nn == '1'; }
399 root 1.21 sint32 get_sint32 () const;
400 root 1.71 sint64 get_sint64 () const { return strtoll (value_nn, 0, 10); }
401     double get_double () const { return strtod (value_nn, 0); }
402 root 1.21
403 root 1.42 void get (float &v) { v = get_double (); }
404 root 1.21 void get (double &v) { v = get_double (); }
405    
406 root 1.66 void get (bool &i) { i = get_bool (); }
407 root 1.21 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 root 1.53
416 root 1.56 bool parse_error (const char *type = 0, const char *name = 0, bool skip = true);
417 root 1.7 };
418 root 1.2
419 root 1.53 //TODO: remove
420 root 1.21 char *fgets (char *s, int n, object_thawer &thawer);
421    
422 root 1.42 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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 root 1.46
430 root 1.79 static tstamp next_cede;
431 root 1.46 static int cede_counter;
432    
433 root 1.62 static void do_cede_every ();
434     static void do_cede_to_tick ();
435     static void do_cede_to_tick_every ();
436    
437 root 1.46 static void cede_every (int count)
438     {
439 root 1.66 if (expect_false (++cede_counter >= count))
440 root 1.62 do_cede_every ();
441     }
442 root 1.46
443 root 1.77 static bool cede_to_tick ()
444 root 1.62 {
445 root 1.79 if (expect_true (now () < next_cede))
446 root 1.77 return false;
447    
448     do_cede_to_tick ();
449     return true;
450 root 1.62 }
451    
452 root 1.77 static bool cede_to_tick_every (int count)
453 root 1.62 {
454 root 1.77 if (expect_true (++cede_counter < count))
455     return false;
456    
457     return cede_to_tick ();
458 root 1.46 }
459 root 1.61
460     static void wait_for_tick ();
461     static void wait_for_tick_begin ();
462 root 1.42 };
463    
464 root 1.36 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 root 1.38 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 root 1.36 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 root 1.38 void fd (int fd);
514 root 1.36 int poll ();
515 root 1.38 void poll (int events);
516 root 1.36
517     private:
518     void alloc ();
519     };
520    
521 root 1.2 #endif
522 root 1.3