Mercurial > pidgin
annotate libgaim/plugins/perl/perl-common.c @ 15218:ec96d6d2fa6d
[gaim-migrate @ 18008]
Patch from Graham Booker to slowly scale up the size of our read or write
buffer when transfer files over fast networks. This should hopefully
reduce CPU load a tiny bit when transfer large files over fast connections.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Fri, 15 Dec 2006 08:39:53 +0000 |
parents | b1fcd2fc903a |
children |
rev | line source |
---|---|
14192 | 1 #include "debug.h" |
2 #include "value.h" | |
3 | |
4 #include "perl-common.h" | |
5 | |
6 extern PerlInterpreter *my_perl; | |
7 | |
8 static GHashTable *object_stashes = NULL; | |
9 | |
10 void gaim_perl_normalize_script_name(char *name) | |
11 { | |
12 char *c; | |
13 | |
14 c = strrchr(name, '.'); | |
15 | |
16 if (c != NULL) | |
17 *c = '\0'; | |
18 | |
19 for (c = name; *c != '\0'; c++) { | |
20 if (*c != '_' && !g_ascii_isalnum(*c)) | |
21 *c = '_'; | |
22 } | |
23 } | |
24 | |
25 static int | |
26 magic_free_object(pTHX_ SV *sv, MAGIC *mg) | |
27 { | |
28 sv_setiv(sv, 0); | |
29 | |
30 return 0; | |
31 } | |
32 | |
33 static MGVTBL vtbl_free_object = | |
34 { | |
35 NULL, NULL, NULL, NULL, magic_free_object, NULL, NULL | |
36 }; | |
37 | |
38 static SV * | |
39 create_sv_ptr(void *object) | |
40 { | |
41 SV *sv; | |
42 | |
43 sv = newSViv((IV)object); | |
44 | |
45 sv_magic(sv, NULL, '~', NULL, 0); | |
46 | |
47 SvMAGIC(sv)->mg_private = 0x1551; /* HF */ | |
48 SvMAGIC(sv)->mg_virtual = &vtbl_free_object; | |
49 | |
50 return sv; | |
51 } | |
52 | |
53 SV * | |
54 newSVGChar(const char *str) | |
55 { | |
56 SV *sv; | |
57 | |
58 if (str == NULL) | |
59 return &PL_sv_undef; | |
60 | |
61 sv = newSVpv(str, 0); | |
62 SvUTF8_on(sv); | |
63 | |
64 return sv; | |
65 } | |
66 | |
67 SV * | |
68 gaim_perl_bless_object(void *object, const char *stash_name) | |
69 { | |
70 HV *stash; | |
71 HV *hv; | |
72 | |
73 if (object == NULL) | |
74 return NULL; | |
75 | |
76 if (object_stashes == NULL) { | |
77 object_stashes = g_hash_table_new(g_direct_hash, g_direct_equal); | |
78 } | |
79 | |
80 stash = gv_stashpv(stash_name, 1); | |
81 | |
82 hv = newHV(); | |
83 hv_store(hv, "_gaim", 5, create_sv_ptr(object), 0); | |
84 | |
85 return sv_bless(newRV_noinc((SV *)hv), stash); | |
86 } | |
87 | |
88 gboolean | |
89 gaim_perl_is_ref_object(SV *o) | |
90 { | |
91 SV **sv; | |
92 HV *hv; | |
93 | |
94 hv = hvref(o); | |
95 | |
96 if (hv != NULL) { | |
97 sv = hv_fetch(hv, "_gaim", 5, 0); | |
98 | |
99 if (sv != NULL) | |
100 return TRUE; | |
101 } | |
102 | |
103 return FALSE; | |
104 } | |
105 | |
106 void * | |
107 gaim_perl_ref_object(SV *o) | |
108 { | |
109 SV **sv; | |
110 HV *hv; | |
111 void *p; | |
112 | |
113 if (o == NULL) | |
114 return NULL; | |
115 | |
116 hv = hvref(o); | |
117 | |
118 if (hv == NULL) | |
119 return NULL; | |
120 | |
121 sv = hv_fetch(hv, "_gaim", 5, 0); | |
122 | |
123 if (sv == NULL) | |
124 croak("variable is damaged"); | |
125 | |
126 p = GINT_TO_POINTER(SvIV(*sv)); | |
127 | |
128 return p; | |
129 } | |
130 | |
131 /* | |
132 2003/02/06: execute_perl modified by Mark Doliner <mark@kingant.net> | |
133 Pass parameters by pushing them onto the stack rather than | |
134 passing an array of strings. This way, perl scripts can | |
135 modify the parameters and we can get the changed values | |
136 and then shoot ourselves. I mean, uh, use them. | |
137 | |
138 2001/06/14: execute_perl replaced by Martin Persson <mep@passagen.se> | |
139 previous use of perl_eval leaked memory, replaced with | |
140 a version that uses perl_call instead | |
141 | |
142 30/11/2002: execute_perl modified by Eric Timme <timothy@voidnet.com> | |
143 args changed to char** so that we can have preparsed | |
144 arguments again, and many headaches ensued! This essentially | |
145 means we replaced one hacked method with a messier hacked | |
146 method out of perceived necessity. Formerly execute_perl | |
147 required a single char_ptr, and it would insert it into an | |
148 array of character pointers and NULL terminate the new array. | |
149 Now we have to pass in pre-terminated character pointer arrays | |
150 to accomodate functions that want to pass in multiple arguments. | |
151 | |
152 Previously arguments were preparsed because an argument list | |
153 was constructed in the form 'arg one','arg two' and was | |
154 executed via a call like &funcname(arglist) (see .59.x), so | |
155 the arglist was magically pre-parsed because of the method. | |
156 With Martin Persson's change to perl_call we now need to | |
157 use a null terminated list of character pointers for arguments | |
158 if we wish them to be parsed. Lacking a better way to allow | |
159 for both single arguments and many I created a NULL terminated | |
160 array in every function that called execute_perl and passed | |
161 that list into the function. In the former version a single | |
162 character pointer was passed in, and was placed into an array | |
163 of character pointers with two elements, with a NULL element | |
164 tacked onto the back, but this method no longer seemed prudent. | |
165 | |
166 Enhancements in the future might be to get rid of pre-declaring | |
167 the array sizes? I am not comfortable enough with this | |
168 subject to attempt it myself and hope it to stand the test | |
169 of time. | |
170 */ | |
171 int | |
172 execute_perl(const char *function, int argc, char **args) | |
173 { | |
174 int count = 0, i, ret_value = 1; | |
175 SV *sv_args[argc]; | |
176 STRLEN na; | |
177 dSP; | |
178 PERL_SET_CONTEXT(my_perl); | |
179 /* | |
180 * Set up the perl environment, push arguments onto the | |
181 * perl stack, then call the given function | |
182 */ | |
183 SPAGAIN; | |
184 ENTER; | |
185 SAVETMPS; | |
186 PUSHMARK(sp); | |
187 | |
188 for (i = 0; i < argc; i++) { | |
189 if (args[i]) { | |
190 sv_args[i] = sv_2mortal(newSVpv(args[i], 0)); | |
191 XPUSHs(sv_args[i]); | |
192 } | |
193 } | |
194 | |
195 PUTBACK; | |
196 PERL_SET_CONTEXT(my_perl); | |
197 count = call_pv(function, G_EVAL | G_SCALAR); | |
198 SPAGAIN; | |
199 | |
200 /* | |
201 * Check for "die," make sure we have 1 argument, and set our | |
202 * return value. | |
203 */ | |
204 if (SvTRUE(ERRSV)) { | |
205 gaim_debug(GAIM_DEBUG_ERROR, "perl", | |
206 "Perl function %s exited abnormally: %s\n", | |
207 function, SvPV(ERRSV, na)); | |
208 POPs; | |
209 } else if (count != 1) { | |
210 /* | |
211 * This should NEVER happen. G_SCALAR ensures that we WILL | |
212 * have 1 parameter. | |
213 */ | |
214 gaim_debug(GAIM_DEBUG_ERROR, "perl", | |
215 "Perl error from %s: expected 1 return value, " | |
216 "but got %d\n", function, count); | |
217 } else | |
218 ret_value = POPi; | |
219 | |
220 /* Check for changed arguments */ | |
221 for (i = 0; i < argc; i++) { | |
222 if (args[i] && strcmp(args[i], SvPVX(sv_args[i]))) { | |
223 /* | |
224 * Shizzel. So the perl script changed one of the parameters, | |
225 * and we want this change to affect the original parameters. | |
226 * args[i] is just a temporary little list of pointers. We don't | |
227 * want to free args[i] here because the new parameter doesn't | |
228 * overwrite the data that args[i] points to. That is done by | |
229 * the function that called execute_perl. I'm not explaining this | |
230 * very well. See, it's aggregate... Oh, but if 2 perl scripts | |
231 * both modify the data, _that's_ a memleak. This is really kind | |
232 * of hackish. I should fix it. Look how long this comment is. | |
233 * Holy crap. | |
234 */ | |
235 args[i] = g_strdup(SvPV(sv_args[i], na)); | |
236 } | |
237 } | |
238 | |
239 PUTBACK; | |
240 FREETMPS; | |
241 LEAVE; | |
242 | |
243 return ret_value; | |
244 } | |
245 | |
246 #if 0 | |
247 gboolean | |
248 gaim_perl_value_from_sv(GaimValue *value, SV *sv) | |
249 { | |
250 switch (gaim_value_get_type(value)) | |
251 { | |
252 case GAIM_TYPE_CHAR: | |
253 if ((tmp = SvGChar(sv)) != NULL) | |
254 gaim_value_set_char(value, tmp[0]); | |
255 else | |
256 return FALSE; | |
257 break; | |
258 | |
259 case GAIM_TYPE_UCHAR: | |
260 if ((tmp = SvPV_nolen(sv)) != NULL) | |
261 gaim_value_set_uchar(value, tmp[0]); | |
262 else | |
263 return FALSE; | |
264 break; | |
265 | |
266 case GAIM_TYPE_BOOLEAN: | |
267 gaim_value_set_boolean(value, SvTRUE(sv)); | |
268 break; | |
269 | |
270 case GAIM_TYPE_INT: | |
271 gaim_value_set_int(value, SvIV(sv)); | |
272 break; | |
273 | |
274 case GAIM_TYPE_UINT: | |
275 gaim_value_set_uint(value, SvIV(sv)); | |
276 break; | |
277 | |
278 case GAIM_TYPE_LONG: | |
279 gaim_value_set_long(value, SvIV(sv)); | |
280 break; | |
281 | |
282 case GAIM_TYPE_ULONG: | |
283 gaim_value_set_ulong(value, SvIV(sv)); | |
284 break; | |
285 | |
286 case GAIM_TYPE_INT64: | |
287 gaim_value_set_int64(value, SvIV(sv)); | |
288 break; | |
289 | |
290 case GAIM_TYPE_UINT64: | |
291 gaim_value_set_uint64(value, SvIV(sv)); | |
292 break; | |
293 | |
294 case GAIM_TYPE_STRING: | |
295 gaim_value_set_string(value, SvGChar(sv)); | |
296 break; | |
297 | |
298 case GAIM_TYPE_POINTER: | |
299 gaim_value_set_pointer(value, (void *)SvIV(sv)); | |
300 break; | |
301 | |
302 case GAIM_TYPE_BOXED: | |
303 if (!strcmp(gaim_value_get_specific_type(value), "SV")) | |
304 gaim_value_set_boxed(value, (sv == &PL_sv_undef ? NULL : sv)); | |
305 else | |
306 gaim_value_set_boxed(value, sv); | |
307 break; | |
308 | |
309 default: | |
310 return FALSE; | |
311 } | |
312 | |
313 return TRUE; | |
314 } | |
315 | |
316 SV * | |
317 gaim_perl_sv_from_value(const GaimValue *value, va_list list) | |
318 { | |
319 switch (gaim_value_get_type(value)) | |
320 { | |
321 case GAIM_TYPE_BOOLEAN: | |
322 return newSViv(gaim_value_get_boolean(value)); | |
323 break; | |
324 | |
325 case GAIM_TYPE_INT: | |
326 return newSViv(gaim_value_get_int(value)); | |
327 break; | |
328 | |
329 case GAIM_TYPE_UINT: | |
330 return newSVuv(gaim_value_get_uint(value)); | |
331 break; | |
332 | |
333 case GAIM_TYPE_LONG: | |
334 return newSViv(gaim_value_get_long(value)); | |
335 break; | |
336 | |
337 case GAIM_TYPE_ULONG: | |
338 return newSVuv(gaim_value_get_ulong(value)); | |
339 break; | |
340 | |
341 case GAIM_TYPE_INT64: | |
342 return newSViv(gaim_value_get_int64(value)); | |
343 break; | |
344 | |
345 case GAIM_TYPE_UINT64: | |
346 return newSVuv(gaim_value_get_int64(value)); | |
347 break; | |
348 | |
349 case GAIM_TYPE_STRING: | |
350 return newSVGChar(gaim_value_get_string(value)); | |
351 break; | |
352 | |
353 case GAIM_TYPE_POINTER: | |
354 return newSViv((IV)gaim_value_get_pointer(value)); | |
355 break; | |
356 | |
357 case GAIM_TYPE_BOXED: | |
358 if (!strcmp(gaim_value_get_specific_type(value), "SV")) | |
359 { | |
360 SV *sv = (SV *)gaim_perl_get_boxed(value); | |
361 | |
362 return (sv == NULL ? &PL_sv_undef : sv); | |
363 } | |
364 | |
365 /* Uh.. I dunno. Try this? */ | |
366 return sv_2mortal(gaim_perl_bless_object( | |
367 gaim_perl_get_boxed(value), | |
368 gaim_value_get_specific_type(value))); | |
369 | |
370 default: | |
371 return FALSE; | |
372 } | |
373 | |
374 return TRUE; | |
375 } | |
376 #endif | |
377 | |
378 void * | |
379 gaim_perl_data_from_sv(GaimValue *value, SV *sv) | |
380 { | |
381 STRLEN na; | |
382 | |
383 switch (gaim_value_get_type(value)) { | |
384 case GAIM_TYPE_BOOLEAN: return (void *)SvIV(sv); | |
385 case GAIM_TYPE_INT: return (void *)SvIV(sv); | |
386 case GAIM_TYPE_UINT: return (void *)SvUV(sv); | |
387 case GAIM_TYPE_LONG: return (void *)SvIV(sv); | |
388 case GAIM_TYPE_ULONG: return (void *)SvUV(sv); | |
389 case GAIM_TYPE_INT64: return (void *)SvIV(sv); | |
390 case GAIM_TYPE_UINT64: return (void *)SvUV(sv); | |
391 case GAIM_TYPE_STRING: return g_strdup((void *)SvPV(sv, na)); | |
392 case GAIM_TYPE_POINTER: return (void *)SvIV(sv); | |
393 case GAIM_TYPE_BOXED: return (void *)SvIV(sv); | |
394 | |
395 default: | |
396 return NULL; | |
397 } | |
398 | |
399 return NULL; | |
400 } | |
401 | |
402 static SV * | |
403 gaim_perl_sv_from_subtype(const GaimValue *value, void *arg) | |
404 { | |
405 const char *stash = NULL; | |
406 | |
407 switch (gaim_value_get_subtype(value)) { | |
408 case GAIM_SUBTYPE_ACCOUNT: | |
409 stash = "Gaim::Account"; | |
410 break; | |
411 case GAIM_SUBTYPE_BLIST: | |
412 stash = "Gaim::BuddyList"; | |
413 break; | |
414 case GAIM_SUBTYPE_BLIST_BUDDY: | |
415 stash = "Gaim::BuddyList::Buddy"; | |
416 break; | |
417 case GAIM_SUBTYPE_BLIST_GROUP: | |
418 stash = "Gaim::BuddyList::Group"; | |
419 break; | |
420 case GAIM_SUBTYPE_BLIST_CHAT: | |
421 stash = "Gaim::BuddyList::Chat"; | |
422 break; | |
423 case GAIM_SUBTYPE_BUDDY_ICON: | |
424 stash = "Gaim::Buddy::Icon"; | |
425 break; | |
426 case GAIM_SUBTYPE_CONNECTION: | |
427 stash = "Gaim::Connection"; | |
428 break; | |
429 case GAIM_SUBTYPE_CONVERSATION: | |
430 stash = "Gaim::Conversation"; | |
431 break; | |
432 case GAIM_SUBTYPE_PLUGIN: | |
433 stash = "Gaim::Plugin"; | |
434 break; | |
435 case GAIM_SUBTYPE_BLIST_NODE: | |
436 stash = "Gaim::BuddyList::Node"; | |
437 break; | |
438 case GAIM_SUBTYPE_CIPHER: | |
439 stash = "Gaim::Cipher"; | |
440 break; | |
441 case GAIM_SUBTYPE_STATUS: | |
442 stash = "Gaim::Status"; | |
443 break; | |
444 case GAIM_SUBTYPE_LOG: | |
445 stash = "Gaim::Log"; | |
446 break; | |
447 case GAIM_SUBTYPE_XFER: | |
448 stash = "Gaim::Xfer"; | |
449 break; | |
14717
b1fcd2fc903a
[gaim-migrate @ 17471]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
450 case GAIM_SUBTYPE_XMLNODE: |
b1fcd2fc903a
[gaim-migrate @ 17471]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
451 stash = "Gaim::XMLNode"; |
b1fcd2fc903a
[gaim-migrate @ 17471]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
452 break; |
14192 | 453 |
454 default: | |
455 stash = "Gaim"; /* ? */ | |
456 } | |
457 | |
458 return sv_2mortal(gaim_perl_bless_object(arg, stash)); | |
459 } | |
460 | |
461 SV * | |
462 gaim_perl_sv_from_vargs(const GaimValue *value, va_list *args, void ***copy_arg) | |
463 { | |
464 if (gaim_value_is_outgoing(value)) { | |
465 switch (gaim_value_get_type(value)) { | |
466 case GAIM_TYPE_SUBTYPE: | |
467 if ((*copy_arg = va_arg(*args, void **)) == NULL) | |
468 return &PL_sv_undef; | |
469 | |
470 return gaim_perl_sv_from_subtype(value, *(void **)*copy_arg); | |
471 | |
472 case GAIM_TYPE_BOOLEAN: | |
473 if ((*copy_arg = (void *)va_arg(*args, gboolean *)) == NULL) | |
474 return &PL_sv_undef; | |
475 | |
476 return newSViv(*(gboolean *)*copy_arg); | |
477 | |
478 case GAIM_TYPE_INT: | |
479 if ((*copy_arg = (void *)va_arg(*args, int *)) == NULL) | |
480 return &PL_sv_undef; | |
481 | |
482 return newSViv(*(int *)*copy_arg); | |
483 | |
484 case GAIM_TYPE_UINT: | |
485 if ((*copy_arg = (void *)va_arg(*args, unsigned int *)) == NULL) | |
486 return &PL_sv_undef; | |
487 | |
488 return newSVuv(*(unsigned int *)*copy_arg); | |
489 | |
490 case GAIM_TYPE_LONG: | |
491 if ((*copy_arg = (void *)va_arg(*args, long *)) == NULL) | |
492 return &PL_sv_undef; | |
493 | |
494 return newSViv(*(long *)*copy_arg); | |
495 | |
496 case GAIM_TYPE_ULONG: | |
497 if ((*copy_arg = (void *)va_arg(*args, | |
498 unsigned long *)) == NULL) | |
499 return &PL_sv_undef; | |
500 | |
501 return newSVuv(*(unsigned long *)*copy_arg); | |
502 | |
503 case GAIM_TYPE_INT64: | |
504 if ((*copy_arg = (void *)va_arg(*args, gint64 *)) == NULL) | |
505 return &PL_sv_undef; | |
506 | |
507 return newSViv(*(gint64 *)*copy_arg); | |
508 | |
509 case GAIM_TYPE_UINT64: | |
510 if ((*copy_arg = (void *)va_arg(*args, guint64 *)) == NULL) | |
511 return &PL_sv_undef; | |
512 | |
513 return newSVuv(*(guint64 *)*copy_arg); | |
514 | |
515 case GAIM_TYPE_STRING: | |
516 if ((*copy_arg = (void *)va_arg(*args, char **)) == NULL) | |
517 return &PL_sv_undef; | |
518 | |
519 return newSVGChar(*(char **)*copy_arg); | |
520 | |
521 case GAIM_TYPE_POINTER: | |
522 if ((*copy_arg = va_arg(*args, void **)) == NULL) | |
523 return &PL_sv_undef; | |
524 | |
525 return newSViv((IV)*(void **)*copy_arg); | |
526 | |
527 case GAIM_TYPE_BOXED: | |
528 /* Uh.. I dunno. Try this? */ | |
529 if ((*copy_arg = va_arg(*args, void **)) == NULL) | |
530 return &PL_sv_undef; | |
531 | |
532 return sv_2mortal(gaim_perl_bless_object( | |
533 *(void **)*copy_arg, | |
534 gaim_value_get_specific_type(value))); | |
535 | |
536 default: | |
537 /* If this happens, things are going to get screwed up... */ | |
538 return NULL; | |
539 } | |
540 } else { | |
541 switch (gaim_value_get_type(value)) { | |
542 case GAIM_TYPE_SUBTYPE: | |
543 if ((*copy_arg = va_arg(*args, void *)) == NULL) | |
544 return &PL_sv_undef; | |
545 | |
546 return gaim_perl_sv_from_subtype(value, *copy_arg); | |
547 | |
548 case GAIM_TYPE_BOOLEAN: | |
549 *copy_arg = GINT_TO_POINTER( va_arg(*args, gboolean) ); | |
550 | |
551 return newSViv((gboolean)GPOINTER_TO_INT(*copy_arg)); | |
552 | |
553 case GAIM_TYPE_INT: | |
554 *copy_arg = GINT_TO_POINTER( va_arg(*args, int) ); | |
555 | |
556 return newSViv(GPOINTER_TO_INT(*copy_arg)); | |
557 | |
558 case GAIM_TYPE_UINT: | |
559 *copy_arg = GUINT_TO_POINTER(va_arg(*args, unsigned int)); | |
560 | |
561 return newSVuv(GPOINTER_TO_UINT(*copy_arg)); | |
562 | |
563 case GAIM_TYPE_LONG: | |
564 *copy_arg = (void *)va_arg(*args, long); | |
565 | |
566 return newSViv((long)*copy_arg); | |
567 | |
568 case GAIM_TYPE_ULONG: | |
569 *copy_arg = (void *)va_arg(*args, unsigned long); | |
570 | |
571 return newSVuv((unsigned long)*copy_arg); | |
572 | |
573 case GAIM_TYPE_INT64: | |
574 #if 0 | |
575 /* XXX This yells and complains. */ | |
576 *copy_arg = va_arg(*args, gint64); | |
577 | |
578 return newSViv(*copy_arg); | |
579 #endif | |
580 break; | |
581 | |
582 case GAIM_TYPE_UINT64: | |
583 /* XXX This also yells and complains. */ | |
584 #if 0 | |
585 *copy_arg = (void *)va_arg(*args, guint64); | |
586 | |
587 return newSVuv(*copy_arg); | |
588 #endif | |
589 break; | |
590 | |
591 case GAIM_TYPE_STRING: | |
592 if ((*copy_arg = (void *)va_arg(*args, char *)) == NULL) | |
593 return &PL_sv_undef; | |
594 | |
595 return newSVGChar((char *)*copy_arg); | |
596 | |
597 case GAIM_TYPE_POINTER: | |
598 if ((*copy_arg = (void *)va_arg(*args, void *)) == NULL) | |
599 return &PL_sv_undef; | |
600 | |
601 return newSViv((IV)*copy_arg); | |
602 | |
603 case GAIM_TYPE_BOXED: | |
604 /* Uh.. I dunno. Try this? */ | |
605 if ((*copy_arg = (void *)va_arg(*args, void *)) == NULL) | |
606 return &PL_sv_undef; | |
607 | |
608 return sv_2mortal(gaim_perl_bless_object(*copy_arg, | |
609 gaim_value_get_specific_type(value))); | |
610 | |
611 default: | |
612 /* If this happens, things are going to get screwed up... */ | |
613 return NULL; | |
614 } | |
615 } | |
616 | |
617 return NULL; | |
618 } |