Freeciv-3.3
Loading...
Searching...
No Matches
luascript_signal.c
Go to the documentation of this file.
1/*****************************************************************************
2 Freeciv - Copyright (C) 2005 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12*****************************************************************************/
13
14/*****************************************************************************
15 Signals implementation.
16
17 New signal types can be declared with script_signal_create. Each
18 signal should have a unique name string.
19 All signal declarations are in signals_create, for convenience.
20
21 A signal may have any number of Lua callback functions connected to it
22 at any given time.
23
24 A signal emission invokes all associated callbacks in the order they were
25 connected:
26
27 * A callback can stop the current signal emission, preventing the callbacks
28 connected after it from being invoked.
29
30 * A callback can detach itself from its associated signal.
31
32 Lua callbacks functions are able to do these via their return values.
33
34 All Lua callback functions can return a value. Example:
35 return false
36
37 If the value is 'true' the current signal emission will be stopped.
38*****************************************************************************/
39
40#ifdef HAVE_CONFIG_H
41#include <fc_config.h>
42#endif
43
44#include <stdarg.h>
45
46/* utility */
47#include "deprecations.h"
48#include "log.h"
49
50/* common/scriptcore */
51#include "luascript.h"
52#include "luascript_types.h"
53
54#include "luascript_signal.h"
55
56struct signal;
57struct signal_callback;
58
59/* get 'struct signal_callback_list' and related functions: */
60#define SPECLIST_TAG signal_callback
61#define SPECLIST_TYPE struct signal_callback
62#include "speclist.h"
63
64#define signal_callback_list_iterate(list, pcallback) \
65 TYPED_LIST_ITERATE(struct signal_callback, list, pcallback)
66#define signal_callback_list_iterate_end \
67 LIST_ITERATE_END
68
69static struct signal_callback *signal_callback_new(const char *name);
71static struct signal *signal_new(int nargs, enum api_types *parg_types);
72static void signal_destroy(struct signal *psignal);
73
74/* Signal datastructure. */
75struct signal {
76 int nargs; /* Number of arguments to pass */
77 enum api_types *arg_types; /* Argument types */
78 struct signal_callback_list *callbacks; /* Connected callbacks */
80};
81
82/* Signal callback datastructure. */
84 char *name; /* callback function name */
85};
86
87/*****************************************************************************
88 Signal hash table.
89*****************************************************************************/
90#define SPECHASH_TAG luascript_signal
91#define SPECHASH_ASTR_KEY_TYPE
92#define SPECHASH_IDATA_TYPE struct signal *
93#define SPECHASH_IDATA_FREE signal_destroy
94#include "spechash.h"
95
96#define signal_hash_iterate(phash, key, data) \
97 TYPED_HASH_ITERATE(char *, struct signal *, phash, key, data)
98#define signal_hash_iterate_end \
99 HASH_ITERATE_END
100
101/* get 'struct luascript_signal_name_list' and related functions: */
102#define SPECLIST_TAG luascript_signal_name
103#define SPECLIST_TYPE char
104#include "speclist.h"
105
106#define luascript_signal_name_list_iterate(list, pname) \
107 TYPED_LIST_ITERATE(struct signal_callback, list, pcallback)
108#define luascript_signal_name_list_iterate_end \
109 LIST_ITERATE_END
110
111/**********************************************************************/
114static struct signal_callback *signal_callback_new(const char *name)
115{
116 struct signal_callback *pcallback = fc_malloc(sizeof(*pcallback));
117
118 pcallback->name = fc_strdup(name);
119 return pcallback;
120}
121
122/**********************************************************************/
126{
127 free(pcallback->name);
129}
130
131/**********************************************************************/
134static struct signal *signal_new(int nargs, enum api_types *parg_types)
135{
136 struct signal *psignal = fc_malloc(sizeof(*psignal));
137
138 psignal->nargs = nargs;
139 psignal->arg_types = parg_types;
140 psignal->callbacks
142 psignal->deprecator.depr_msg = NULL;
143 psignal->deprecator.retired = NULL;
144
145 return psignal;
146}
147
148/**********************************************************************/
151static void signal_destroy(struct signal *psignal)
152{
153 if (psignal->arg_types) {
154 free(psignal->arg_types);
155 }
156 if (psignal->deprecator.depr_msg) {
157 free(psignal->deprecator.depr_msg);
158 }
159 if (psignal->deprecator.retired) {
160 free(psignal->deprecator.retired);
161 }
163 free(psignal);
164}
165
166/**********************************************************************/
170 const char *signal_name,
171 va_list args)
172{
173 struct signal *psignal;
174
176 fc_assert_ret(fcl->signals);
177
181
182 va_copy(args_cb, args);
184 psignal->arg_types, args_cb)) {
186 break;
187 }
190 } else {
191 luascript_log(fcl, LOG_ERROR, "Signal \"%s\" does not exist, so cannot "
192 "be invoked.", signal_name);
193 }
194}
195
196/**********************************************************************/
200 const char *signal_name, ...)
201{
202 va_list args;
203
204 va_start(args, signal_name);
206 va_end(args);
207}
208
209/**********************************************************************/
213 const char *signal_name,
214 int nargs, va_list args)
215{
216 struct signal *psignal;
217
219 fc_assert_ret_val(fcl->signals, NULL);
220
222 luascript_log(fcl, LOG_ERROR, "Signal \"%s\" was already created.",
224 return NULL;
225 } else {
226 enum api_types *parg_types;
227 char *sn = fc_malloc(strlen(signal_name) + 1);
228 struct signal *created;
229
230 if (nargs > 0) {
231 int i;
232
234
235 for (i = 0; i < nargs; i++) {
236 *(parg_types + i) = va_arg(args, int);
237 }
238 } else {
240 }
241
244 created);
247
248 return created;
249 }
250}
251
252/**********************************************************************/
256 const char *signal_name,
257 int nargs, ...)
258{
259 va_list args;
260 struct signal *created;
261
262 va_start(args, nargs);
264 va_end(args);
265
266 if (created != NULL) {
267 return &(created->deprecator);
268 }
269
270 return NULL;
271}
272
273/**********************************************************************/
277 char *replacement, char *deprecated_since,
278 char *retired_since)
279{
280 if (deprecator != NULL) {
281 char buffer[1024];
282 char *deprtype = ((retired_since != NULL) ? "Retired:" : "Deprecated:");
283
284 if (deprecated_since != NULL && replacement != NULL) {
285 if (retired_since != NULL) {
286 fc_snprintf(buffer, sizeof(buffer),
287 "%s lua signal \"%s\", retired since \"%s\", "
288 "and deprecated already since \"%s\", used. "
289 "Use \"%s\" instead",
291 } else {
292 fc_snprintf(buffer, sizeof(buffer),
293 "%s lua signal \"%s\", deprecated since \"%s\", used. "
294 "Use \"%s\" instead",
296 }
297 } else if (replacement != NULL) {
298 fc_snprintf(buffer, sizeof(buffer),
299 "%s lua signal \"%s\" used. Use \"%s\" instead",
301 } else {
302 fc_snprintf(buffer, sizeof(buffer),
303 "%s lua signal \"%s\" used.", deprtype, signal_name);
304 }
305
306 deprecator->depr_msg = fc_strdup(buffer);
307
308 if (retired_since != NULL) {
310 }
311 }
312}
313
314/**********************************************************************/
318 const char *callback_name, bool create)
319{
320 struct signal *psignal;
322
324 fc_assert_ret(fcl->signals != NULL);
325
327
328 if (psignal->deprecator.depr_msg != NULL) {
329 log_deprecation("%s", psignal->deprecator.depr_msg);
330 }
331
332 if (psignal->deprecator.retired != NULL) {
333 luascript_error(fcl->state, "Signal \"%s\" has been retired.",
335 return;
336 }
337
338 /* Check for a duplicate callback */
340 if (!strcmp(pcallback->name, callback_name)) {
342 break;
343 }
345
346 if (create) {
347 if (pcallback_found) {
348 luascript_error(fcl->state, "Signal \"%s\" already has a callback "
349 "called \"%s\".", signal_name,
351 } else {
354 }
355 } else {
356 if (pcallback_found) {
358 }
359 }
360 } else {
361 luascript_error(fcl->state, "Signal \"%s\" does not exist.",
363 }
364}
365
366/**********************************************************************/
370 const char *signal_name,
371 const char *callback_name)
372{
373 struct signal *psignal;
374
376 fc_assert_ret_val(fcl->signals != NULL, FALSE);
377
379 /* check for a duplicate callback */
381 if (!strcmp(pcallback->name, callback_name)) {
382 return TRUE;
383 }
385 }
386
387 return FALSE;
388}
389
390/**********************************************************************/
394static void sn_free(char *name)
395{
396 FC_FREE(name);
397}
398
399/**********************************************************************/
403{
405
406 if (NULL == fcl->signals) {
407 fcl->signals = luascript_signal_hash_new();
409 }
410}
411
412/**********************************************************************/
416{
417 if (NULL != fcl && NULL != fcl->signals) {
419
421
422 fcl->signals = NULL;
423 }
424}
425
426/**********************************************************************/
430{
432 fc_assert_ret_val(fcl->signal_names != NULL, NULL);
433
434 return luascript_signal_name_list_get(fcl->signal_names, sindex);
435}
436
437/**********************************************************************/
442 const char *signal_name,
443 int sindex)
444{
445 struct signal *psignal;
446
448 fc_assert_ret_val(fcl->signals != NULL, NULL);
449
453 if (pcallback) {
454 return pcallback->name;
455 }
456 }
457
458 return NULL;
459}
char * incite_cost
Definition comments.c:76
#define log_deprecation(message,...)
const char * name
Definition inputfile.c:127
#define fc_assert_ret(condition)
Definition log.h:192
#define fc_assert_ret_val(condition, val)
Definition log.h:195
@ LOG_ERROR
Definition log.h:31
bool luascript_callback_invoke(struct fc_lua *fcl, const char *callback_name, int nargs, enum api_types *parg_types, va_list args)
Definition luascript.c:657
int luascript_error(lua_State *L, const char *format,...)
Definition luascript.c:291
void luascript_log(struct fc_lua *fcl, enum log_level level, const char *format,...)
Definition luascript.c:409
void luascript_signal_free(struct fc_lua *fcl)
void luascript_signal_init(struct fc_lua *fcl)
static void signal_destroy(struct signal *psignal)
bool luascript_signal_callback_defined(struct fc_lua *fcl, const char *signal_name, const char *callback_name)
void deprecate_signal(struct signal_deprecator *deprecator, char *signal_name, char *replacement, char *deprecated_since, char *retired_since)
struct signal_deprecator * luascript_signal_create(struct fc_lua *fcl, const char *signal_name, int nargs,...)
void luascript_signal_emit_valist(struct fc_lua *fcl, const char *signal_name, va_list args)
static struct signal * luascript_signal_create_valist(struct fc_lua *fcl, const char *signal_name, int nargs, va_list args)
const char * luascript_signal_by_index(struct fc_lua *fcl, int sindex)
#define signal_callback_list_iterate(list, pcallback)
static struct signal_callback * signal_callback_new(const char *name)
static void signal_callback_destroy(struct signal_callback *pcallback)
const char * luascript_signal_callback_by_index(struct fc_lua *fcl, const char *signal_name, int sindex)
void luascript_signal_emit(struct fc_lua *fcl, const char *signal_name,...)
#define signal_callback_list_iterate_end
void luascript_signal_callback(struct fc_lua *fcl, const char *signal_name, const char *callback_name, bool create)
static void sn_free(char *name)
static struct signal * signal_new(int nargs, enum api_types *parg_types)
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_strdup(str)
Definition mem.h:43
#define fc_malloc(sz)
Definition mem.h:34
struct signal_callback_list * callbacks
enum api_types * arg_types
struct signal_deprecator deprecator
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47