1 /**
2  * @file signals.c Signal API
3  * @ingroup core
4  */
5 
6 /* purple
7  *
8  * Purple is the legal property of its developers, whose names are too numerous
9  * to list here.  Please refer to the COPYRIGHT file distributed with this
10  * source distribution.
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
25  */
26 #include "internal.h"
27 
28 #include "dbus-maybe.h"
29 #include "debug.h"
30 #include "glibcompat.h"
31 #include "signals.h"
32 #include "value.h"
33 
34 /* must include this to use G_VA_COPY */
35 #include <string.h>
36 
37 typedef struct
38 {
39 	void *instance;
40 
41 	GHashTable *signals;
42 	size_t signal_count;
43 
44 	gulong next_signal_id;
45 
46 } PurpleInstanceData;
47 
48 typedef struct
49 {
50 	gulong id;
51 
52 	PurpleSignalMarshalFunc marshal;
53 
54 	int num_values;
55 	PurpleValue **values;
56 	PurpleValue *ret_value;
57 
58 	GList *handlers;
59 	size_t handler_count;
60 
61 	gulong next_handler_id;
62 } PurpleSignalData;
63 
64 typedef struct
65 {
66 	gulong id;
67 	PurpleCallback cb;
68 	void *handle;
69 	void *data;
70 	gboolean use_vargs;
71 	int priority;
72 
73 } PurpleSignalHandlerData;
74 
75 static GHashTable *instance_table = NULL;
76 
77 static void
destroy_instance_data(PurpleInstanceData * instance_data)78 destroy_instance_data(PurpleInstanceData *instance_data)
79 {
80 	g_hash_table_destroy(instance_data->signals);
81 
82 	g_free(instance_data);
83 }
84 
85 static void
destroy_signal_data(PurpleSignalData * signal_data)86 destroy_signal_data(PurpleSignalData *signal_data)
87 {
88 	g_list_free_full(signal_data->handlers, (GDestroyNotify)g_free);
89 
90 	if (signal_data->values != NULL)
91 	{
92 		int i;
93 
94 		for (i = 0; i < signal_data->num_values; i++)
95 			purple_value_destroy((PurpleValue *)signal_data->values[i]);
96 
97 		g_free(signal_data->values);
98 	}
99 
100 	if (signal_data->ret_value != NULL)
101 		purple_value_destroy(signal_data->ret_value);
102 	g_free(signal_data);
103 }
104 
105 gulong
purple_signal_register(void * instance,const char * signal,PurpleSignalMarshalFunc marshal,PurpleValue * ret_value,int num_values,...)106 purple_signal_register(void *instance, const char *signal,
107 					 PurpleSignalMarshalFunc marshal,
108 					 PurpleValue *ret_value, int num_values, ...)
109 {
110 	PurpleInstanceData *instance_data;
111 	PurpleSignalData *signal_data;
112 	va_list args;
113 
114 	g_return_val_if_fail(instance != NULL, 0);
115 	g_return_val_if_fail(signal   != NULL, 0);
116 	g_return_val_if_fail(marshal  != NULL, 0);
117 
118 	instance_data =
119 		(PurpleInstanceData *)g_hash_table_lookup(instance_table, instance);
120 
121 	if (instance_data == NULL)
122 	{
123 		instance_data = g_new0(PurpleInstanceData, 1);
124 
125 		instance_data->instance = instance;
126 		instance_data->next_signal_id = 1;
127 
128 		instance_data->signals =
129 			g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
130 								  (GDestroyNotify)destroy_signal_data);
131 
132 		g_hash_table_insert(instance_table, instance, instance_data);
133 	}
134 
135 	signal_data = g_new0(PurpleSignalData, 1);
136 	signal_data->id              = instance_data->next_signal_id;
137 	signal_data->marshal         = marshal;
138 	signal_data->next_handler_id = 1;
139 	signal_data->ret_value       = ret_value;
140 	signal_data->num_values      = num_values;
141 
142 	if (num_values > 0)
143 	{
144 		int i;
145 
146 		signal_data->values = g_new0(PurpleValue *, num_values);
147 
148 		va_start(args, num_values);
149 
150 		for (i = 0; i < num_values; i++)
151 			signal_data->values[i] = va_arg(args, PurpleValue *);
152 
153 		va_end(args);
154 	}
155 
156 	g_hash_table_insert(instance_data->signals,
157 						g_strdup(signal), signal_data);
158 
159 	instance_data->next_signal_id++;
160 	instance_data->signal_count++;
161 
162 	return signal_data->id;
163 }
164 
165 void
purple_signal_unregister(void * instance,const char * signal)166 purple_signal_unregister(void *instance, const char *signal)
167 {
168 	PurpleInstanceData *instance_data;
169 
170 	g_return_if_fail(instance != NULL);
171 	g_return_if_fail(signal   != NULL);
172 
173 	instance_data =
174 		(PurpleInstanceData *)g_hash_table_lookup(instance_table, instance);
175 
176 	g_return_if_fail(instance_data != NULL);
177 
178 	g_hash_table_remove(instance_data->signals, signal);
179 
180 	instance_data->signal_count--;
181 
182 	if (instance_data->signal_count == 0)
183 	{
184 		/* Unregister the instance. */
185 		g_hash_table_remove(instance_table, instance);
186 	}
187 }
188 
189 void
purple_signals_unregister_by_instance(void * instance)190 purple_signals_unregister_by_instance(void *instance)
191 {
192 	gboolean found;
193 
194 	g_return_if_fail(instance != NULL);
195 
196 	found = g_hash_table_remove(instance_table, instance);
197 
198 	/*
199 	 * Makes things easier (more annoying?) for developers who don't have
200 	 * things registering and unregistering in the right order :)
201 	 */
202 	g_return_if_fail(found);
203 }
204 
205 void
purple_signal_get_values(void * instance,const char * signal,PurpleValue ** ret_value,int * num_values,PurpleValue *** values)206 purple_signal_get_values(void *instance, const char *signal,
207 					   PurpleValue **ret_value,
208 					   int *num_values, PurpleValue ***values)
209 {
210 	PurpleInstanceData *instance_data;
211 	PurpleSignalData *signal_data;
212 
213 	g_return_if_fail(instance   != NULL);
214 	g_return_if_fail(signal     != NULL);
215 	g_return_if_fail(num_values != NULL);
216 	g_return_if_fail(values     != NULL);
217 
218 	/* Get the instance data */
219 	instance_data =
220 		(PurpleInstanceData *)g_hash_table_lookup(instance_table, instance);
221 
222 	g_return_if_fail(instance_data != NULL);
223 
224 	/* Get the signal data */
225 	signal_data =
226 		(PurpleSignalData *)g_hash_table_lookup(instance_data->signals, signal);
227 
228 	g_return_if_fail(signal_data != NULL);
229 
230 	*num_values = signal_data->num_values;
231 	*values     = signal_data->values;
232 
233 	if (ret_value != NULL)
234 		*ret_value = signal_data->ret_value;
235 }
236 
handler_priority(void * a,void * b)237 static gint handler_priority(void * a, void * b) {
238 	PurpleSignalHandlerData *ah = (PurpleSignalHandlerData*)a;
239 	PurpleSignalHandlerData *bh = (PurpleSignalHandlerData*)b;
240 	if (ah->priority > bh->priority) return 1;
241 	if (ah->priority < bh->priority) return -1;
242 	return 0;
243 }
244 
245 static gulong
signal_connect_common(void * instance,const char * signal,void * handle,PurpleCallback func,void * data,int priority,gboolean use_vargs)246 signal_connect_common(void *instance, const char *signal, void *handle,
247 					  PurpleCallback func, void *data, int priority, gboolean use_vargs)
248 {
249 	PurpleInstanceData *instance_data;
250 	PurpleSignalData *signal_data;
251 	PurpleSignalHandlerData *handler_data;
252 
253 	g_return_val_if_fail(instance != NULL, 0);
254 	g_return_val_if_fail(signal   != NULL, 0);
255 	g_return_val_if_fail(handle   != NULL, 0);
256 	g_return_val_if_fail(func     != NULL, 0);
257 
258 	/* Get the instance data */
259 	instance_data =
260 		(PurpleInstanceData *)g_hash_table_lookup(instance_table, instance);
261 
262 	if (instance_data == NULL)
263 	{
264 		purple_debug_warning("signals", "Something tried to register a callback "
265 				"for the '%s' signal, but we do not have any signals "
266 				"registered with the given handle\n", signal);
267 		g_return_val_if_reached(0);
268 	}
269 
270 	/* Get the signal data */
271 	signal_data =
272 		(PurpleSignalData *)g_hash_table_lookup(instance_data->signals, signal);
273 
274 	if (signal_data == NULL)
275 	{
276 		purple_debug(PURPLE_DEBUG_ERROR, "signals",
277 				   "Signal data for %s not found!\n", signal);
278 		return 0;
279 	}
280 
281 	/* Create the signal handler data */
282 	handler_data = g_new0(PurpleSignalHandlerData, 1);
283 	handler_data->id        = signal_data->next_handler_id;
284 	handler_data->cb        = func;
285 	handler_data->handle    = handle;
286 	handler_data->data      = data;
287 	handler_data->use_vargs = use_vargs;
288 	handler_data->priority = priority;
289 
290 	signal_data->handlers = g_list_insert_sorted(signal_data->handlers, handler_data, (GCompareFunc)handler_priority);
291 	signal_data->handler_count++;
292 	signal_data->next_handler_id++;
293 
294 	return handler_data->id;
295 }
296 
297 gulong
purple_signal_connect_priority(void * instance,const char * signal,void * handle,PurpleCallback func,void * data,int priority)298 purple_signal_connect_priority(void *instance, const char *signal, void *handle,
299 					PurpleCallback func, void *data, int priority)
300 {
301 	return signal_connect_common(instance, signal, handle, func, data, priority, FALSE);
302 }
303 
304 gulong
purple_signal_connect(void * instance,const char * signal,void * handle,PurpleCallback func,void * data)305 purple_signal_connect(void *instance, const char *signal, void *handle,
306 					PurpleCallback func, void *data)
307 {
308 	return signal_connect_common(instance, signal, handle, func, data, PURPLE_SIGNAL_PRIORITY_DEFAULT, FALSE);
309 }
310 
311 gulong
purple_signal_connect_priority_vargs(void * instance,const char * signal,void * handle,PurpleCallback func,void * data,int priority)312 purple_signal_connect_priority_vargs(void *instance, const char *signal, void *handle,
313 						  PurpleCallback func, void *data, int priority)
314 {
315 	return signal_connect_common(instance, signal, handle, func, data, priority, TRUE);
316 }
317 
318 gulong
purple_signal_connect_vargs(void * instance,const char * signal,void * handle,PurpleCallback func,void * data)319 purple_signal_connect_vargs(void *instance, const char *signal, void *handle,
320 						  PurpleCallback func, void *data)
321 {
322 	return signal_connect_common(instance, signal, handle, func, data, PURPLE_SIGNAL_PRIORITY_DEFAULT, TRUE);
323 }
324 
325 void
purple_signal_disconnect(void * instance,const char * signal,void * handle,PurpleCallback func)326 purple_signal_disconnect(void *instance, const char *signal,
327 					   void *handle, PurpleCallback func)
328 {
329 	PurpleInstanceData *instance_data;
330 	PurpleSignalData *signal_data;
331 	PurpleSignalHandlerData *handler_data;
332 	GList *l;
333 	gboolean found = FALSE;
334 
335 	g_return_if_fail(instance != NULL);
336 	g_return_if_fail(signal   != NULL);
337 	g_return_if_fail(handle   != NULL);
338 	g_return_if_fail(func     != NULL);
339 
340 	/* Get the instance data */
341 	instance_data =
342 		(PurpleInstanceData *)g_hash_table_lookup(instance_table, instance);
343 
344 	g_return_if_fail(instance_data != NULL);
345 
346 	/* Get the signal data */
347 	signal_data =
348 		(PurpleSignalData *)g_hash_table_lookup(instance_data->signals, signal);
349 
350 	if (signal_data == NULL)
351 	{
352 		purple_debug(PURPLE_DEBUG_ERROR, "signals",
353 				   "Signal data for %s not found!\n", signal);
354 		return;
355 	}
356 
357 	/* Find the handler data. */
358 	for (l = signal_data->handlers; l != NULL; l = l->next)
359 	{
360 		handler_data = (PurpleSignalHandlerData *)l->data;
361 
362 		if (handler_data->handle == handle && handler_data->cb == func)
363 		{
364 			g_free(handler_data);
365 
366 			signal_data->handlers = g_list_delete_link(signal_data->handlers,
367 												       l);
368 			signal_data->handler_count--;
369 
370 			found = TRUE;
371 
372 			break;
373 		}
374 	}
375 
376 	/* See note somewhere about this actually helping developers.. */
377 	g_return_if_fail(found);
378 }
379 
380 /*
381  * TODO: Make this all more efficient by storing a list of handlers, keyed
382  *       to a handle.
383  */
384 static void
disconnect_handle_from_signals(const char * signal,PurpleSignalData * signal_data,void * handle)385 disconnect_handle_from_signals(const char *signal,
386 							   PurpleSignalData *signal_data, void *handle)
387 {
388 	GList *l, *l_next;
389 	PurpleSignalHandlerData *handler_data;
390 
391 	for (l = signal_data->handlers; l != NULL; l = l_next)
392 	{
393 		handler_data = (PurpleSignalHandlerData *)l->data;
394 		l_next = l->next;
395 
396 		if (handler_data->handle == handle)
397 		{
398 			g_free(handler_data);
399 
400 			signal_data->handler_count--;
401 			signal_data->handlers = g_list_delete_link(signal_data->handlers,
402 			                                           l);
403 		}
404 	}
405 }
406 
407 static void
disconnect_handle_from_instance(void * instance,PurpleInstanceData * instance_data,void * handle)408 disconnect_handle_from_instance(void *instance,
409 								PurpleInstanceData *instance_data,
410 								void *handle)
411 {
412 	g_hash_table_foreach(instance_data->signals,
413 						 (GHFunc)disconnect_handle_from_signals, handle);
414 }
415 
416 void
purple_signals_disconnect_by_handle(void * handle)417 purple_signals_disconnect_by_handle(void *handle)
418 {
419 	g_return_if_fail(handle != NULL);
420 
421 	g_hash_table_foreach(instance_table,
422 						 (GHFunc)disconnect_handle_from_instance, handle);
423 }
424 
425 void
purple_signal_emit(void * instance,const char * signal,...)426 purple_signal_emit(void *instance, const char *signal, ...)
427 {
428 	va_list args;
429 
430 	g_return_if_fail(instance != NULL);
431 	g_return_if_fail(signal   != NULL);
432 
433 	va_start(args, signal);
434 	purple_signal_emit_vargs(instance, signal, args);
435 	va_end(args);
436 }
437 
438 void
purple_signal_emit_vargs(void * instance,const char * signal,va_list args)439 purple_signal_emit_vargs(void *instance, const char *signal, va_list args)
440 {
441 	PurpleInstanceData *instance_data;
442 	PurpleSignalData *signal_data;
443 	PurpleSignalHandlerData *handler_data;
444 	GList *l, *l_next;
445 	va_list tmp;
446 
447 	g_return_if_fail(instance != NULL);
448 	g_return_if_fail(signal   != NULL);
449 
450 	instance_data =
451 		(PurpleInstanceData *)g_hash_table_lookup(instance_table, instance);
452 
453 	g_return_if_fail(instance_data != NULL);
454 
455 	signal_data =
456 		(PurpleSignalData *)g_hash_table_lookup(instance_data->signals, signal);
457 
458 	if (signal_data == NULL)
459 	{
460 		purple_debug(PURPLE_DEBUG_ERROR, "signals",
461 				   "Signal data for %s not found!\n", signal);
462 		return;
463 	}
464 
465 	for (l = signal_data->handlers; l != NULL; l = l_next)
466 	{
467 		l_next = l->next;
468 
469 		handler_data = (PurpleSignalHandlerData *)l->data;
470 
471 		/* This is necessary because a va_list may only be
472 		 * evaluated once */
473 		G_VA_COPY(tmp, args);
474 
475 		if (handler_data->use_vargs)
476 		{
477 			((void (*)(va_list, void *))handler_data->cb)(tmp,
478 														  handler_data->data);
479 		}
480 		else
481 		{
482 			signal_data->marshal(handler_data->cb, tmp,
483 								 handler_data->data, NULL);
484 		}
485 
486 		va_end(tmp);
487 	}
488 
489 #ifdef HAVE_DBUS
490 	purple_dbus_signal_emit_purple(signal, signal_data->num_values,
491 				   signal_data->values, args);
492 #endif	/* HAVE_DBUS */
493 
494 }
495 
496 void *
purple_signal_emit_return_1(void * instance,const char * signal,...)497 purple_signal_emit_return_1(void *instance, const char *signal, ...)
498 {
499 	void *ret_val;
500 	va_list args;
501 
502 	g_return_val_if_fail(instance != NULL, NULL);
503 	g_return_val_if_fail(signal   != NULL, NULL);
504 
505 	va_start(args, signal);
506 	ret_val = purple_signal_emit_vargs_return_1(instance, signal, args);
507 	va_end(args);
508 
509 	return ret_val;
510 }
511 
512 void *
purple_signal_emit_vargs_return_1(void * instance,const char * signal,va_list args)513 purple_signal_emit_vargs_return_1(void *instance, const char *signal,
514 								va_list args)
515 {
516 	PurpleInstanceData *instance_data;
517 	PurpleSignalData *signal_data;
518 	PurpleSignalHandlerData *handler_data;
519 	GList *l, *l_next;
520 	va_list tmp;
521 
522 	g_return_val_if_fail(instance != NULL, NULL);
523 	g_return_val_if_fail(signal   != NULL, NULL);
524 
525 	instance_data =
526 		(PurpleInstanceData *)g_hash_table_lookup(instance_table, instance);
527 
528 	g_return_val_if_fail(instance_data != NULL, NULL);
529 
530 	signal_data =
531 		(PurpleSignalData *)g_hash_table_lookup(instance_data->signals, signal);
532 
533 	if (signal_data == NULL)
534 	{
535 		purple_debug(PURPLE_DEBUG_ERROR, "signals",
536 				   "Signal data for %s not found!\n", signal);
537 		return 0;
538 	}
539 
540 #ifdef HAVE_DBUS
541 	G_VA_COPY(tmp, args);
542 	purple_dbus_signal_emit_purple(signal, signal_data->num_values,
543 				   signal_data->values, tmp);
544 	va_end(tmp);
545 #endif	/* HAVE_DBUS */
546 
547 	for (l = signal_data->handlers; l != NULL; l = l_next)
548 	{
549 		void *ret_val = NULL;
550 
551 		l_next = l->next;
552 
553 		handler_data = (PurpleSignalHandlerData *)l->data;
554 
555 		G_VA_COPY(tmp, args);
556 		if (handler_data->use_vargs)
557 		{
558 			ret_val = ((void *(*)(va_list, void *))handler_data->cb)(
559 				tmp, handler_data->data);
560 		}
561 		else
562 		{
563 			signal_data->marshal(handler_data->cb, tmp,
564 								 handler_data->data, &ret_val);
565 		}
566 		va_end(tmp);
567 
568 		if (ret_val != NULL)
569 			return ret_val;
570 	}
571 
572 	return NULL;
573 }
574 
575 void
purple_signals_init()576 purple_signals_init()
577 {
578 	g_return_if_fail(instance_table == NULL);
579 
580 	instance_table =
581 		g_hash_table_new_full(g_direct_hash, g_direct_equal,
582 							  NULL, (GDestroyNotify)destroy_instance_data);
583 }
584 
585 void
purple_signals_uninit()586 purple_signals_uninit()
587 {
588 	g_return_if_fail(instance_table != NULL);
589 
590 	g_hash_table_destroy(instance_table);
591 	instance_table = NULL;
592 }
593 
594 /**************************************************************************
595  * Marshallers
596  **************************************************************************/
597 void
purple_marshal_VOID(PurpleCallback cb,va_list args,void * data,void ** return_val)598 purple_marshal_VOID(PurpleCallback cb, va_list args, void *data,
599 				  void **return_val)
600 {
601 	((void (*)(void *))cb)(data);
602 }
603 
604 void
purple_marshal_VOID__INT(PurpleCallback cb,va_list args,void * data,void ** return_val)605 purple_marshal_VOID__INT(PurpleCallback cb, va_list args, void *data,
606 					   void **return_val)
607 {
608 	gint arg1 = va_arg(args, gint);
609 
610 	((void (*)(gint, void *))cb)(arg1, data);
611 }
612 
613 void
purple_marshal_VOID__INT_INT(PurpleCallback cb,va_list args,void * data,void ** return_val)614 purple_marshal_VOID__INT_INT(PurpleCallback cb, va_list args, void *data,
615 						   void **return_val)
616 {
617 	gint arg1 = va_arg(args, gint);
618 	gint arg2 = va_arg(args, gint);
619 
620 	((void (*)(gint, gint, void *))cb)(arg1, arg2, data);
621 }
622 
623 void
purple_marshal_VOID__POINTER(PurpleCallback cb,va_list args,void * data,void ** return_val)624 purple_marshal_VOID__POINTER(PurpleCallback cb, va_list args, void *data,
625 						   void **return_val)
626 {
627 	void *arg1 = va_arg(args, void *);
628 
629 	((void (*)(void *, void *))cb)(arg1, data);
630 }
631 
632 void
purple_marshal_VOID__POINTER_UINT(PurpleCallback cb,va_list args,void * data,void ** return_val)633 purple_marshal_VOID__POINTER_UINT(PurpleCallback cb, va_list args,
634 										void *data, void **return_val)
635 {
636 	void *arg1 = va_arg(args, void *);
637 	guint arg2 = va_arg(args, guint);
638 
639 	((void (*)(void *, guint, void *))cb)(arg1, arg2, data);
640 }
641 
purple_marshal_VOID__POINTER_INT_INT(PurpleCallback cb,va_list args,void * data,void ** return_val)642 void purple_marshal_VOID__POINTER_INT_INT(PurpleCallback cb, va_list args,
643                                         void *data, void **return_val)
644 {
645 	void *arg1 = va_arg(args, void *);
646 	gint arg2 = va_arg(args, gint);
647 	gint arg3 = va_arg(args, gint);
648 
649 	((void (*)(void *, gint, gint, void *))cb)(arg1, arg2, arg3, data);
650 }
651 
purple_marshal_VOID__POINTER_INT_POINTER(PurpleCallback cb,va_list args,void * data,void ** return_val)652 void purple_marshal_VOID__POINTER_INT_POINTER(PurpleCallback cb, va_list args,
653                                               void *data, void **return_val)
654 {
655 	void *arg1 = va_arg(args, void *);
656 	gint arg2 = va_arg(args, gint);
657 	void *arg3 = va_arg(args, void *);
658 
659 	((void (*)(void *, gint, void *, void *))cb)(arg1, arg2, arg3, data);
660 }
661 
662 void
purple_marshal_VOID__POINTER_POINTER(PurpleCallback cb,va_list args,void * data,void ** return_val)663 purple_marshal_VOID__POINTER_POINTER(PurpleCallback cb, va_list args,
664 								   void *data, void **return_val)
665 {
666 	void *arg1 = va_arg(args, void *);
667 	void *arg2 = va_arg(args, void *);
668 
669 	((void (*)(void *, void *, void *))cb)(arg1, arg2, data);
670 }
671 
672 void
purple_marshal_VOID__POINTER_POINTER_UINT(PurpleCallback cb,va_list args,void * data,void ** return_val)673 purple_marshal_VOID__POINTER_POINTER_UINT(PurpleCallback cb, va_list args,
674 										void *data, void **return_val)
675 {
676 	void *arg1 = va_arg(args, void *);
677 	void *arg2 = va_arg(args, void *);
678 	guint arg3 = va_arg(args, guint);
679 
680 	((void (*)(void *, void *, guint, void *))cb)(arg1, arg2, arg3, data);
681 }
682 
683 void
purple_marshal_VOID__POINTER_POINTER_UINT_UINT(PurpleCallback cb,va_list args,void * data,void ** return_val)684 purple_marshal_VOID__POINTER_POINTER_UINT_UINT(PurpleCallback cb, va_list args,
685 										     void *data, void **return_val)
686 {
687 	void *arg1 = va_arg(args, void *);
688 	void *arg2 = va_arg(args, void *);
689 	guint arg3 = va_arg(args, guint);
690 	guint arg4 = va_arg(args, guint);
691 
692 	((void (*)(void *, void *, guint, guint, void *))cb)(arg1, arg2, arg3, arg4, data);
693 }
694 
695 void
purple_marshal_VOID__POINTER_POINTER_POINTER(PurpleCallback cb,va_list args,void * data,void ** return_val)696 purple_marshal_VOID__POINTER_POINTER_POINTER(PurpleCallback cb, va_list args,
697 										   void *data, void **return_val)
698 {
699 	void *arg1 = va_arg(args, void *);
700 	void *arg2 = va_arg(args, void *);
701 	void *arg3 = va_arg(args, void *);
702 
703 	((void (*)(void *, void *, void *, void *))cb)(arg1, arg2, arg3, data);
704 }
705 
706 void
purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER(PurpleCallback cb,va_list args,void * data,void ** return_val)707 purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER(PurpleCallback cb,
708 												   va_list args,
709 												   void *data,
710 												   void **return_val)
711 {
712 	void *arg1 = va_arg(args, void *);
713 	void *arg2 = va_arg(args, void *);
714 	void *arg3 = va_arg(args, void *);
715 	void *arg4 = va_arg(args, void *);
716 
717 	((void (*)(void *, void *, void *, void *, void *))cb)(arg1, arg2, arg3, arg4, data);
718 }
719 
720 void
purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_POINTER(PurpleCallback cb,va_list args,void * data,void ** return_val)721 purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_POINTER(PurpleCallback cb,
722 														   va_list args,
723 														   void *data,
724 														   void **return_val)
725 {
726 	void *arg1 = va_arg(args, void *);
727 	void *arg2 = va_arg(args, void *);
728 	void *arg3 = va_arg(args, void *);
729 	void *arg4 = va_arg(args, void *);
730 	void *arg5 = va_arg(args, void *);
731 
732 	((void (*)(void *, void *, void *, void *, void *, void *))cb)(arg1, arg2, arg3, arg4, arg5, data);
733 }
734 
735 void
purple_marshal_VOID__POINTER_POINTER_POINTER_UINT(PurpleCallback cb,va_list args,void * data,void ** return_val)736 purple_marshal_VOID__POINTER_POINTER_POINTER_UINT(PurpleCallback cb,
737 												   va_list args,
738 												   void *data,
739 												   void **return_val)
740 {
741 	void *arg1 = va_arg(args, void *);
742 	void *arg2 = va_arg(args, void *);
743 	void *arg3 = va_arg(args, void *);
744 	guint arg4 = va_arg(args, guint);
745 
746 	((void (*)(void *, void *, void *, guint, void *))cb)(arg1, arg2, arg3, arg4, data);
747 }
748 
749 void
purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT(PurpleCallback cb,va_list args,void * data,void ** return_val)750 purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT(PurpleCallback cb,
751 													    va_list args,
752 													    void *data,
753 													    void **return_val)
754 {
755 	void *arg1 = va_arg(args, void *);
756 	void *arg2 = va_arg(args, void *);
757 	void *arg3 = va_arg(args, void *);
758 	void *arg4 = va_arg(args, void *);
759 	guint arg5 = va_arg(args, guint);
760 
761 	((void (*)(void *, void *, void *, void *, guint, void *))cb)(arg1, arg2, arg3, arg4, arg5, data);
762 }
763 
764 void
purple_marshal_VOID__POINTER_POINTER_POINTER_UINT_UINT(PurpleCallback cb,va_list args,void * data,void ** return_val)765 purple_marshal_VOID__POINTER_POINTER_POINTER_UINT_UINT(PurpleCallback cb,
766 													 va_list args,
767 													 void *data,
768 													 void **return_val)
769 {
770 	void *arg1 = va_arg(args, void *);
771 	void *arg2 = va_arg(args, void *);
772 	void *arg3 = va_arg(args, void *);
773 	guint arg4 = va_arg(args, guint);
774 	guint arg5 = va_arg(args, guint);
775 
776 	((void (*)(void *, void *, void *, guint, guint, void *))cb)(
777 			arg1, arg2, arg3, arg4, arg5, data);
778 }
779 
780 void
purple_marshal_INT__INT(PurpleCallback cb,va_list args,void * data,void ** return_val)781 purple_marshal_INT__INT(PurpleCallback cb, va_list args, void *data,
782 					  void **return_val)
783 {
784 	gint ret_val;
785 	gint arg1 = va_arg(args, gint);
786 
787 	ret_val = ((gint (*)(gint, void *))cb)(arg1, data);
788 
789 	if (return_val != NULL)
790 		*return_val = GINT_TO_POINTER(ret_val);
791 }
792 
793 void
purple_marshal_INT__INT_INT(PurpleCallback cb,va_list args,void * data,void ** return_val)794 purple_marshal_INT__INT_INT(PurpleCallback cb, va_list args, void *data,
795 						  void **return_val)
796 {
797 	gint ret_val;
798 	gint arg1 = va_arg(args, gint);
799 	gint arg2 = va_arg(args, gint);
800 
801 	ret_val = ((gint (*)(gint, gint, void *))cb)(arg1, arg2, data);
802 
803 	if (return_val != NULL)
804 		*return_val = GINT_TO_POINTER(ret_val);
805 }
806 
807 void
purple_marshal_INT__POINTER_POINTER(PurpleCallback cb,va_list args,void * data,void ** return_val)808 purple_marshal_INT__POINTER_POINTER(PurpleCallback cb, va_list args, void *data,
809                                       void **return_val)
810 {
811 	gint ret_val;
812 	void *arg1 = va_arg(args, void *);
813 	void *arg2 = va_arg(args, void *);
814 
815 	ret_val = ((gint (*)(void *, void *, void *))cb)(arg1, arg2, data);
816 
817 	if (return_val != NULL)
818 		*return_val = GINT_TO_POINTER(ret_val);
819 }
820 
821 	void
purple_marshal_INT__POINTER_POINTER_POINTER(PurpleCallback cb,va_list args,void * data,void ** return_val)822 purple_marshal_INT__POINTER_POINTER_POINTER(
823 		PurpleCallback cb, va_list args, void *data, void **return_val)
824 {
825 	gint ret_val;
826 	void *arg1 = va_arg(args, void *);
827 	void *arg2 = va_arg(args, void *);
828 	void *arg3 = va_arg(args, void *);
829 
830 	ret_val = ((gint (*)(void *, void *, void *, void *))cb)(arg1, arg2, arg3, data);
831 
832 	if (return_val != NULL)
833 		*return_val = GINT_TO_POINTER(ret_val);
834 }
835 
836 void
purple_marshal_INT__POINTER_POINTER_POINTER_POINTER_POINTER(PurpleCallback cb,va_list args,void * data,void ** return_val)837 purple_marshal_INT__POINTER_POINTER_POINTER_POINTER_POINTER(
838 		PurpleCallback cb, va_list args, void *data, void **return_val)
839 {
840 	gint ret_val;
841 	void *arg1 = va_arg(args, void *);
842 	void *arg2 = va_arg(args, void *);
843 	void *arg3 = va_arg(args, void *);
844 	void *arg4 = va_arg(args, void *);
845 	void *arg5 = va_arg(args, void *);
846 
847 	ret_val =
848 		((gint (*)(void *, void *, void *, void *, void *, void *))cb)(
849 			arg1, arg2, arg3, arg4, arg5, data);
850 
851 	if (return_val != NULL)
852 		*return_val = GINT_TO_POINTER(ret_val);
853 }
854 
855 void
purple_marshal_BOOLEAN__POINTER(PurpleCallback cb,va_list args,void * data,void ** return_val)856 purple_marshal_BOOLEAN__POINTER(PurpleCallback cb, va_list args, void *data,
857 							  void **return_val)
858 {
859 	gboolean ret_val;
860 	void *arg1 = va_arg(args, void *);
861 
862 	ret_val = ((gboolean (*)(void *, void *))cb)(arg1, data);
863 
864 	if (return_val != NULL)
865 		*return_val = GINT_TO_POINTER(ret_val);
866 }
867 
868 void
purple_marshal_BOOLEAN__POINTER_POINTER(PurpleCallback cb,va_list args,void * data,void ** return_val)869 purple_marshal_BOOLEAN__POINTER_POINTER(PurpleCallback cb, va_list args,
870 									  void *data, void **return_val)
871 {
872 	gboolean ret_val;
873 	void *arg1 = va_arg(args, void *);
874 	void *arg2 = va_arg(args, void *);
875 
876 	ret_val = ((gboolean (*)(void *, void *, void *))cb)(arg1, arg2, data);
877 
878 	if (return_val != NULL)
879 		*return_val = GINT_TO_POINTER(ret_val);
880 }
881 
882 void
purple_marshal_BOOLEAN__POINTER_BOOLEAN(PurpleCallback cb,va_list args,void * data,void ** return_val)883 purple_marshal_BOOLEAN__POINTER_BOOLEAN(PurpleCallback cb, va_list args,
884 									  void *data, void **return_val)
885 {
886 	gboolean ret_val;
887 	void *arg1 = va_arg(args, void *);
888 	gboolean arg2 = va_arg(args, gboolean);
889 
890 	ret_val = ((gboolean (*)(void *, gboolean, void *))cb)(arg1, arg2, data);
891 
892 	if (return_val != NULL)
893 		*return_val = GINT_TO_POINTER(ret_val);
894 }
895 
896 void
purple_marshal_BOOLEAN__POINTER_POINTER_POINTER(PurpleCallback cb,va_list args,void * data,void ** return_val)897 purple_marshal_BOOLEAN__POINTER_POINTER_POINTER(PurpleCallback cb, va_list args,
898 											  void *data, void **return_val)
899 {
900 	gboolean ret_val;
901 	void *arg1 = va_arg(args, void *);
902 	void *arg2 = va_arg(args, void *);
903 	void *arg3 = va_arg(args, void *);
904 
905 	ret_val = ((gboolean (*)(void *, void *, void *, void *))cb)(arg1, arg2,
906 																 arg3, data);
907 
908 	if (return_val != NULL)
909 		*return_val = GINT_TO_POINTER(ret_val);
910 }
911 
912 void
purple_marshal_BOOLEAN__POINTER_POINTER_UINT(PurpleCallback cb,va_list args,void * data,void ** return_val)913 purple_marshal_BOOLEAN__POINTER_POINTER_UINT(PurpleCallback cb,
914 												   va_list args,
915 												   void *data,
916 												   void **return_val)
917 {
918 	gboolean ret_val;
919 	void *arg1 = va_arg(args, void *);
920 	void *arg2 = va_arg(args, void *);
921 	guint arg3 = va_arg(args, guint);
922 
923 	ret_val = ((gboolean (*)(void *, void *, guint, void *))cb)(
924 			arg1, arg2, arg3, data);
925 
926 	if (return_val != NULL)
927 		*return_val = GINT_TO_POINTER(ret_val);
928 }
929 
930 void
purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_UINT(PurpleCallback cb,va_list args,void * data,void ** return_val)931 purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_UINT(PurpleCallback cb,
932 												   va_list args,
933 												   void *data,
934 												   void **return_val)
935 {
936 	gboolean ret_val;
937 	void *arg1 = va_arg(args, void *);
938 	void *arg2 = va_arg(args, void *);
939 	void *arg3 = va_arg(args, void *);
940 	guint arg4 = va_arg(args, guint);
941 
942 	ret_val = ((gboolean (*)(void *, void *, void *, guint, void *))cb)(
943 			arg1, arg2, arg3, arg4, data);
944 
945 	if (return_val != NULL)
946 		*return_val = GINT_TO_POINTER(ret_val);
947 }
948 
949 void
purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER(PurpleCallback cb,va_list args,void * data,void ** return_val)950 purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER(PurpleCallback cb,
951 													  va_list args,
952 													  void *data,
953 													  void **return_val)
954 {
955 	gboolean ret_val;
956 	void *arg1 = va_arg(args, void *);
957 	void *arg2 = va_arg(args, void *);
958 	void *arg3 = va_arg(args, void *);
959 	void *arg4 = va_arg(args, void *);
960 
961 	ret_val = ((gboolean (*)(void *, void *, void *, void *, void *))cb)(
962 			arg1, arg2, arg3, arg4, data);
963 
964 	if (return_val != NULL)
965 		*return_val = GINT_TO_POINTER(ret_val);
966 }
967 
968 void
purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER(PurpleCallback cb,va_list args,void * data,void ** return_val)969 purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER(
970 		PurpleCallback cb, va_list args, void *data, void **return_val)
971 {
972 	gboolean ret_val;
973 	void *arg1 = va_arg(args, void *);
974 	void *arg2 = va_arg(args, void *);
975 	void *arg3 = va_arg(args, void *);
976 	void *arg4 = va_arg(args, void *);
977 	void *arg5 = va_arg(args, void *);
978 
979 	ret_val =
980 		((gboolean (*)(void *, void *, void *, void *, void *, void *))cb)(
981 			arg1, arg2, arg3, arg4, arg5, data);
982 
983 	if (return_val != NULL)
984 		*return_val = GINT_TO_POINTER(ret_val);
985 }
986 
987 void
purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_UINT(PurpleCallback cb,va_list args,void * data,void ** return_val)988 purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_UINT(
989 		PurpleCallback cb, va_list args, void *data, void **return_val)
990 {
991 	gboolean ret_val;
992 	void *arg1 = va_arg(args, void *);
993 	void *arg2 = va_arg(args, void *);
994 	void *arg3 = va_arg(args, void *);
995 	void *arg4 = va_arg(args, void *);
996 	guint arg5 = va_arg(args, guint);
997 
998 	ret_val =
999 		((gboolean (*)(void *, void *, void *, void *, guint, void *))cb)(
1000 			arg1, arg2, arg3, arg4, arg5, data);
1001 
1002 	if (return_val != NULL)
1003 		*return_val = GINT_TO_POINTER(ret_val);
1004 }
1005 
1006 void
purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER_POINTER(PurpleCallback cb,va_list args,void * data,void ** return_val)1007 purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER_POINTER(
1008 		PurpleCallback cb, va_list args, void *data, void **return_val)
1009 {
1010 	gboolean ret_val;
1011 	void *arg1 = va_arg(args, void *);
1012 	void *arg2 = va_arg(args, void *);
1013 	void *arg3 = va_arg(args, void *);
1014 	void *arg4 = va_arg(args, void *);
1015 	void *arg5 = va_arg(args, void *);
1016 	void *arg6 = va_arg(args, void *);
1017 
1018 	ret_val =
1019 		((gboolean (*)(void *, void *, void *, void *, void *, void *, void *))cb)(
1020 			arg1, arg2, arg3, arg4, arg5, arg6, data);
1021 
1022 	if (return_val != NULL)
1023 		*return_val = GINT_TO_POINTER(ret_val);
1024 }
1025 
1026 void
purple_marshal_BOOLEAN__INT_POINTER(PurpleCallback cb,va_list args,void * data,void ** return_val)1027 purple_marshal_BOOLEAN__INT_POINTER(PurpleCallback cb, va_list args, void *data,
1028                                   void **return_val)
1029 {
1030 	gboolean ret_val;
1031 	gint arg1 = va_arg(args, gint);
1032 	void *arg2 = va_arg(args, void *);
1033 
1034 	ret_val = ((gboolean (*)(gint, void *, void *))cb)(arg1, arg2, data);
1035 
1036 	if (return_val != NULL)
1037 		*return_val = GINT_TO_POINTER(ret_val);
1038 }
1039 
1040 void
purple_marshal_POINTER__POINTER(PurpleCallback cb,va_list args,void * data,void ** return_val)1041 purple_marshal_POINTER__POINTER(
1042                                     PurpleCallback cb, va_list args, void *data,
1043                                     void **return_val)
1044 {
1045 	gpointer ret_val;
1046 	void *arg1 = va_arg(args, void *);
1047 
1048 	ret_val = ((gpointer(*)(void *, void *))cb)(arg1, data);
1049 
1050 	if (return_val != NULL)
1051 		*return_val = ret_val;
1052 }
1053 
1054 
1055 void
purple_marshal_POINTER__POINTER_INT(PurpleCallback cb,va_list args,void * data,void ** return_val)1056 purple_marshal_POINTER__POINTER_INT(
1057                                     PurpleCallback cb, va_list args, void *data,
1058                                     void **return_val)
1059 {
1060 	gpointer ret_val;
1061 	void *arg1 = va_arg(args, void *);
1062 	gint arg2 = va_arg(args, gint);
1063 
1064 	ret_val = ((gpointer(*)(void *, gint, void *))cb)(arg1, arg2, data);
1065 
1066 	if (return_val != NULL)
1067 		*return_val = ret_val;
1068 }
1069 
1070 void
purple_marshal_POINTER__POINTER_INT64(PurpleCallback cb,va_list args,void * data,void ** return_val)1071 purple_marshal_POINTER__POINTER_INT64(
1072                                     PurpleCallback cb, va_list args, void *data,
1073                                     void **return_val)
1074 {
1075 	gpointer ret_val;
1076 	void *arg1 = va_arg(args, void *);
1077 	gint64 arg2 = va_arg(args, gint64);
1078 
1079 	ret_val = ((gpointer(*)(void *, gint64, void *))cb)(arg1, arg2, data);
1080 
1081 	if (return_val != NULL)
1082 		*return_val = ret_val;
1083 }
1084 
1085 void
purple_marshal_POINTER__POINTER_INT_BOOLEAN(PurpleCallback cb,va_list args,void * data,void ** return_val)1086 purple_marshal_POINTER__POINTER_INT_BOOLEAN(
1087                                     PurpleCallback cb, va_list args, void *data,
1088                                     void **return_val)
1089 {
1090 	gpointer ret_val;
1091 	void *arg1 = va_arg(args, void *);
1092 	gint arg2 = va_arg(args, gint);
1093 	gboolean arg3 = va_arg(args, gboolean);
1094 
1095 	ret_val = ((gpointer(*)(void *, gint, gboolean, void *))cb)(arg1, arg2, arg3, data);
1096 
1097 	if (return_val != NULL)
1098 		*return_val = ret_val;
1099 }
1100 
1101 void
purple_marshal_POINTER__POINTER_INT64_BOOLEAN(PurpleCallback cb,va_list args,void * data,void ** return_val)1102 purple_marshal_POINTER__POINTER_INT64_BOOLEAN(
1103                                     PurpleCallback cb, va_list args, void *data,
1104                                     void **return_val)
1105 {
1106 	gpointer ret_val;
1107 	void *arg1 = va_arg(args, void *);
1108 	gint64 arg2 = va_arg(args, gint64);
1109 	gboolean arg3 = va_arg(args, gboolean);
1110 
1111 	ret_val = ((gpointer(*)(void *, gint64, gboolean, void *))cb)(arg1, arg2, arg3, data);
1112 
1113 	if (return_val != NULL)
1114 		*return_val = ret_val;
1115 }
1116 
1117 void
purple_marshal_POINTER__POINTER_POINTER(PurpleCallback cb,va_list args,void * data,void ** return_val)1118 purple_marshal_POINTER__POINTER_POINTER(PurpleCallback cb, va_list args, void *data,
1119                                       void **return_val)
1120 {
1121 	gpointer ret_val;
1122 	void *arg1 = va_arg(args, void *);
1123 	void *arg2 = va_arg(args, void *);
1124 
1125 	ret_val = ((gpointer (*)(void *, void *, void *))cb)(arg1, arg2, data);
1126 
1127 	if (return_val != NULL)
1128 		*return_val = ret_val;
1129 }
1130