1 /*
2 * swigutil_pl.c: utility functions for the SWIG Perl bindings
3 *
4 * ====================================================================
5 * Licensed to the Apache Software Foundation (ASF) under one
6 * or more contributor license agreements. See the NOTICE file
7 * distributed with this work for additional information
8 * regarding copyright ownership. The ASF licenses this file
9 * to you under the Apache License, Version 2.0 (the
10 * "License"); you may not use this file except in compliance
11 * with the License. You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing,
16 * software distributed under the License is distributed on an
17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 * KIND, either express or implied. See the License for the
19 * specific language governing permissions and limitations
20 * under the License.
21 * ====================================================================
22 */
23
24 #include <apr.h>
25 #include <apr_general.h>
26 #include <apr_portable.h>
27
28 /* Windows hack: Allow overriding some <perl.h> defaults */
29 #include "swigutil_pl__pre_perl.h"
30
31 #include <EXTERN.h>
32 #include <perl.h>
33 #include <XSUB.h>
34
35 /* Perl defines a _ macro, but SVN uses it for translations.
36 * So undefine _ after including the Perl headers. */
37 #undef _
38
39 #include <stdarg.h>
40 #ifdef WIN32
41 #include <io.h>
42 #endif
43
44 #include "svn_hash.h"
45 #include "svn_pools.h"
46 #include "svn_opt.h"
47 #include "svn_time.h"
48 #include "svn_private_config.h"
49
50 #include "swig_perl_external_runtime.swg"
51
52 #include "swigutil_pl.h"
53
54 /* cache SWIG_TypeQuery results in a perl hash */
55 static HV *type_cache = NULL;
56
57 #define _SWIG_TYPE(name) _swig_perl_type_query(name, 0)
58 #define POOLINFO _SWIG_TYPE("apr_pool_t *")
59
_swig_perl_type_query(const char * type_name,U32 klen)60 static swig_type_info *_swig_perl_type_query(const char *type_name, U32 klen)
61 {
62 SV **type_info;
63 swig_type_info *tinfo;
64
65 if (!type_cache)
66 type_cache = newHV();
67
68 if (klen == 0)
69 klen = strlen(type_name);
70
71 if ((type_info = hv_fetch(type_cache, type_name, klen, 0)))
72 return (swig_type_info *) (SvIV(*type_info));
73
74 tinfo = SWIG_TypeQuery(type_name);
75 hv_store(type_cache, type_name, klen, newSViv((IV)tinfo), 0);
76
77 return tinfo;
78 }
79
80 /* element convertors for perl -> c */
81 typedef void *(*pl_element_converter_t)(SV *value, void *ctx,
82 apr_pool_t *pool);
83
convert_pl_string(SV * value,void * dummy,apr_pool_t * pool)84 static void *convert_pl_string(SV *value, void *dummy, apr_pool_t *pool)
85 {
86 void **result = apr_palloc(pool, sizeof(void *));
87 *result = SvPV_nolen(value);
88 return *result;
89 }
90
convert_pl_obj(SV * value,swig_type_info * tinfo,apr_pool_t * pool)91 static void *convert_pl_obj(SV *value, swig_type_info *tinfo,
92 apr_pool_t *pool)
93 {
94 void **result = apr_palloc(pool, sizeof(void *));
95 if (SWIG_ConvertPtr(value, result, tinfo, 0) < 0) {
96 croak("unable to convert from swig object");
97 }
98 return *result;
99 }
100
convert_pl_revnum_t(SV * value,void * dummy,apr_pool_t * pool)101 static void *convert_pl_revnum_t(SV *value, void *dummy, apr_pool_t *pool)
102 {
103 svn_revnum_t *result = apr_palloc(pool, sizeof(svn_revnum_t));
104 *result = SvIV(value);
105 return (void *)result;
106 }
107
convert_pl_svn_string_t(SV * value,void * dummy,apr_pool_t * pool)108 static void *convert_pl_svn_string_t(SV *value, void *dummy, apr_pool_t *pool)
109 {
110 svn_string_t *result = apr_palloc(pool, sizeof(svn_string_t));
111 /* just the in typemap for svn_string_t */
112 result->data = SvPV(value, result->len);
113 return (void *)result;
114 }
115
116 /* Convert a revision range and return a svn_opt_revision_range_t*.
117 * Value can be:
118 * - a _p_svn_opt_revision_range_t object
119 * - a reference to a two-element array, [start, end],
120 * where start and end is anything accepted by svn_swig_pl_set_revision
121 * If value is not acceptable and *(svn_boolean_t *)ctx is FALSE,
122 * convert_pl_revision_range returns NULL, otherwise it croak()s.
123 */
convert_pl_revision_range(SV * value,void * ctx,apr_pool_t * pool)124 static void *convert_pl_revision_range(SV *value, void *ctx, apr_pool_t *pool)
125 {
126 svn_boolean_t croak_on_error = *(svn_boolean_t *)ctx;
127
128 if (sv_isobject(value) && sv_derived_from(value, "_p_svn_opt_revision_range_t")) {
129 svn_opt_revision_range_t *range;
130 /* this will assign to range */
131 SWIG_ConvertPtr(value, (void **)&range, _SWIG_TYPE("svn_opt_revision_range_t *"), 0);
132 return range;
133 }
134
135 if (SvROK(value)
136 && SvTYPE(SvRV(value)) == SVt_PVAV
137 && av_len((AV *)SvRV(value)) == 1) {
138 /* value is a two-element ARRAY */
139 AV* array = (AV *)SvRV(value);
140 svn_opt_revision_t temp_start, temp_end;
141 svn_opt_revision_t *start, *end;
142 svn_opt_revision_range_t *range;
143
144 /* Note: Due to how svn_swig_pl_set_revision works,
145 * either the passed in svn_opt_revision_t is modified
146 * (and the original pointer returned) or a different pointer
147 * is returned. svn_swig_pl_set_revision may return NULL
148 * only if croak_on_error is FALSE.
149 */
150 start = svn_swig_pl_set_revision(&temp_start,
151 *av_fetch(array, 0, 0),
152 croak_on_error, pool);
153 if (start == NULL)
154 return NULL;
155 end = svn_swig_pl_set_revision(&temp_end,
156 *av_fetch(array, 1, 0),
157 croak_on_error, pool);
158 if (end == NULL)
159 return NULL;
160
161 /* allocate a new range and copy in start and end fields */
162 range = apr_palloc(pool, sizeof(*range));
163 range->start = *start;
164 range->end = *end;
165 return range;
166 }
167
168 if (croak_on_error)
169 croak("unknown revision range: "
170 "must be an array of length 2 whose elements are acceptable "
171 "as opt_revision_t or a _p_svn_opt_revision_range_t object");
172 return NULL;
173 }
174
175 /* perl -> c hash convertors */
svn_swig_pl_to_hash(SV * source,pl_element_converter_t cv,void * ctx,apr_pool_t * pool)176 static apr_hash_t *svn_swig_pl_to_hash(SV *source,
177 pl_element_converter_t cv,
178 void *ctx, apr_pool_t *pool)
179 {
180 apr_hash_t *hash;
181 HV *h;
182 char *key;
183 I32 cnt, retlen;
184
185 if (!(source && SvROK(source) && SvTYPE(SvRV(source)) == SVt_PVHV)) {
186 return NULL;
187 }
188
189 hash = apr_hash_make(pool);
190 h = (HV *)SvRV(source);
191 cnt = hv_iterinit(h);
192 while (cnt--) {
193 SV* item = hv_iternextsv(h, &key, &retlen);
194 void *val = cv(item, ctx, pool);
195 svn_hash_sets(hash, apr_pstrmemdup(pool, key, retlen), val);
196 }
197
198 return hash;
199 }
200
svn_swig_pl_objs_to_hash(SV * source,swig_type_info * tinfo,apr_pool_t * pool)201 apr_hash_t *svn_swig_pl_objs_to_hash(SV *source, swig_type_info *tinfo,
202 apr_pool_t *pool)
203 {
204
205 return svn_swig_pl_to_hash(source, (pl_element_converter_t)convert_pl_obj,
206 tinfo, pool);
207 }
208
svn_swig_pl_strings_to_hash(SV * source,apr_pool_t * pool)209 apr_hash_t *svn_swig_pl_strings_to_hash(SV *source, apr_pool_t *pool)
210 {
211
212 return svn_swig_pl_to_hash(source, convert_pl_string, NULL, pool);
213 }
214
215
svn_swig_pl_objs_to_hash_by_name(SV * source,const char * typename,apr_pool_t * pool)216 apr_hash_t *svn_swig_pl_objs_to_hash_by_name(SV *source,
217 const char *typename,
218 apr_pool_t *pool)
219 {
220 swig_type_info *tinfo = _SWIG_TYPE(typename);
221 return svn_swig_pl_objs_to_hash(source, tinfo, pool);
222 }
223
svn_swig_pl_objs_to_hash_of_revnum_t(SV * source,apr_pool_t * pool)224 apr_hash_t *svn_swig_pl_objs_to_hash_of_revnum_t(SV *source,
225 apr_pool_t *pool)
226 {
227
228 return svn_swig_pl_to_hash(source,
229 (pl_element_converter_t)convert_pl_revnum_t,
230 NULL, pool);
231 }
232
svn_swig_pl_hash_to_prophash(SV * source,apr_pool_t * pool)233 apr_hash_t *svn_swig_pl_hash_to_prophash(SV *source, apr_pool_t *pool)
234 {
235 return svn_swig_pl_to_hash(source, convert_pl_svn_string_t, NULL, pool);
236 }
237
238 /* perl -> c array convertors */
svn_swig_pl_to_array(SV * source,pl_element_converter_t cv,void * ctx,apr_pool_t * pool)239 static apr_array_header_t *svn_swig_pl_to_array(SV *source,
240 pl_element_converter_t cv,
241 void *ctx, apr_pool_t *pool)
242 {
243 int targlen;
244 apr_array_header_t *temp;
245 AV* array;
246
247 if (SvROK(source) && SvTYPE(SvRV(source)) == SVt_PVAV) {
248 array = (AV *)SvRV(source);
249 targlen = av_len(array) + 1;
250 temp = apr_array_make(pool, targlen, sizeof(const char *));
251 temp->nelts = targlen;
252
253 while (targlen--) {
254 /* more error handling here */
255 SV **item = av_fetch(array, targlen, 0);
256 APR_ARRAY_IDX(temp, targlen, const char *) = cv(*item, ctx, pool);
257 }
258 } else if (SvOK(source)) {
259 targlen = 1;
260 temp = apr_array_make(pool, targlen, sizeof(const char *));
261 temp->nelts = targlen;
262 APR_ARRAY_IDX(temp, 0, const char *) = cv(source, ctx, pool);
263 } else {
264 croak("Must pass a single value or an array reference");
265 }
266
267 return temp;
268 }
269
svn_swig_pl_strings_to_array(SV * source,apr_pool_t * pool)270 apr_array_header_t *svn_swig_pl_strings_to_array(SV *source,
271 apr_pool_t *pool)
272 {
273 return svn_swig_pl_to_array(source, convert_pl_string, NULL, pool);
274 }
275
svn_swig_pl_objs_to_array(SV * source,swig_type_info * tinfo,apr_pool_t * pool)276 apr_array_header_t *svn_swig_pl_objs_to_array(SV *source,
277 swig_type_info *tinfo,
278 apr_pool_t *pool)
279 {
280 return svn_swig_pl_to_array(source,
281 (pl_element_converter_t)convert_pl_obj,
282 tinfo, pool);
283 }
284
285 /* Convert a single revision range or an array of revisions ranges
286 * Note: We can't simply use svn_swig_pl_to_array() as is, since
287 * it immediatley checks whether source is an array reference and then
288 * proceeds to treat this as the "array of ..." case. But a revision range
289 * may be specified as a (two-element) array. Hence we first try to
290 * convert source as a single revision range. Failing that and if it's
291 * an array we then call svn_swig_pl_to_array(). Otherwise we croak().
292 */
svn_swig_pl_array_to_apr_array_revision_range(SV * source,apr_pool_t * pool)293 apr_array_header_t *svn_swig_pl_array_to_apr_array_revision_range(
294 SV *source, apr_pool_t *pool)
295 {
296 svn_boolean_t croak_on_error = FALSE;
297 svn_opt_revision_range_t *range;
298
299 if ((range = convert_pl_revision_range(source, &croak_on_error, pool))) {
300 apr_array_header_t *temp = apr_array_make(pool, 1,
301 sizeof(svn_opt_revision_range_t *));
302 temp->nelts = 1;
303 APR_ARRAY_IDX(temp, 0, svn_opt_revision_range_t *) = range;
304 return temp;
305 }
306
307 if (SvROK(source) && SvTYPE(SvRV(source)) == SVt_PVAV) {
308 croak_on_error = TRUE;
309 return svn_swig_pl_to_array(source, convert_pl_revision_range,
310 &croak_on_error, pool);
311 }
312
313 croak("must pass a single revision range or a reference to an array of revision ranges");
314
315 /* This return is actually unreachable because of the croak above,
316 * however, Visual Studio's compiler doesn't like if all paths don't have
317 * a return and errors out otherwise. */
318 return NULL;
319 }
320
321 /* element convertors for c -> perl */
322 typedef SV *(*element_converter_t)(void *value, void *ctx);
323
convert_string(const char * value,void * dummy)324 static SV *convert_string(const char *value, void *dummy)
325 {
326 SV *obj = sv_2mortal(newSVpv(value, 0));
327 return obj;
328 }
329
convert_svn_string_t(svn_string_t * value,void * dummy)330 static SV *convert_svn_string_t(svn_string_t *value, void *dummy)
331 {
332 SV *obj = sv_2mortal(newSVpv(value->data, value->len));
333 return obj;
334 }
335
convert_to_swig_type(void * ptr,swig_type_info * tinfo)336 static SV *convert_to_swig_type(void *ptr, swig_type_info *tinfo)
337 {
338 SV *obj = sv_newmortal();
339 SWIG_MakePtr(obj, ptr, tinfo, 0);
340 return obj;
341 }
342
convert_int(int value,void * dummy)343 static SV *convert_int(int value, void *dummy)
344 {
345 return sv_2mortal(newSViv(value));
346 }
347
convert_svn_revnum_t(svn_revnum_t revnum,void * dummy)348 static SV *convert_svn_revnum_t(svn_revnum_t revnum, void *dummy)
349 {
350 return sv_2mortal(newSViv((long int)revnum));
351
352 }
353
354 /* c -> perl hash convertors */
convert_hash(apr_hash_t * hash,element_converter_t converter_func,void * ctx)355 static SV *convert_hash(apr_hash_t *hash, element_converter_t converter_func,
356 void *ctx)
357 {
358 apr_hash_index_t *hi;
359 HV *hv;
360
361 hv = newHV();
362 for (hi = apr_hash_first(NULL, hash); hi; hi = apr_hash_next(hi)) {
363 const char *key;
364 void *val;
365 int klen;
366 SV *obj;
367
368 apr_hash_this(hi, (void *)&key, NULL, &val);
369 klen = strlen(key);
370
371 obj = converter_func(val, ctx);
372 hv_store(hv, (const char *)key, klen, obj, 0);
373 SvREFCNT_inc(obj);
374 }
375
376 return sv_2mortal(newRV_noinc((SV*)hv));
377 }
378
svn_swig_pl_prophash_to_hash(apr_hash_t * hash)379 SV *svn_swig_pl_prophash_to_hash(apr_hash_t *hash)
380 {
381 return convert_hash(hash, (element_converter_t)convert_svn_string_t,
382 NULL);
383 }
384
svn_swig_pl_convert_hash(apr_hash_t * hash,swig_type_info * tinfo)385 SV *svn_swig_pl_convert_hash(apr_hash_t *hash, swig_type_info *tinfo)
386 {
387 return convert_hash(hash, (element_converter_t)convert_to_swig_type,
388 tinfo);
389 }
390
391 /* c -> perl array convertors */
convert_array(const apr_array_header_t * array,element_converter_t converter_func,void * ctx)392 static SV *convert_array(const apr_array_header_t *array,
393 element_converter_t converter_func, void *ctx)
394 {
395 AV *list = newAV();
396 int i;
397
398 for (i = 0; i < array->nelts; ++i) {
399 void *element = APR_ARRAY_IDX(array, i, void *);
400 SV *item = converter_func(element, ctx);
401 av_push(list, item);
402 SvREFCNT_inc(item);
403 }
404 return sv_2mortal(newRV_noinc((SV*)list));
405 }
406
svn_swig_pl_array_to_list(const apr_array_header_t * array)407 SV *svn_swig_pl_array_to_list(const apr_array_header_t *array)
408 {
409 return convert_array(array, (element_converter_t)convert_string, NULL);
410 }
411
412 /* Formerly used by pre-1.0 APIs. Now unused
413 SV *svn_swig_pl_ints_to_list(const apr_array_header_t *array)
414 {
415 return convert_array (array, (element_converter_t)convert_int, NULL);
416 }
417 */
418
svn_swig_pl_convert_array(const apr_array_header_t * array,swig_type_info * tinfo)419 SV *svn_swig_pl_convert_array(const apr_array_header_t *array,
420 swig_type_info *tinfo)
421 {
422 return convert_array(array, (element_converter_t)convert_to_swig_type,
423 tinfo);
424 }
425
svn_swig_pl_revnums_to_list(const apr_array_header_t * array)426 SV *svn_swig_pl_revnums_to_list(const apr_array_header_t *array)
427 {
428 return convert_array(array, (element_converter_t)convert_svn_revnum_t,
429 NULL);
430 }
431
432 /* perl -> c svn_opt_revision_t conversion */
svn_swig_pl_set_revision(svn_opt_revision_t * rev,SV * source,svn_boolean_t croak_on_error,apr_pool_t * pool)433 svn_opt_revision_t *svn_swig_pl_set_revision(svn_opt_revision_t *rev,
434 SV *source,
435 svn_boolean_t croak_on_error,
436 apr_pool_t *pool)
437 {
438 #define maybe_croak(argv) do { if (croak_on_error) croak argv; \
439 else return NULL; } while (0)
440
441 if (source == NULL || source == &PL_sv_undef || !SvOK(source)) {
442 rev->kind = svn_opt_revision_unspecified;
443 }
444 else if (sv_isobject(source) && sv_derived_from(source, "_p_svn_opt_revision_t")) {
445 /* this will assign to rev */
446 SWIG_ConvertPtr(source, (void **)&rev, _SWIG_TYPE("svn_opt_revision_t *"), 0);
447 }
448 else if (looks_like_number(source)) {
449 rev->kind = svn_opt_revision_number;
450 rev->value.number = SvIV(source);
451 }
452 else if (SvPOK(source)) {
453 char *input = SvPV_nolen(source);
454 if (svn_cstring_casecmp(input, "BASE") == 0)
455 rev->kind = svn_opt_revision_base;
456 else if (svn_cstring_casecmp(input, "HEAD") == 0)
457 rev->kind = svn_opt_revision_head;
458 else if (svn_cstring_casecmp(input, "WORKING") == 0)
459 rev->kind = svn_opt_revision_working;
460 else if (svn_cstring_casecmp(input, "COMMITTED") == 0)
461 rev->kind = svn_opt_revision_committed;
462 else if (svn_cstring_casecmp(input, "PREV") == 0)
463 rev->kind = svn_opt_revision_previous;
464 else if (*input == '{') {
465 svn_boolean_t matched;
466 apr_time_t tm;
467 svn_error_t *err;
468
469 char *end = strchr(input,'}');
470 char saved_end;
471 if (!end)
472 maybe_croak(("unknown opt_revision_t string \"%s\": "
473 "missing closing brace for \"{DATE}\"", input));
474 saved_end = *end;
475 *end = '\0';
476 err = svn_parse_date (&matched, &tm,
477 input + 1, apr_time_now(), pool);
478 *end = saved_end;
479 if (err) {
480 svn_error_clear (err);
481 maybe_croak(("unknown opt_revision_t string \"%s\": "
482 "internal svn_parse_date error", input));
483 }
484 if (!matched)
485 maybe_croak(("unknown opt_revision_t string \"%s\": "
486 "svn_parse_date failed to parse it", input));
487
488 rev->kind = svn_opt_revision_date;
489 rev->value.date = tm;
490 } else
491 maybe_croak(("unknown opt_revision_t string \"%s\": must be one of "
492 "\"BASE\", \"HEAD\", \"WORKING\", \"COMMITTED\", "
493 "\"PREV\" or a \"{DATE}\"", input));
494 } else
495 maybe_croak(("unknown opt_revision_t type: must be undef, a number, "
496 "a string (one of \"BASE\", \"HEAD\", \"WORKING\", "
497 "\"COMMITTED\", \"PREV\" or a \"{DATE}\") "
498 "or a _p_svn_opt_revision_t object"));
499
500 return rev;
501 #undef maybe_croak
502 }
503
504 /* put the va_arg in stack and invoke caller_func with func.
505 fmt:
506 * O: perl object
507 * i: apr_int32_t
508 * u: apr_uint32_t
509 * L: apr_int64_t
510 * U: apr_uint64_t
511 * s: string
512 * S: swigtype
513 * r: svn_revnum_t
514 * b: svn_boolean_t
515 * t: svn_string_t
516 * z: apr_size_t
517
518 Please do not add C types here. Add a new format code if needed.
519 Using the underlying C types and not the APR or SVN types can break
520 things if these data types change in the future or on platforms which
521 use different types.
522
523 put returned value in result if result is not NULL
524 */
525
526 /* NOTE: calls back into Perl (directly) */
svn_swig_pl_callback_thunk(perl_func_invoker_t caller_func,void * func,SV ** result,const char * fmt,...)527 svn_error_t *svn_swig_pl_callback_thunk(perl_func_invoker_t caller_func,
528 void *func,
529 SV **result,
530 const char *fmt, ...)
531 {
532 const char *fp = fmt;
533 va_list ap;
534 int count;
535 I32 call_flags = result ? G_SCALAR : (G_VOID & G_DISCARD);
536
537 dSP ;
538 ENTER ;
539 SAVETMPS ;
540
541 PUSHMARK(SP) ;
542
543 va_start(ap, fmt);
544 while (*fp) {
545 char *c;
546 void *o;
547 SV *obj;
548 swig_type_info *t;
549 svn_string_t *str;
550
551 switch (*fp++) {
552 case 'O':
553 XPUSHs(va_arg(ap, SV *));
554 break;
555 case 'S': /* swig object */
556 o = va_arg(ap, void *);
557 t = va_arg(ap, swig_type_info *);
558
559 obj = sv_newmortal();
560 SWIG_MakePtr(obj, o, t, 0);
561 XPUSHs(obj);
562 break;
563
564 case 's': /* string */
565 c = va_arg(ap, char *);
566 XPUSHs(c ? sv_2mortal(newSVpv(c, 0)) : &PL_sv_undef);
567 break;
568
569 case 'i': /* apr_int32_t */
570 XPUSHs(sv_2mortal(newSViv(va_arg(ap, apr_int32_t))));
571 break;
572
573 case 'u': /* apr_uint32_t */
574 XPUSHs(sv_2mortal(newSViv(va_arg(ap, apr_uint32_t))));
575 break;
576
577 case 'r': /* svn_revnum_t */
578 XPUSHs(sv_2mortal(newSViv(va_arg(ap, svn_revnum_t))));
579 break;
580
581 case 'b': /* svn_boolean_t */
582 XPUSHs(sv_2mortal(newSViv(va_arg(ap, svn_boolean_t))));
583 break;
584
585 case 't': /* svn_string_t */
586 str = va_arg(ap, svn_string_t *);
587 XPUSHs(str ? sv_2mortal(newSVpv(str->data, str->len))
588 : &PL_sv_undef);
589 break;
590
591 case 'L': /* apr_int64_t */
592 /* Pass into perl as a string because some implementations may
593 * not be able to handle a 64-bit int. If it's too long to
594 * fit in Perl's interal IV size then perl will only make
595 * it available as a string. If not then perl will convert
596 * it to an IV for us. So this handles the problem gracefully */
597 c = malloc(30);
598 snprintf(c,30,"%" APR_INT64_T_FMT,va_arg(ap, apr_int64_t));
599 XPUSHs(sv_2mortal(newSVpv(c, 0)));
600 free(c);
601 break;
602
603 case 'U': /* apr_uint64_t */
604 c = malloc(30);
605 snprintf(c,30,"%" APR_UINT64_T_FMT,va_arg(ap, apr_uint64_t));
606 XPUSHs(sv_2mortal(newSVpv(c, 0)));
607 free(c);
608 break;
609
610 case 'z': /* apr_size_t */
611 if (sizeof(apr_size_t) >= 8)
612 {
613 c = malloc(30);
614 snprintf(c,30,"%" APR_SIZE_T_FMT,va_arg(ap, apr_size_t));
615 XPUSHs(sv_2mortal(newSVpv(c, 0)));
616 free(c);
617 }
618 else
619 {
620 XPUSHs(sv_2mortal(newSViv(va_arg(ap, apr_size_t))));
621 }
622 break;
623 }
624 }
625
626 va_end(ap);
627
628 PUTBACK;
629 switch (caller_func) {
630 case CALL_SV:
631 count = call_sv(func, call_flags );
632 break;
633 case CALL_METHOD:
634 count = call_method(func, call_flags );
635 break;
636 default:
637 croak("unkonwn calling type");
638 break;
639 }
640 SPAGAIN ;
641
642 if (((call_flags & G_SCALAR) && count != 1) ||
643 ((call_flags & G_VOID) && count != 0))
644 croak("Wrong number of returns");
645
646 if (result) {
647 *result = POPs;
648 SvREFCNT_inc(*result);
649 }
650
651 PUTBACK;
652 FREETMPS ;
653 LEAVE ;
654
655 return SVN_NO_ERROR;
656 }
657
658 /*** Editor Wrapping ***/
659
660 /* this could be more perlish */
661 typedef struct item_baton {
662 SV *editor; /* the editor handling the callbacks */
663 SV *baton; /* the dir/file baton (or NULL for edit baton) */
664 } item_baton;
665
make_baton(apr_pool_t * pool,SV * editor,SV * baton)666 static item_baton * make_baton(apr_pool_t *pool,
667 SV *editor, SV *baton)
668 {
669 item_baton *newb = apr_palloc(pool, sizeof(*newb));
670
671 newb->editor = editor;
672 newb->baton = baton;
673
674 return newb;
675 }
676
677 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
close_baton(void * baton,const char * method,apr_pool_t * pool)678 static svn_error_t * close_baton(void *baton, const char *method, apr_pool_t *pool)
679 {
680 item_baton *ib = baton;
681
682 if (ib->baton) {
683 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD,
684 (void *)method, NULL,
685 "OOS", ib->editor, ib->baton,
686 pool, POOLINFO));
687 SvREFCNT_dec(ib->baton);
688 }
689 else {
690 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD,
691 (void *)method, NULL,
692 "OS", ib->editor, pool, POOLINFO));
693 }
694
695 return SVN_NO_ERROR;
696 }
697
698 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
thunk_set_target_revision(void * edit_baton,svn_revnum_t target_revision,apr_pool_t * pool)699 static svn_error_t * thunk_set_target_revision(void *edit_baton,
700 svn_revnum_t target_revision,
701 apr_pool_t *pool)
702 {
703 item_baton *ib = edit_baton;
704
705 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD,
706 (void *)"set_target_revision", NULL,
707 "Or", ib->editor, target_revision));
708
709 return SVN_NO_ERROR;
710 }
711
712 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
thunk_open_root(void * edit_baton,svn_revnum_t base_revision,apr_pool_t * dir_pool,void ** root_baton)713 static svn_error_t * thunk_open_root(void *edit_baton,
714 svn_revnum_t base_revision,
715 apr_pool_t *dir_pool,
716 void **root_baton)
717 {
718 item_baton *ib = edit_baton;
719 SV *result;
720
721 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD,
722 (void *)"open_root", &result,
723 "OrS", ib->editor, base_revision,
724 dir_pool, POOLINFO));
725
726 *root_baton = make_baton(dir_pool, ib->editor, result);
727 return SVN_NO_ERROR;
728 }
729
730 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
thunk_delete_entry(const char * path,svn_revnum_t revision,void * parent_baton,apr_pool_t * pool)731 static svn_error_t * thunk_delete_entry(const char *path,
732 svn_revnum_t revision,
733 void *parent_baton,
734 apr_pool_t *pool)
735 {
736 item_baton *ib = parent_baton;
737
738 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD,
739 (void *)"delete_entry", NULL,
740 "OsrOS", ib->editor, path, revision,
741 ib->baton, pool, POOLINFO));
742 return SVN_NO_ERROR;
743 }
744
745 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
thunk_add_directory(const char * path,void * parent_baton,const char * copyfrom_path,svn_revnum_t copyfrom_revision,apr_pool_t * dir_pool,void ** child_baton)746 static svn_error_t * thunk_add_directory(const char *path,
747 void *parent_baton,
748 const char *copyfrom_path,
749 svn_revnum_t copyfrom_revision,
750 apr_pool_t *dir_pool,
751 void **child_baton)
752 {
753 item_baton *ib = parent_baton;
754 SV *result;
755
756 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD,
757 (void *)"add_directory", &result,
758 "OsOsrS", ib->editor, path, ib->baton,
759 copyfrom_path, copyfrom_revision,
760 dir_pool, POOLINFO));
761 *child_baton = make_baton(dir_pool, ib->editor, result);
762 return SVN_NO_ERROR;
763 }
764
765 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
thunk_open_directory(const char * path,void * parent_baton,svn_revnum_t base_revision,apr_pool_t * dir_pool,void ** child_baton)766 static svn_error_t * thunk_open_directory(const char *path,
767 void *parent_baton,
768 svn_revnum_t base_revision,
769 apr_pool_t *dir_pool,
770 void **child_baton)
771 {
772 item_baton *ib = parent_baton;
773 SV *result;
774
775 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD,
776 (void *)"open_directory", &result,
777 "OsOrS", ib->editor, path, ib->baton,
778 base_revision, dir_pool, POOLINFO));
779
780 *child_baton = make_baton(dir_pool, ib->editor, result);
781
782 return SVN_NO_ERROR;
783 }
784
785 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
thunk_change_dir_prop(void * dir_baton,const char * name,const svn_string_t * value,apr_pool_t * pool)786 static svn_error_t * thunk_change_dir_prop(void *dir_baton,
787 const char *name,
788 const svn_string_t *value,
789 apr_pool_t *pool)
790 {
791 item_baton *ib = dir_baton;
792
793 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD,
794 (void *)"change_dir_prop", NULL,
795 "OOstS", ib->editor, ib->baton, name,
796 value, pool, POOLINFO));
797
798 return SVN_NO_ERROR;
799 }
800
801 /* NOTE: calls back into Perl (by calling close_baton) */
thunk_close_directory(void * dir_baton,apr_pool_t * pool)802 static svn_error_t * thunk_close_directory(void *dir_baton,
803 apr_pool_t *pool)
804 {
805 return close_baton(dir_baton, "close_directory", pool);
806 }
807
808 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
thunk_absent_directory(const char * path,void * parent_baton,apr_pool_t * pool)809 static svn_error_t * thunk_absent_directory(const char *path,
810 void *parent_baton,
811 apr_pool_t *pool)
812 {
813 item_baton *ib = parent_baton;
814
815 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD,
816 (void *)"absent_directory", NULL,
817 "OsOS", ib->editor, path, ib->baton,
818 pool, POOLINFO));
819
820 return SVN_NO_ERROR;
821 }
822
823 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
thunk_add_file(const char * path,void * parent_baton,const char * copyfrom_path,svn_revnum_t copyfrom_revision,apr_pool_t * file_pool,void ** file_baton)824 static svn_error_t * thunk_add_file(const char *path,
825 void *parent_baton,
826 const char *copyfrom_path,
827 svn_revnum_t copyfrom_revision,
828 apr_pool_t *file_pool,
829 void **file_baton)
830 {
831 item_baton *ib = parent_baton;
832 SV *result;
833
834 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD,
835 (void *)"add_file", &result,
836 "OsOsrS", ib->editor, path, ib->baton,
837 copyfrom_path, copyfrom_revision,
838 file_pool, POOLINFO));
839
840 *file_baton = make_baton(file_pool, ib->editor, result);
841 return SVN_NO_ERROR;
842 }
843
844 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
thunk_open_file(const char * path,void * parent_baton,svn_revnum_t base_revision,apr_pool_t * file_pool,void ** file_baton)845 static svn_error_t * thunk_open_file(const char *path,
846 void *parent_baton,
847 svn_revnum_t base_revision,
848 apr_pool_t *file_pool,
849 void **file_baton)
850 {
851 item_baton *ib = parent_baton;
852 SV *result;
853
854 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD,
855 (void *)"open_file", &result,
856 "OsOrS", ib->editor, path, ib->baton,
857 base_revision, file_pool, POOLINFO));
858
859 *file_baton = make_baton(file_pool, ib->editor, result);
860 return SVN_NO_ERROR;
861 }
862
863 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
thunk_window_handler(svn_txdelta_window_t * window,void * baton)864 static svn_error_t * thunk_window_handler(svn_txdelta_window_t *window,
865 void *baton)
866 {
867 SV *handler = baton;
868
869 if (window == NULL) {
870 SVN_ERR(svn_swig_pl_callback_thunk(CALL_SV,
871 handler, NULL, "O",
872 &PL_sv_undef));
873 SvREFCNT_dec(handler);
874 }
875 else {
876 swig_type_info *tinfo = _SWIG_TYPE("svn_txdelta_window_t *");
877 SVN_ERR(svn_swig_pl_callback_thunk(CALL_SV, handler,
878 NULL, "S", window, tinfo));
879 }
880
881 return SVN_NO_ERROR;
882 }
883
884 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
885 static svn_error_t *
thunk_apply_textdelta(void * file_baton,const char * base_checksum,apr_pool_t * pool,svn_txdelta_window_handler_t * handler,void ** h_baton)886 thunk_apply_textdelta(void *file_baton,
887 const char *base_checksum,
888 apr_pool_t *pool,
889 svn_txdelta_window_handler_t *handler,
890 void **h_baton)
891 {
892 item_baton *ib = file_baton;
893 SV *result;
894
895 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD,
896 (void *)"apply_textdelta", &result,
897 "OOsS", ib->editor, ib->baton,
898 base_checksum, pool, POOLINFO));
899 if (SvOK(result)) {
900 if (SvROK(result) && SvTYPE(SvRV(result)) == SVt_PVAV) {
901 swig_type_info *handler_info =
902 _SWIG_TYPE("svn_txdelta_window_handler_t");
903 swig_type_info *void_info = _SWIG_TYPE("void *");
904 AV *array = (AV *)SvRV(result);
905
906 if (SWIG_ConvertPtr(*av_fetch(array, 0, 0),
907 (void **)handler, handler_info,0) < 0) {
908 croak("Unable to convert from SWIG Type");
909 }
910 if (SWIG_ConvertPtr(*av_fetch(array, 1, 0),
911 h_baton, void_info,0) < 0) {
912 croak("Unable to convert from SWIG Type ");
913 }
914 SvREFCNT_dec(result);
915 }
916 else {
917 *handler = thunk_window_handler;
918 *h_baton = result;
919 }
920 }
921 else {
922 *handler = svn_delta_noop_window_handler;
923 *h_baton = NULL;
924 }
925
926 return SVN_NO_ERROR;
927 }
928
929 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
thunk_change_file_prop(void * file_baton,const char * name,const svn_string_t * value,apr_pool_t * pool)930 static svn_error_t * thunk_change_file_prop(void *file_baton,
931 const char *name,
932 const svn_string_t *value,
933 apr_pool_t *pool)
934 {
935 item_baton *ib = file_baton;
936
937 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD,
938 (void *)"change_file_prop", NULL,
939 "OOstS", ib->editor, ib->baton, name,
940 value, pool, POOLINFO));
941
942 return SVN_NO_ERROR;
943 }
944
945 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
thunk_close_file(void * file_baton,const char * text_checksum,apr_pool_t * pool)946 static svn_error_t * thunk_close_file(void *file_baton,
947 const char *text_checksum,
948 apr_pool_t *pool)
949 {
950 item_baton *ib = file_baton;
951
952 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD,
953 (void *)"close_file", NULL, "OOsS",
954 ib->editor, ib->baton, text_checksum,
955 pool, POOLINFO));
956
957 SvREFCNT_dec(ib->baton);
958
959 return SVN_NO_ERROR;
960 }
961
962 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
thunk_absent_file(const char * path,void * parent_baton,apr_pool_t * pool)963 static svn_error_t * thunk_absent_file(const char *path,
964 void *parent_baton,
965 apr_pool_t *pool)
966 {
967 item_baton *ib = parent_baton;
968
969 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD,
970 (void *)"absent_file", NULL,
971 "OsOS", ib->editor, path, ib->baton,
972 pool, POOLINFO));
973
974 return SVN_NO_ERROR;
975 }
976
977 /* NOTE: calls back into Perl (by calling close_baton) */
thunk_close_edit(void * edit_baton,apr_pool_t * pool)978 static svn_error_t * thunk_close_edit(void *edit_baton,
979 apr_pool_t *pool)
980 {
981 return close_baton(edit_baton, "close_edit", pool);
982 }
983
984 /* NOTE: calls back into Perl (by calling close_baton) */
thunk_abort_edit(void * edit_baton,apr_pool_t * pool)985 static svn_error_t * thunk_abort_edit(void *edit_baton,
986 apr_pool_t *pool)
987 {
988 return close_baton(edit_baton, "abort_edit", pool);
989 }
990
991
svn_swig_pl_make_editor(svn_delta_editor_t ** editor,void ** edit_baton,SV * perl_editor,apr_pool_t * pool)992 void svn_swig_pl_make_editor(svn_delta_editor_t **editor,
993 void **edit_baton,
994 SV *perl_editor,
995 apr_pool_t *pool)
996 {
997 svn_delta_editor_t *thunk_editor = svn_delta_default_editor(pool);
998
999 thunk_editor->set_target_revision = thunk_set_target_revision;
1000 thunk_editor->open_root = thunk_open_root;
1001 thunk_editor->delete_entry = thunk_delete_entry;
1002 thunk_editor->add_directory = thunk_add_directory;
1003 thunk_editor->open_directory = thunk_open_directory;
1004 thunk_editor->change_dir_prop = thunk_change_dir_prop;
1005 thunk_editor->close_directory = thunk_close_directory;
1006 thunk_editor->absent_directory = thunk_absent_directory;
1007 thunk_editor->add_file = thunk_add_file;
1008 thunk_editor->open_file = thunk_open_file;
1009 thunk_editor->apply_textdelta = thunk_apply_textdelta;
1010 thunk_editor->change_file_prop = thunk_change_file_prop;
1011 thunk_editor->close_file = thunk_close_file;
1012 thunk_editor->absent_file = thunk_absent_file;
1013 thunk_editor->close_edit = thunk_close_edit;
1014 thunk_editor->abort_edit = thunk_abort_edit;
1015
1016 *editor = thunk_editor;
1017 *edit_baton = make_baton(pool, perl_editor, NULL);
1018 svn_swig_pl_hold_ref_in_pool(pool, perl_editor);
1019 }
1020
1021 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_thunk_log_receiver(void * baton,apr_hash_t * changed_paths,svn_revnum_t rev,const char * author,const char * date,const char * msg,apr_pool_t * pool)1022 svn_error_t *svn_swig_pl_thunk_log_receiver(void *baton,
1023 apr_hash_t *changed_paths,
1024 svn_revnum_t rev,
1025 const char *author,
1026 const char *date,
1027 const char *msg,
1028 apr_pool_t *pool)
1029 {
1030 SV *receiver = baton;
1031 swig_type_info *tinfo = _SWIG_TYPE("svn_log_changed_path_t *");
1032
1033 if (!SvOK(receiver))
1034 return SVN_NO_ERROR;
1035
1036 svn_swig_pl_callback_thunk(CALL_SV,
1037 receiver, NULL,
1038 "OrsssS", (changed_paths) ?
1039 svn_swig_pl_convert_hash(changed_paths, tinfo)
1040 : &PL_sv_undef,
1041 rev, author, date, msg, pool, POOLINFO);
1042
1043 return SVN_NO_ERROR;
1044 }
1045
1046 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_thunk_log_entry_receiver(void * baton,svn_log_entry_t * log_entry,apr_pool_t * pool)1047 svn_error_t *svn_swig_pl_thunk_log_entry_receiver(void *baton,
1048 svn_log_entry_t *log_entry,
1049 apr_pool_t *pool)
1050 {
1051 SV *receiver = baton;
1052
1053 if (!SvOK(receiver))
1054 return SVN_NO_ERROR;
1055
1056 svn_swig_pl_callback_thunk(CALL_SV,
1057 receiver, NULL,
1058 "SS",
1059 log_entry, _SWIG_TYPE("svn_log_entry_t *"),
1060 pool, POOLINFO);
1061
1062 return SVN_NO_ERROR;
1063 }
1064
1065 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_thunk_client_diff_summarize_func(const svn_client_diff_summarize_t * diff,void * baton,apr_pool_t * pool)1066 svn_error_t * svn_swig_pl_thunk_client_diff_summarize_func(
1067 const svn_client_diff_summarize_t *diff,
1068 void *baton,
1069 apr_pool_t *pool)
1070 {
1071 SV *func = baton;
1072
1073 if(!SvOK(func))
1074 return SVN_NO_ERROR;
1075
1076 svn_swig_pl_callback_thunk(CALL_SV,
1077 func, NULL,
1078 "SS", diff,
1079 _SWIG_TYPE("svn_client_diff_summarize_t *"),
1080 pool, POOLINFO);
1081
1082 return SVN_NO_ERROR;
1083 }
1084
1085 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_thunk_history_func(void * baton,const char * path,svn_revnum_t revision,apr_pool_t * pool)1086 svn_error_t *svn_swig_pl_thunk_history_func(void *baton,
1087 const char *path,
1088 svn_revnum_t revision,
1089 apr_pool_t *pool)
1090 {
1091 SV *func = baton;
1092
1093 if (!SvOK(func))
1094 return SVN_NO_ERROR;
1095
1096 svn_swig_pl_callback_thunk(CALL_SV,
1097 func, NULL,
1098 "srS", path, revision, pool, POOLINFO);
1099
1100 return SVN_NO_ERROR;
1101 }
1102
1103 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_thunk_authz_func(svn_boolean_t * allowed,svn_fs_root_t * root,const char * path,void * baton,apr_pool_t * pool)1104 svn_error_t *svn_swig_pl_thunk_authz_func(svn_boolean_t *allowed,
1105 svn_fs_root_t *root,
1106 const char *path,
1107 void *baton,
1108 apr_pool_t *pool)
1109 {
1110 SV *func = baton, *result;
1111
1112 if (!SvOK(func))
1113 return SVN_NO_ERROR;
1114
1115 svn_swig_pl_callback_thunk(CALL_SV,
1116 func, &result,
1117 "SsS", root, _SWIG_TYPE("svn_fs_root_t *"),
1118 path, pool, POOLINFO);
1119
1120 *allowed = SvIV(result);
1121 SvREFCNT_dec(result);
1122
1123 return SVN_NO_ERROR;
1124 }
1125
1126 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_thunk_commit_callback(svn_revnum_t new_revision,const char * date,const char * author,void * baton)1127 svn_error_t *svn_swig_pl_thunk_commit_callback(svn_revnum_t new_revision,
1128 const char *date,
1129 const char *author,
1130 void *baton)
1131 {
1132 if (!SvOK((SV *)baton))
1133 return SVN_NO_ERROR;
1134
1135 svn_swig_pl_callback_thunk(CALL_SV, baton, NULL,
1136 "rss", new_revision, date, author);
1137
1138 return SVN_NO_ERROR;
1139 }
1140
1141 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_thunk_commit_callback2(const svn_commit_info_t * commit_info,void * baton,apr_pool_t * pool)1142 svn_error_t *svn_swig_pl_thunk_commit_callback2(const svn_commit_info_t *commit_info,
1143 void *baton,
1144 apr_pool_t *pool)
1145 {
1146 if (!SvOK((SV *)baton))
1147 return SVN_NO_ERROR;
1148
1149 svn_swig_pl_callback_thunk(CALL_SV, baton, NULL,
1150 "SS",
1151 commit_info, _SWIG_TYPE("svn_commit_info_t *"),
1152 pool, POOLINFO);
1153
1154 return SVN_NO_ERROR;
1155 }
1156
1157
1158 /* Wrap RA */
1159
1160 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
thunk_open_tmp_file(apr_file_t ** fp,void * callback_baton,apr_pool_t * pool)1161 static svn_error_t * thunk_open_tmp_file(apr_file_t **fp,
1162 void *callback_baton,
1163 apr_pool_t *pool)
1164 {
1165 SV *result;
1166 swig_type_info *tinfo = _SWIG_TYPE("apr_file_t *");
1167
1168 svn_swig_pl_callback_thunk(CALL_METHOD, (void *)"open_tmp_file",
1169 &result, "OS", callback_baton, pool, POOLINFO);
1170
1171 if (SWIG_ConvertPtr(result, (void *)fp, tinfo,0) < 0) {
1172 croak("Unable to convert from SWIG Type");
1173 }
1174
1175 SvREFCNT_dec(result);
1176 return SVN_NO_ERROR;
1177 }
1178
1179 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
thunk_get_wc_prop(void * baton,const char * relpath,const char * name,const svn_string_t ** value,apr_pool_t * pool)1180 static svn_error_t *thunk_get_wc_prop(void *baton,
1181 const char *relpath,
1182 const char *name,
1183 const svn_string_t **value,
1184 apr_pool_t *pool)
1185 {
1186 SV *result;
1187 char *data;
1188 STRLEN len;
1189
1190 svn_swig_pl_callback_thunk(CALL_METHOD, (void *)"get_wc_prop",
1191 &result, "OssS", baton, relpath, name,
1192 pool, POOLINFO);
1193
1194 /* this is svn_string_t * typemap in */
1195 if (!SvOK(result) || result == &PL_sv_undef) {
1196 *value = NULL;
1197 }
1198 else if (SvPOK(result)) {
1199 data = SvPV(result, len);
1200 *value = svn_string_ncreate(data, len, pool);
1201 }
1202 else {
1203 SvREFCNT_dec(result);
1204 croak("not a string");
1205 }
1206
1207 SvREFCNT_dec(result);
1208 return SVN_NO_ERROR;
1209 }
1210
1211
svn_swig_pl_make_callbacks(svn_ra_callbacks_t ** cb,void ** c_baton,SV * perl_callbacks,apr_pool_t * pool)1212 svn_error_t *svn_swig_pl_make_callbacks(svn_ra_callbacks_t **cb,
1213 void **c_baton,
1214 SV *perl_callbacks,
1215 apr_pool_t *pool)
1216 {
1217 SV *auth_baton;
1218
1219 *cb = apr_pcalloc(pool, sizeof(**cb));
1220
1221 (*cb)->open_tmp_file = thunk_open_tmp_file;
1222 (*cb)->get_wc_prop = thunk_get_wc_prop;
1223 (*cb)->set_wc_prop = NULL;
1224 (*cb)->push_wc_prop = NULL;
1225 (*cb)->invalidate_wc_props = NULL;
1226 auth_baton = *hv_fetch((HV *)SvRV(perl_callbacks), "auth", 4, 0);
1227
1228 if (SWIG_ConvertPtr(auth_baton,
1229 (void **)&(*cb)->auth_baton, _SWIG_TYPE("svn_auth_baton_t *"),0) < 0) {
1230 croak("Unable to convert from SWIG Type");
1231 }
1232 *c_baton = perl_callbacks;
1233 svn_swig_pl_hold_ref_in_pool(pool, perl_callbacks);
1234 return SVN_NO_ERROR;
1235 }
1236
1237 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_thunk_gnome_keyring_unlock_prompt(char ** keyring_password,const char * keyring_name,void * baton,apr_pool_t * pool)1238 svn_error_t *svn_swig_pl_thunk_gnome_keyring_unlock_prompt(char **keyring_password,
1239 const char *keyring_name,
1240 void *baton,
1241 apr_pool_t *pool)
1242 {
1243 SV *result;
1244 STRLEN len;
1245 /* The baton is the actual prompt function passed from perl, so we
1246 * call that one and process the result. */
1247 svn_swig_pl_callback_thunk(CALL_SV,
1248 baton, &result,
1249 "sS", keyring_name,
1250 pool, POOLINFO);
1251 if (!SvOK(result) || result == &PL_sv_undef) {
1252 *keyring_password = NULL;
1253 }
1254 else if (SvPOK(result)) {
1255 *keyring_password = apr_pstrdup(pool, SvPV(result, len));
1256 }
1257 else {
1258 SvREFCNT_dec(result);
1259 croak("not a string");
1260 }
1261
1262 SvREFCNT_dec(result);
1263 return SVN_NO_ERROR;
1264 }
1265
1266 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_thunk_simple_prompt(svn_auth_cred_simple_t ** cred,void * baton,const char * realm,const char * username,svn_boolean_t may_save,apr_pool_t * pool)1267 svn_error_t *svn_swig_pl_thunk_simple_prompt(svn_auth_cred_simple_t **cred,
1268 void *baton,
1269 const char *realm,
1270 const char *username,
1271 svn_boolean_t may_save,
1272 apr_pool_t *pool)
1273 {
1274 /* Be nice and allocate the memory for the cred structure before passing it
1275 * off to the perl space */
1276 *cred = apr_pcalloc(pool, sizeof(**cred));
1277 if (!*cred) {
1278 croak("Could not allocate memory for cred structure");
1279 }
1280 svn_swig_pl_callback_thunk(CALL_SV,
1281 baton, NULL,
1282 "SssbS", *cred, _SWIG_TYPE("svn_auth_cred_simple_t *"),
1283 realm, username, may_save, pool, POOLINFO);
1284
1285 return SVN_NO_ERROR;
1286 }
1287
1288 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_thunk_username_prompt(svn_auth_cred_username_t ** cred,void * baton,const char * realm,svn_boolean_t may_save,apr_pool_t * pool)1289 svn_error_t *svn_swig_pl_thunk_username_prompt(svn_auth_cred_username_t **cred,
1290 void *baton,
1291 const char *realm,
1292 svn_boolean_t may_save,
1293 apr_pool_t *pool)
1294 {
1295 /* Be nice and allocate the memory for the cred structure before passing it
1296 * off to the perl space */
1297 *cred = apr_pcalloc(pool, sizeof(**cred));
1298 if (!*cred) {
1299 croak("Could not allocate memory for cred structure");
1300 }
1301 svn_swig_pl_callback_thunk(CALL_SV,
1302 baton, NULL,
1303 "SsbS", *cred, _SWIG_TYPE("svn_auth_cred_username_t *"),
1304 realm, may_save, pool, POOLINFO);
1305
1306 return SVN_NO_ERROR;
1307 }
1308
1309 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_thunk_ssl_server_trust_prompt(svn_auth_cred_ssl_server_trust_t ** cred,void * baton,const char * realm,apr_uint32_t failures,const svn_auth_ssl_server_cert_info_t * cert_info,svn_boolean_t may_save,apr_pool_t * pool)1310 svn_error_t *svn_swig_pl_thunk_ssl_server_trust_prompt(
1311 svn_auth_cred_ssl_server_trust_t **cred,
1312 void *baton,
1313 const char *realm,
1314 apr_uint32_t failures,
1315 const svn_auth_ssl_server_cert_info_t *cert_info,
1316 svn_boolean_t may_save,
1317 apr_pool_t *pool)
1318 {
1319 /* Be nice and allocate the memory for the cred structure before passing it
1320 * off to the perl space */
1321 *cred = apr_pcalloc(pool, sizeof(**cred));
1322 if (!*cred) {
1323 croak("Could not allocate memory for cred structure");
1324 }
1325 svn_swig_pl_callback_thunk(CALL_SV,
1326 baton, NULL,
1327 "SsiSbS", *cred, _SWIG_TYPE("svn_auth_cred_ssl_server_trust_t *"),
1328 realm, failures,
1329 cert_info, _SWIG_TYPE("svn_auth_ssl_server_cert_info_t *"),
1330 may_save, pool, POOLINFO);
1331
1332 /* Allow the perl callback to indicate failure by setting all vars to 0
1333 * or by simply doing nothing. While still allowing them to indicate
1334 * failure by setting the cred strucutre's pointer to 0 via $$cred = 0 */
1335 if (*cred) {
1336 if ((*cred)->may_save == 0 && (*cred)->accepted_failures == 0) {
1337 *cred = NULL;
1338 }
1339 }
1340
1341 return SVN_NO_ERROR;
1342 }
1343
1344 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_thunk_ssl_client_cert_prompt(svn_auth_cred_ssl_client_cert_t ** cred,void * baton,const char * realm,svn_boolean_t may_save,apr_pool_t * pool)1345 svn_error_t *svn_swig_pl_thunk_ssl_client_cert_prompt(
1346 svn_auth_cred_ssl_client_cert_t **cred,
1347 void *baton,
1348 const char * realm,
1349 svn_boolean_t may_save,
1350 apr_pool_t *pool)
1351 {
1352 /* Be nice and allocate the memory for the cred structure before passing it
1353 * off to the perl space */
1354 *cred = apr_pcalloc(pool, sizeof(**cred));
1355 if (!*cred) {
1356 croak("Could not allocate memory for cred structure");
1357 }
1358 svn_swig_pl_callback_thunk(CALL_SV,
1359 baton, NULL,
1360 "SsbS", *cred, _SWIG_TYPE("svn_auth_cred_ssl_client_cert_t *"),
1361 realm, may_save, pool, POOLINFO);
1362
1363 return SVN_NO_ERROR;
1364 }
1365
1366 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_thunk_ssl_client_cert_pw_prompt(svn_auth_cred_ssl_client_cert_pw_t ** cred,void * baton,const char * realm,svn_boolean_t may_save,apr_pool_t * pool)1367 svn_error_t *svn_swig_pl_thunk_ssl_client_cert_pw_prompt(
1368 svn_auth_cred_ssl_client_cert_pw_t **cred,
1369 void *baton,
1370 const char *realm,
1371 svn_boolean_t may_save,
1372 apr_pool_t *pool)
1373 {
1374 /* Be nice and allocate the memory for the cred structure before passing it
1375 * off to the perl space */
1376 *cred = apr_pcalloc(pool, sizeof(**cred));
1377 if (!*cred) {
1378 croak("Could not allocate memory for cred structure");
1379 }
1380 svn_swig_pl_callback_thunk(CALL_SV,
1381 baton, NULL,
1382 "SsbS", *cred, _SWIG_TYPE("svn_auth_cred_ssl_client_cert_pw_t *"),
1383 realm, may_save, pool, POOLINFO);
1384
1385 return SVN_NO_ERROR;
1386 }
1387
1388 /* Thunked version of svn_wc_notify_func_t callback type */
1389 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_notify_func(void * baton,const char * path,svn_wc_notify_action_t action,svn_node_kind_t kind,const char * mime_type,svn_wc_notify_state_t content_state,svn_wc_notify_state_t prop_state,svn_revnum_t revision)1390 void svn_swig_pl_notify_func(void * baton,
1391 const char *path,
1392 svn_wc_notify_action_t action,
1393 svn_node_kind_t kind,
1394 const char *mime_type,
1395 svn_wc_notify_state_t content_state,
1396 svn_wc_notify_state_t prop_state,
1397 svn_revnum_t revision)
1398 {
1399 if (!SvOK((SV *)baton)) {
1400 return;
1401 }
1402
1403 svn_swig_pl_callback_thunk(CALL_SV,
1404 baton, NULL,
1405 "siisiir", path, action, kind, mime_type,
1406 content_state, prop_state, revision);
1407
1408 }
1409
1410 /* Thunked version of svn_client_get_commit_log3_t callback type. */
1411 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_get_commit_log_func(const char ** log_msg,const char ** tmp_file,const apr_array_header_t * commit_items,void * baton,apr_pool_t * pool)1412 svn_error_t *svn_swig_pl_get_commit_log_func(const char **log_msg,
1413 const char **tmp_file,
1414 const apr_array_header_t *
1415 commit_items,
1416 void *baton,
1417 apr_pool_t *pool)
1418 {
1419 SV *result;
1420 svn_error_t *ret_val = SVN_NO_ERROR;
1421 SV *log_msg_sv;
1422 SV *tmp_file_sv;
1423 SV *commit_items_sv;
1424
1425 if (!SvOK((SV *)baton)) {
1426 *log_msg = apr_pstrdup(pool, "");
1427 *tmp_file = NULL;
1428 return SVN_NO_ERROR;
1429 }
1430
1431 log_msg_sv = newRV_noinc(sv_newmortal());
1432 tmp_file_sv = newRV_noinc(sv_newmortal());
1433 commit_items_sv = svn_swig_pl_convert_array
1434 (commit_items, _SWIG_TYPE("svn_client_commit_item3_t *"));
1435
1436 svn_swig_pl_callback_thunk(CALL_SV,
1437 baton, &result,
1438 "OOOS", log_msg_sv, tmp_file_sv,
1439 commit_items_sv, pool, POOLINFO);
1440
1441 if (!SvOK(SvRV(log_msg_sv))) {
1442 /* client returned undef to us */
1443 *log_msg = NULL;
1444 } else if (SvPOK(SvRV(log_msg_sv))) {
1445 /* client returned string so get the string and then duplicate
1446 * it using pool memory */
1447 *log_msg = apr_pstrdup(pool, SvPV_nolen(SvRV(log_msg_sv)));
1448 } else {
1449 croak("Invalid value in log_msg reference, must be undef or a string");
1450 }
1451
1452 if (!SvOK(SvRV(tmp_file_sv))) {
1453 *tmp_file = NULL;
1454 } else if (SvPOK(SvRV(tmp_file_sv))) {
1455 *tmp_file = apr_pstrdup(pool, SvPV_nolen(SvRV(tmp_file_sv)));
1456 } else {
1457 croak("Invalid value in tmp_file reference, "
1458 "must be undef or a string");
1459 }
1460
1461 if (sv_derived_from(result, "_p_svn_error_t")) {
1462 swig_type_info *errorinfo = _SWIG_TYPE("svn_error_t *");
1463 if (SWIG_ConvertPtr(result, (void *)&ret_val, errorinfo, 0) < 0) {
1464 SvREFCNT_dec(result);
1465 croak("Unable to convert from SWIG Type");
1466 }
1467 }
1468
1469 SvREFCNT_dec(result);
1470 return ret_val;
1471 }
1472
1473 /* Thunked version of svn_client_info_t callback type. */
1474 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_info_receiver(void * baton,const char * path,const svn_info_t * info,apr_pool_t * pool)1475 svn_error_t *svn_swig_pl_info_receiver(void *baton,
1476 const char *path,
1477 const svn_info_t *info,
1478 apr_pool_t *pool)
1479 {
1480 SV *result;
1481 svn_error_t *ret_val;
1482 swig_type_info *infoinfo = _SWIG_TYPE("svn_info_t *");
1483
1484 if (!SvOK((SV *)baton))
1485 return SVN_NO_ERROR;
1486
1487 svn_swig_pl_callback_thunk(CALL_SV, baton, &result, "sSS", path, info,
1488 infoinfo, pool, POOLINFO);
1489
1490 if (sv_derived_from(result, "_p_svn_error_t")) {
1491 swig_type_info *errorinfo = _SWIG_TYPE("svn_error_t *");
1492 if (SWIG_ConvertPtr(result, (void *)&ret_val, errorinfo, 0) < 0) {
1493 SvREFCNT_dec(result);
1494 croak("Unable to convert from SWIG Type");
1495 }
1496 }
1497 else
1498 ret_val = SVN_NO_ERROR;
1499
1500 SvREFCNT_dec(result);
1501 return ret_val;
1502 }
1503
1504
1505 /* Thunked version of svn_wc_cancel_func_t callback type. */
1506 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_cancel_func(void * cancel_baton)1507 svn_error_t *svn_swig_pl_cancel_func(void *cancel_baton) {
1508 SV *result;
1509 svn_error_t *ret_val;
1510
1511 if (!SvOK((SV *)cancel_baton)) {
1512 return SVN_NO_ERROR;
1513 }
1514 svn_swig_pl_callback_thunk(CALL_SV, cancel_baton, &result, "");
1515
1516 if (sv_derived_from(result,"_p_svn_error_t")) {
1517 swig_type_info *errorinfo = _SWIG_TYPE("svn_error_t *");
1518 if (SWIG_ConvertPtr(result, (void *)&ret_val, errorinfo, 0) < 0) {
1519 SvREFCNT_dec(result);
1520 croak("Unable to convert from SWIG Type");
1521 }
1522 } else if (SvIOK(result) && SvIV(result)) {
1523 ret_val = svn_error_create(SVN_ERR_CANCELLED, NULL,
1524 "By cancel callback");
1525 } else if (SvTRUE(result) && SvPOK(result)) {
1526 ret_val = svn_error_create(SVN_ERR_CANCELLED, NULL,
1527 SvPV_nolen(result));
1528 } else {
1529 ret_val = SVN_NO_ERROR;
1530 }
1531 SvREFCNT_dec(result);
1532 return ret_val;
1533 }
1534
1535 /* Thunked version of svn_wc_status_func_t callback type. */
1536 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_status_func(void * baton,const char * path,svn_wc_status_t * status)1537 void svn_swig_pl_status_func(void *baton,
1538 const char *path,
1539 svn_wc_status_t *status)
1540 {
1541 swig_type_info *statusinfo = _SWIG_TYPE("svn_wc_status_t *");
1542
1543 if (!SvOK((SV *)baton)) {
1544 return;
1545 }
1546
1547 svn_swig_pl_callback_thunk(CALL_SV, baton, NULL, "sS",
1548 path, status, statusinfo);
1549
1550 }
1551
1552 /* Thunked version of svn_wc_status_func2_t callback type. */
1553 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_status_func2(void * baton,const char * path,svn_wc_status2_t * status)1554 void svn_swig_pl_status_func2(void *baton,
1555 const char *path,
1556 svn_wc_status2_t *status)
1557 {
1558 swig_type_info *statusinfo = _SWIG_TYPE("svn_wc_status2 _t *");
1559
1560 if (!SvOK((SV *)baton)) {
1561 return;
1562 }
1563
1564 svn_swig_pl_callback_thunk(CALL_SV, baton, NULL, "sS",
1565 path, status, statusinfo);
1566
1567 }
1568
1569 /* Thunked version of svn_wc_status_func3_t callback type. */
1570 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_status_func3(void * baton,const char * path,svn_wc_status2_t * status,apr_pool_t * pool)1571 svn_error_t *svn_swig_pl_status_func3(void *baton,
1572 const char *path,
1573 svn_wc_status2_t *status,
1574 apr_pool_t *pool)
1575 {
1576 SV *result;
1577 svn_error_t *ret_val = SVN_NO_ERROR;
1578
1579 swig_type_info *statusinfo = _SWIG_TYPE("svn_wc_status2 _t *");
1580
1581 if (!SvOK((SV *)baton)) {
1582 return ret_val;
1583 }
1584
1585 svn_swig_pl_callback_thunk(CALL_SV, baton, &result, "sSS",
1586 path, status, statusinfo,
1587 pool, POOLINFO);
1588
1589 if (sv_derived_from(result, "_p_svn_error_t")) {
1590 swig_type_info *errorinfo = _SWIG_TYPE("svn_error_t *");
1591 if (SWIG_ConvertPtr(result, (void *)&ret_val, errorinfo, 0) < 0) {
1592 SvREFCNT_dec(result);
1593 croak("Unable to convert from SWIG Type");
1594 }
1595 }
1596
1597 SvREFCNT_dec(result);
1598 return ret_val;
1599 }
1600
1601
1602 /* Thunked version of svn_client_blame_receiver_t callback type. */
1603 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_blame_func(void * baton,apr_int64_t line_no,svn_revnum_t revision,const char * author,const char * date,const char * line,apr_pool_t * pool)1604 svn_error_t *svn_swig_pl_blame_func(void *baton,
1605 apr_int64_t line_no,
1606 svn_revnum_t revision,
1607 const char *author,
1608 const char *date,
1609 const char *line,
1610 apr_pool_t *pool)
1611 {
1612 SV *result;
1613 svn_error_t *ret_val = SVN_NO_ERROR;
1614
1615 svn_swig_pl_callback_thunk(CALL_SV, baton, &result, "LrsssS",
1616 line_no, revision, author, date, line,
1617 pool, POOLINFO);
1618
1619 if (sv_derived_from(result, "_p_svn_error_t")) {
1620 swig_type_info *errorinfo = _SWIG_TYPE("svn_error_t *");
1621 if (SWIG_ConvertPtr(result, (void *)&ret_val, errorinfo, 0) < 0) {
1622 SvREFCNT_dec(result);
1623 croak("Unable to convert from SWIG Type");
1624 }
1625 }
1626
1627 SvREFCNT_dec(result);
1628 return ret_val;
1629 }
1630
1631 /* Thunked config enumerator */
1632 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_thunk_config_enumerator(const char * name,const char * value,void * baton)1633 svn_boolean_t svn_swig_pl_thunk_config_enumerator(const char *name, const char *value, void *baton)
1634 {
1635 SV *result;
1636 if (!SvOK((SV *)baton))
1637 return 0;
1638
1639 svn_swig_pl_callback_thunk(CALL_SV, baton, &result,
1640 "ss", name, value);
1641
1642 return SvOK(result);
1643 }
1644
1645
1646 /* default pool support */
1647
1648 static svn_swig_pl_get_current_pool_func_t get_current_pool_cb = NULL;
1649 static svn_swig_pl_set_current_pool_func_t set_current_pool_cb = NULL;
1650
1651 void
svn_swig_pl__bind_current_pool_fns(svn_swig_pl_get_current_pool_func_t get,svn_swig_pl_set_current_pool_func_t set)1652 svn_swig_pl__bind_current_pool_fns(svn_swig_pl_get_current_pool_func_t get,
1653 svn_swig_pl_set_current_pool_func_t set)
1654 {
1655 /* This function should only be called ONCE, otherwise there are two
1656 global variables CURRENT_POOL */
1657 SVN_ERR_ASSERT_NO_RETURN(get_current_pool_cb == NULL
1658 && set_current_pool_cb == NULL);
1659
1660 get_current_pool_cb = get;
1661 set_current_pool_cb = set;
1662 }
1663
svn_swig_pl_get_current_pool()1664 apr_pool_t * svn_swig_pl_get_current_pool()
1665 {
1666 SVN_ERR_ASSERT_NO_RETURN(get_current_pool_cb != NULL);
1667 return get_current_pool_cb();
1668 }
1669
svn_swig_pl_set_current_pool(apr_pool_t * pool)1670 void svn_swig_pl_set_current_pool(apr_pool_t *pool)
1671 {
1672 SVN_ERR_ASSERT_NO_RETURN(set_current_pool_cb != NULL);
1673 set_current_pool_cb(pool);
1674 }
1675
1676 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_make_pool(SV * obj)1677 apr_pool_t *svn_swig_pl_make_pool(SV *obj)
1678 {
1679 apr_pool_t *pool;
1680
1681 if (obj && sv_isobject(obj)) {
1682 if (sv_derived_from(obj, "SVN::Pool")) {
1683 obj = SvRV(obj);
1684 }
1685 if (sv_derived_from(obj, "_p_apr_pool_t")) {
1686 SWIG_ConvertPtr(obj, (void **)&pool, POOLINFO, 0);
1687 return pool;
1688 }
1689 }
1690
1691 if (!svn_swig_pl_get_current_pool())
1692 svn_swig_pl_callback_thunk(CALL_METHOD, (void *)"new_default",
1693 &obj, "s", "SVN::Pool");
1694
1695 return svn_swig_pl_get_current_pool();
1696 }
1697
1698 /* stream interpolability with io::handle */
1699
1700 typedef struct io_baton_t {
1701 SV *obj;
1702 IO *io;
1703 } io_baton_t;
1704
1705 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
io_handle_read(void * baton,char * buffer,apr_size_t * len)1706 static svn_error_t *io_handle_read(void *baton,
1707 char *buffer,
1708 apr_size_t *len)
1709 {
1710 io_baton_t *io = baton;
1711 MAGIC *mg;
1712
1713 if ((mg = SvTIED_mg((SV*)io->io, PERL_MAGIC_tiedscalar))) {
1714 SV *ret;
1715 SV *buf = sv_newmortal();
1716
1717 svn_swig_pl_callback_thunk(CALL_METHOD, (void *)"READ", &ret, "OOz",
1718 SvTIED_obj((SV*)io->io, mg),
1719 buf, *len);
1720 *len = SvIV(ret);
1721 SvREFCNT_dec(ret);
1722 memmove(buffer, SvPV_nolen(buf), *len);
1723 }
1724 else
1725 *len = PerlIO_read(IoIFP(io->io), buffer, *len);
1726 return SVN_NO_ERROR;
1727 }
1728
1729 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
io_handle_write(void * baton,const char * data,apr_size_t * len)1730 static svn_error_t *io_handle_write(void *baton,
1731 const char *data,
1732 apr_size_t *len)
1733 {
1734 io_baton_t *io = baton;
1735 MAGIC *mg;
1736
1737 if ((mg = SvTIED_mg((SV*)io->io, PERL_MAGIC_tiedscalar))) {
1738 SV *ret, *pv;
1739 pv = sv_2mortal(newSVpvn(data, *len));
1740 svn_swig_pl_callback_thunk(CALL_METHOD, (void *)"WRITE", &ret, "OOz",
1741 SvTIED_obj((SV*)io->io, mg), pv, *len);
1742 *len = SvIV(ret);
1743 SvREFCNT_dec(ret);
1744 }
1745 else
1746 *len = PerlIO_write(IoIFP(io->io), data, *len);
1747 return SVN_NO_ERROR;
1748 }
1749
1750 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
io_handle_close(void * baton)1751 static svn_error_t *io_handle_close(void *baton)
1752 {
1753 io_baton_t *io = baton;
1754 MAGIC *mg;
1755
1756 if ((mg = SvTIED_mg((SV*)io->io, PERL_MAGIC_tiedscalar))) {
1757 svn_swig_pl_callback_thunk(CALL_METHOD, (void *)"CLOSE", NULL, "O",
1758 SvTIED_obj((SV*)io->io, mg));
1759 }
1760 else {
1761 PerlIO_close(IoIFP(io->io));
1762 }
1763
1764 return SVN_NO_ERROR;
1765 }
1766
io_handle_cleanup(void * baton)1767 static apr_status_t io_handle_cleanup(void *baton)
1768 {
1769 io_baton_t *io = baton;
1770 SvREFCNT_dec(io->obj);
1771 return APR_SUCCESS;
1772 }
1773
1774 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_make_stream(svn_stream_t ** stream,SV * obj)1775 svn_error_t *svn_swig_pl_make_stream(svn_stream_t **stream, SV *obj)
1776 {
1777 IO *io;
1778
1779 if (!SvOK(obj)) {
1780 *stream = NULL;
1781 return SVN_NO_ERROR;
1782 }
1783
1784 if (obj && sv_isobject(obj)) {
1785 int simple_type = 1;
1786 if (sv_derived_from(obj, "SVN::Stream"))
1787 svn_swig_pl_callback_thunk(CALL_METHOD, (void *)"svn_stream",
1788 &obj, "O", obj);
1789 else if (!sv_derived_from(obj, "_p_svn_stream_t"))
1790 simple_type = 0;
1791
1792 if (simple_type) {
1793 SWIG_ConvertPtr(obj, (void **)stream, _SWIG_TYPE("svn_stream_t *"), 0);
1794 return SVN_NO_ERROR;
1795 }
1796 }
1797
1798 if (obj && SvROK(obj) && SvTYPE(SvRV(obj)) == SVt_PVGV &&
1799 (io = GvIO(SvRV(obj)))) {
1800 apr_pool_t *pool = svn_swig_pl_get_current_pool();
1801 io_baton_t *iob = apr_palloc(pool, sizeof(io_baton_t));
1802 SvREFCNT_inc(obj);
1803 iob->obj = obj;
1804 iob->io = io;
1805 *stream = svn_stream_create(iob, pool);
1806 svn_stream_set_read2(*stream, NULL /* only full read support */,
1807 io_handle_read);
1808 svn_stream_set_write(*stream, io_handle_write);
1809 svn_stream_set_close(*stream, io_handle_close);
1810 apr_pool_cleanup_register(pool, iob, io_handle_cleanup,
1811 io_handle_cleanup);
1812
1813 }
1814 else
1815 croak("unknown type for svn_stream_t");
1816
1817 return SVN_NO_ERROR;
1818 }
1819
1820 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_ra_lock_callback(void * baton,const char * path,svn_boolean_t do_lock,const svn_lock_t * lock,svn_error_t * ra_err,apr_pool_t * pool)1821 svn_error_t *svn_swig_pl_ra_lock_callback(
1822 void *baton,
1823 const char *path,
1824 svn_boolean_t do_lock,
1825 const svn_lock_t *lock,
1826 svn_error_t *ra_err,
1827 apr_pool_t *pool)
1828 {
1829 if (!SvOK((SV *)baton))
1830 return SVN_NO_ERROR;
1831
1832 SVN_ERR(svn_swig_pl_callback_thunk(CALL_SV, baton, NULL, "sbSSS",
1833 path, do_lock,
1834 lock, _SWIG_TYPE("svn_lock_t *"),
1835 ra_err, _SWIG_TYPE("svn_error_t *"),
1836 pool, POOLINFO));
1837 return SVN_NO_ERROR;
1838 }
1839
1840 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_from_stream(svn_stream_t * stream)1841 SV *svn_swig_pl_from_stream(svn_stream_t *stream)
1842 {
1843 SV *ret;
1844
1845 svn_swig_pl_callback_thunk(CALL_METHOD, (void *)"new", &ret, "sS",
1846 "SVN::Stream", stream, _SWIG_TYPE("svn_stream_t *"));
1847
1848 return sv_2mortal(ret);
1849 }
1850
svn_swig_pl_make_file(SV * file,apr_pool_t * pool)1851 apr_file_t *svn_swig_pl_make_file(SV *file, apr_pool_t *pool)
1852 {
1853 apr_file_t *apr_file = NULL;
1854
1855 if (!SvOK(file) || file == &PL_sv_undef)
1856 return NULL;
1857
1858 if (SvPOKp(file)) {
1859 apr_file_open(&apr_file, SvPV_nolen(file),
1860 APR_CREATE | APR_READ | APR_WRITE,
1861 APR_OS_DEFAULT,
1862 pool);
1863 } else if (SvROK(file) && SvTYPE(SvRV(file)) == SVt_PVGV) {
1864 apr_status_t status;
1865 #ifdef WIN32
1866 apr_os_file_t osfile = (apr_os_file_t)
1867 _get_osfhandle(PerlIO_fileno(IoIFP(sv_2io(file))));
1868 #else
1869 apr_os_file_t osfile = PerlIO_fileno(IoIFP(sv_2io(file)));
1870 #endif
1871 status = apr_os_file_put(&apr_file, &osfile,
1872 O_CREAT | O_WRONLY, pool);
1873 if (status)
1874 return NULL;
1875 }
1876 return apr_file;
1877 }
1878
cleanup_refcnt(void * data)1879 static apr_status_t cleanup_refcnt(void *data)
1880 {
1881 SV *sv = data;
1882 SvREFCNT_dec(sv);
1883 return APR_SUCCESS;
1884 }
1885
svn_swig_pl_hold_ref_in_pool(apr_pool_t * pool,SV * sv)1886 void svn_swig_pl_hold_ref_in_pool(apr_pool_t *pool, SV *sv)
1887 {
1888 SvREFCNT_inc(sv);
1889 apr_pool_cleanup_register(pool, sv, cleanup_refcnt, apr_pool_cleanup_null);
1890 }
1891
1892 /* NOTE: calls back into Perl (by calling svn_swig_pl_callback_thunk) */
svn_swig_pl_from_md5(unsigned char * digest)1893 SV *svn_swig_pl_from_md5(unsigned char *digest)
1894 {
1895 SV *ret;
1896
1897 svn_swig_pl_callback_thunk(CALL_METHOD, (void *)"new", &ret, "sS",
1898 "SVN::MD5", digest,
1899 _SWIG_TYPE("unsigned char *"));
1900
1901 return sv_2mortal(ret);
1902 }
1903