1/*
2 * ====================================================================
3 *    Licensed to the Apache Software Foundation (ASF) under one
4 *    or more contributor license agreements.  See the NOTICE file
5 *    distributed with this work for additional information
6 *    regarding copyright ownership.  The ASF licenses this file
7 *    to you under the Apache License, Version 2.0 (the
8 *    "License"); you may not use this file except in compliance
9 *    with the License.  You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 *    Unless required by applicable law or agreed to in writing,
14 *    software distributed under the License is distributed on an
15 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 *    KIND, either express or implied.  See the License for the
17 *    specific language governing permissions and limitations
18 *    under the License.
19 * ====================================================================
20 *
21 * svn_types.swg: This is the main file of the Subversion typemap
22 *   library.  Certain categories of typemaps are removed into child
23 *   files that are then %included into this one, solely to promote
24 *   code comprehensibility by grouping related parts.
25 */
26
27%include apr.swg
28%include svn_string.swg
29%include svn_containers.swg
30
31/* -----------------------------------------------------------------------
32   Generic handling for "type **" parameters.  Almost all such parameters
33   are OUTPUT parameters.  Handling is as follows:
34   - "in" typemap which allocates storage for a pointer, and points the
35     argument to that storage.
36   - Default "argout" typemap which complains at compile time, and raises
37     an exception at runtime.
38   - OUTPARAM "argout" typemap which wraps (SWIG_NewPointerObj) a C
39     pointer for return to the scripting language.
40   - Application of the OUTPARAM typemap to those types for which it makes
41     sense (key examples for which it does not are strings, arrays, and
42     hashes - which need to be turned into their scripting language
43     equivalent).
44   Known instances of "type **" which are *not* OUTPUT parameters are:
45   - svn_stream_checksummed(..., const unsigned char **read_digest,
46                                 const unsigned char **write_digest, ...)
47   - svn_*_change_rev_prop2(..., const svn_string_t *const *old_value_p, ...)
48*/
49%typemap(in, numinputs=0) SWIGTYPE ** ($*1_ltype temp) "$1 = &temp;";
50
51/* We have a long standing bug where svn_client_commit_info_t and
52   svn_commit_info_t output parameters are not properly initialized to NULL
53   when there is nothing to commit.  This is a workaround.  Yes, it is
54   unspeakably evil that this was not just fixed at source when it was
55   discovered initially. */
56%typemap(in, numinputs=0) BAD_OUTPUT_INIT_HACK ** ($*1_ltype temp = NULL)
57  "$1 = &temp;";
58%apply BAD_OUTPUT_INIT_HACK ** {
59  svn_commit_info_t **,
60  svn_client_commit_info_t **
61};
62
63%typemap(argout,warning="900:FIXME: Missing argout typemap") SWIGTYPE ** {
64  /* FIXME: Missing argout typemap: $symname arg $argnum ($1_type) */
65#if defined(SWIGRUBY) && SWIG_VERSION <= 0x010329
66  /* Ruby fails to define $symname. */
67  SWIG_exception(SWIG_ValueError, "Function is not implemented yet");
68#else
69  SWIG_exception(SWIG_ValueError, "$symname is not implemented yet");
70#endif
71}
72
73%typemap(in,warning="901:FIXME: Missing old_value_p typemap") const svn_string_t *const *old_value_p {
74#if defined(SWIGRUBY) && SWIG_VERSION <= 0x010329
75  /* Ruby fails to define $symname. */
76  SWIG_exception(SWIG_ValueError, "Function is not implemented yet");
77#else
78  SWIG_exception(SWIG_ValueError, "$symname is not implemented yet");
79#endif
80}
81
82#ifdef SWIGPYTHON
83%typemap(argout) SWIGTYPE **OUTPARAM {
84  %append_output(svn_swig_py_new_pointer_obj(*$1, $*1_descriptor,
85                                             _global_py_pool, args));
86}
87#else
88%typemap(argout) SWIGTYPE **OUTPARAM {
89  %append_output(SWIG_NewPointerObj(*$1, $*1_descriptor, 0));
90}
91#endif
92
93%apply SWIGTYPE **OUTPARAM {
94  /* apr */
95  apr_file_t **,
96  apr_hash_t **,
97  /* svn_types.h */
98  svn_commit_info_t **,
99  svn_dirent_t **,
100  svn_lock_t **,
101  svn_stream_t **,
102  svn_commit_callback2_t *,
103  void **callback2_baton,
104  /* core */
105  svn_auth_baton_t **,
106  svn_auth_cred_simple_t **cred,
107  svn_auth_cred_username_t **cred,
108  svn_auth_cred_ssl_client_cert_pw_t **cred,
109  svn_auth_cred_ssl_client_cert_t **cred,
110  svn_auth_cred_ssl_server_trust_t **cred,
111  svn_auth_iterstate_t **,
112  svn_auth_provider_object_t **,
113  svn_config_t **,
114  svn_diff_t **,
115  svn_patch_file_t **,
116  svn_patch_t **,
117  void **credentials,
118  void **iter_baton,
119  void **token,
120  /* svn_checksum */
121  svn_checksum_t **,
122  /* svn_client */
123  svn_client_commit_info_t **,
124  svn_client_conflict_t **,
125  svn_client_conflict_option_t **,
126  svn_client_ctx_t **,
127  const svn_client_commit_item3_t **,
128  svn_client__shelf_t **,
129  svn_client__shelf_version_t **,
130  /* svn_delta */
131  const svn_delta_editor_t **,
132  svn_txdelta_stream_t **,
133  svn_txdelta_window_t **,
134#ifndef SWIGPYTHON
135  /* Python wraps this as a CALLABLE_CALLBACK instead */
136  svn_txdelta_window_handler_t *,
137#endif
138  void **handler_baton,
139  void **handler2_baton,
140  void **root_baton,
141  void **child_baton,
142  void **file_baton,
143  void **edit_baton,
144  void **dir_baton,
145  /* svn_fs */
146  svn_fs_t **,
147  svn_fs_access_t **,
148  svn_fs_history_t **,
149  svn_fs_id_t **,
150  svn_fs_root_t **,
151  svn_fs_txn_t **,
152  void **contents_baton_p,
153  /* svn_io */
154  svn_io_dirent2_t **,
155  svn_stream_mark_t **,
156  /* svn_ra */
157  svn_ra_callbacks2_t **,
158  svn_ra_plugin_t **,
159  const svn_ra_reporter_t **,
160  const svn_ra_reporter2_t **,
161  const svn_ra_reporter3_t **,
162  svn_ra_session_t **,
163  void **delta_baton,
164  void **report_baton,
165  void **ra_baton,
166  void **session_baton,
167  /* svn_repos */
168  svn_authz_t **,
169  svn_repos_t **,
170  const svn_repos_parse_fns3_t **,
171  const svn_repos_parser_fns2_t **,
172  const svn_repos_parser_fns_t **,
173  void **parse_baton,
174  void **revision_baton,
175  void **node_baton,
176  /* svn_wc */
177  svn_wc_adm_access_t **,
178  svn_wc_external_item2_t **,
179  svn_wc_entry_t **,
180  svn_wc_revision_status_t **,
181  svn_wc_status_t **,
182  svn_wc_status2_t **,
183  svn_wc_committed_queue_t **,
184#ifdef SWIGRUBY
185  /* Only tested for Ruby */
186  svn_wc_context_t **,
187#endif
188  void **set_locks_baton
189};
190
191#ifdef SWIGRUBY
192%typemap(argout) SWIGTYPE **OUTPARAM_WITH_BLOCK {
193  VALUE tmp;
194  tmp = SWIG_NewPointerObj(*$1, $*1_descriptor, 0);
195  if (rb_block_given_p()) {
196    rb_yield(tmp);
197    svn_swig_rb_destroy_pool(_global_svn_swig_rb_pool);
198    DATA_PTR(tmp) = NULL;
199  } else {
200    %append_output(tmp);
201  }
202}
203
204%apply SWIGTYPE **OUTPARAM_WITH_BLOCK {
205  /* svn_fs */
206  svn_fs_t **,
207  /* svn_repos */
208  svn_repos_t **
209};
210#endif
211
212
213/* -----------------------------------------------------------------------
214   Check whether fs/repos was closed or not.
215*/
216#ifdef SWIGRUBY
217%define %raise_if_null(TYPE)
218%typemap(check) svn_ ## TYPE ## _t *
219{
220  if (!$1) {
221    svn_swig_rb_raise_svn_ ## TYPE ## _already_close();
222  }
223}
224%enddef
225
226%raise_if_null(fs);
227%raise_if_null(repos);
228
229%define %define_close_related_methods(TYPE)
230%ignore svn_ ## TYPE ## _swig_rb_close;
231%ignore svn_ ## TYPE ## _swig_rb_closed;
232
233%inline %{
234static VALUE
235svn_ ## TYPE ## _swig_rb_close(VALUE self)
236{
237  if (!DATA_PTR(self)) {
238    svn_swig_rb_raise_svn_ ## TYPE ## _already_close();
239  }
240
241  svn_swig_rb_destroy_internal_pool(self);
242  DATA_PTR(self) = NULL;
243
244  return Qnil;
245}
246
247static VALUE
248svn_ ## TYPE ## _swig_rb_closed(VALUE self)
249{
250  return DATA_PTR(self) ? Qfalse : Qtrue;
251}
252%}
253
254%init %{
255  {
256    VALUE cSvn ## TYPE;
257    cSvn ## TYPE = rb_const_get(_mSWIG, rb_intern("TYPE_p_svn_" #TYPE "_t"));
258    rb_define_method(cSvn ## TYPE, "close",
259                     svn_ ## TYPE ## _swig_rb_close, 0);
260    rb_define_method(cSvn ## TYPE, "closed?",
261                     svn_ ## TYPE ## _swig_rb_closed, 0);
262  }
263%}
264%enddef
265#endif
266
267/* -----------------------------------------------------------------------
268   %apply-ing of typemaps
269*/
270
271%apply int *OUTPUT {
272  int *,
273  svn_boolean_t *,
274  enum svn_wc_merge_outcome_t *
275};
276%apply long *OUTPUT { svn_revnum_t *, svn_node_kind_t * };
277%apply long long *OUTPUT { svn_filesize_t * }
278
279/* -----------------------------------------------------------------------
280   Generic macros for callback typemaps
281*/
282
283#ifdef SWIGPYTHON
284%define %callback_typemap(CallbackFunction, CallbackBaton,
285                          PythonThunk, PerlThunk, RubyThunk)
286%typemap(in) (CallbackFunction, CallbackBaton) {
287  $1 = ($1_ltype) PythonThunk;
288  $2 = $input;
289}
290%enddef
291%define %callback_typemap_maybenull(CallbackFunction, CallbackBaton,
292                                    PythonThunk, PerlThunk, RubyThunk)
293%typemap(in) (CallbackFunction, CallbackBaton) {
294  /* FIXME: Handle the NULL case. */
295  $1 = ($1_ltype) PythonThunk;
296  $2 = $input;
297}
298%enddef
299#endif
300
301#ifdef SWIGPERL
302%define %callback_typemap(CallbackFunction, CallbackBaton,
303                          PythonThunk, PerlThunk, RubyThunk)
304%typemap(in) (CallbackFunction, CallbackBaton) {
305  $1 = ($1_ltype) PerlThunk;
306  $2 = $input;
307}
308%enddef
309%define %callback_typemap_maybenull(CallbackFunction, CallbackBaton,
310                                    PythonThunk, PerlThunk, RubyThunk)
311%typemap(in) (CallbackFunction, CallbackBaton) {
312  if (SvOK($input)) {
313    $1 = ($1_ltype) PerlThunk;
314    $2 = $input;
315  } else {
316    $1 = ($1_ltype) NULL;
317    $2 = NULL;
318  }
319}
320%enddef
321#endif
322
323#ifdef SWIGRUBY
324%define %callback_typemap(CallbackFunction, CallbackBaton,
325                          PythonThunk, PerlThunk, RubyThunk)
326%typemap(in) (CallbackFunction, CallbackBaton) {
327  $1 = ($1_ltype) RubyThunk;
328  $2 = (void *)svn_swig_rb_make_baton($input, _global_svn_swig_rb_pool);
329}
330%enddef
331%define %callback_typemap_maybenull(CallbackFunction, CallbackBaton,
332                                    PythonThunk, PerlThunk, RubyThunk)
333%typemap(in) (CallbackFunction, CallbackBaton) {
334  if (NIL_P($input)) {
335    $1 = ($1_ltype) NULL;
336    $2 = NULL;
337  } else {
338    $1 = ($1_ltype) RubyThunk;
339    $2 = (void *)svn_swig_rb_make_baton($input, _global_svn_swig_rb_pool);
340  }
341}
342%enddef
343#endif
344
345/* -----------------------------------------------------------------------
346   Create a typemap for specifying string args that may be NULL.
347*/
348#ifdef SWIGPYTHON
349%typemap(in) const char *MAY_BE_NULL
350{
351    $1 = svn_swig_py_string_to_cstring($input, TRUE, "$symname", "$1_name");
352    if (PyErr_Occurred()) SWIG_fail;
353}
354#endif
355
356#ifdef SWIGPERL
357%apply const char * { const char *MAY_BE_NULL };
358#endif
359
360#ifdef SWIGRUBY
361%typemap(in) const char *MAY_BE_NULL
362{
363  if (NIL_P($input)) {
364    $1 = NULL;
365  } else {
366    $1 = StringValuePtr($input);
367  }
368}
369
370%typemap(in) const char *NOT_NULL
371{
372  $1 = StringValueCStr($input);
373}
374
375%typemap(out) const char *
376{
377  if ($1) {
378    $result = rb_str_new2($1);
379  } else {
380    $result = Qnil;
381  }
382}
383#endif
384
385/* -----------------------------------------------------------------------
386   const char *header_encoding
387   svn_diff_file_output_unified2
388   svn_client_diff3
389*/
390#ifdef SWIGRUBY
391%typemap(in) const char *header_encoding
392{
393  $1 = NULL;
394
395  if (NIL_P($input)) {
396  } else if (TYPE($input) == T_FIXNUM) {
397    $1 = (char *)NUM2INT($input);
398    if (!($1 == APR_LOCALE_CHARSET || $1 == APR_DEFAULT_CHARSET)) {
399      $1 = NULL;
400    }
401  } else {
402    $1 = StringValuePtr($input);
403  }
404
405  if (!$1) {
406    $1 = (char *)APR_LOCALE_CHARSET;
407  }
408}
409#endif
410
411/* -----------------------------------------------------------------------
412   Define a more refined 'memberin' typemap for 'const char *' members. This
413   is used in place of the 'char *' handler defined automatically.
414
415   We need to do the free/malloc/strcpy special because of the const
416*/
417%typemap(memberin) const char * {
418    apr_size_t len = strlen($input) + 1;
419    char *copied;
420    if ($1) free((char *)$1);
421    copied = malloc(len);
422    memcpy(copied, $input, len);
423    $1 = copied;
424}
425
426/* -----------------------------------------------------------------------
427   Specify how svn_error_t returns are turned into exceptions.
428*/
429#ifdef SWIGPYTHON
430%typemap(out) svn_error_t * {
431    if ($1 != NULL) {
432        if ($1->apr_err != SVN_ERR_SWIG_PY_EXCEPTION_SET)
433            svn_swig_py_svn_exception($1);
434        else
435            svn_error_clear($1);
436        SWIG_fail;
437    }
438    Py_INCREF(Py_None);
439    $result = Py_None;
440}
441#endif
442
443#ifdef SWIGPERL
444%typemap(out) svn_error_t * {
445    if ($1) {
446        SV *exception_handler = perl_get_sv ("SVN::Error::handler", FALSE);
447
448        if (SvOK(exception_handler)) {
449            SV *callback_result;
450
451            PUTBACK;
452            svn_swig_pl_callback_thunk (CALL_SV, exception_handler,
453                                        &callback_result, "S", $1,
454                                        $1_descriptor);
455            SPAGAIN;
456        } else {
457            $result = SWIG_NewPointerObj($1, $1_descriptor, 0);
458            argvi++;
459        }
460    }
461}
462#endif
463
464#ifdef SWIGRUBY
465%typemap(out) svn_error_t *
466{
467  if ($1) {
468    svn_swig_rb_destroy_pool(_global_svn_swig_rb_pool);
469    svn_swig_rb_pop_pool(_global_svn_swig_rb_pool);
470    svn_swig_rb_handle_svn_error($1);
471  }
472  $result = Qnil;
473}
474#endif
475
476/* -----------------------------------------------------------------------
477   Define a general ptr/len typemap. This takes a single script argument
478   and expands it into a ptr/len pair for the native call.
479*/
480#ifdef SWIGPYTHON
481%typemap(in) (const char *PTR, apr_size_t LEN) {
482    Py_ssize_t pyStrLen;
483    if (!PyBytes_Check($input)) {
484        PyErr_SetString(PyExc_TypeError, "expecting a bytes");
485        SWIG_fail;
486    }
487    if (PyBytes_AsStringAndSize($input, &$1, &pyStrLen) == -1) {
488        SWIG_fail;
489    }
490    $2 = pyStrLen;
491}
492#endif
493
494#ifdef SWIGPERL
495%typemap(in) (const char *PTR, apr_size_t LEN) {
496    if (SvPOK($input)) {
497        $1 = SvPV($input, $2);
498    } else {
499        /* set to 0 to avoid warning */
500        $1 = 0;
501        $2 = 0;
502        SWIG_croak("Expecting a string");
503    }
504}
505#endif
506
507#ifdef SWIGRUBY
508%typemap(in) (const char *PTR, apr_size_t LEN)
509{
510  if (!RTEST(rb_obj_is_kind_of($input, rb_cString))) {
511    rb_raise(rb_eArgError, "Expecting a string");
512  }
513  $1 = StringValuePtr($input);
514  $2 = RSTRING_LEN(StringValue($input));
515}
516#endif
517
518%apply (const char *PTR, apr_size_t LEN) {
519    (const char *data, apr_size_t len)
520}
521
522/* -----------------------------------------------------------------------
523   Handle retrieving the error message from svn_strerror
524*/
525
526#ifdef SWIGPERL
527%typemap(in,numinputs=0) (char *buf, apr_size_t bufsize) ( char temp[128] ) {
528    memset (temp,0,128); /* paranoia */
529    $1 = temp;
530    $2 = 128;
531}
532#endif
533
534/* -----------------------------------------------------------------------
535   Define a generic arginit mapping for pools.
536*/
537
538#ifdef SWIGPYTHON
539
540%typemap(in) POINTER_TYPES
541{
542  $1 = ($1_ltype)svn_swig_py_must_get_ptr($input, $descriptor, $svn_argnum);
543  if (PyErr_Occurred()) {
544    SWIG_fail;
545  }
546}
547
548%typemap(out) POINTER_TYPES
549    "$result = svn_swig_py_new_pointer_obj((void*)($1), $descriptor,
550                                           _global_py_pool, args);";
551
552%apply POINTER_TYPES { void *, SWIGTYPE *, SWIGTYPE [] };
553
554%typemap(default, noblock=1) apr_pool_t
555  *(apr_pool_t *_global_pool = NULL, PyObject *_global_py_pool = NULL)
556{
557  if (svn_swig_py_get_pool_arg(args, $descriptor,
558      &_global_py_pool, &_global_pool))
559    SWIG_fail;
560  $1 = _global_pool;
561}
562
563%typemap(in, noblock=1) apr_pool_t * {
564  /* Verify that the user supplied a valid pool */
565  if ($input != Py_None && $input != _global_py_pool) {
566    SWIG_Python_TypeError(SWIG_TypePrettyName($descriptor), $input);
567    SWIG_arg_fail($svn_argnum);
568    SWIG_fail;
569  }
570}
571
572%typemap(freearg) apr_pool_t * {
573  Py_XDECREF(_global_py_pool);
574}
575#endif
576
577#ifdef SWIGPERL
578%typemap(in) apr_pool_t *pool "";
579%typemap(default) apr_pool_t *pool(apr_pool_t *_global_pool) {
580    _global_pool = $1 = svn_swig_pl_make_pool (ST(items-1));
581    SPAGAIN;
582}
583#endif
584#ifdef SWIGRUBY
585%typemap(in) apr_pool_t *pool "";
586%typemap(default) apr_pool_t *pool
587    (VALUE _global_svn_swig_rb_pool, apr_pool_t *_global_pool)
588{
589  svn_swig_rb_get_pool(argc, argv, self, &_global_svn_swig_rb_pool, &$1);
590  _global_pool = $1;
591  svn_swig_rb_push_pool(_global_svn_swig_rb_pool);
592}
593
594%typemap(default) (svn_client_ctx_t *ctx, apr_pool_t *pool)
595     (VALUE _global_svn_swig_rb_pool, apr_pool_t *_global_pool)
596{
597  int adjusted_argc = argc;
598  VALUE *adjusted_argv = argv;
599
600  svn_swig_rb_adjust_arg_for_client_ctx_and_pool(&adjusted_argc,
601                                                 &adjusted_argv);
602  svn_swig_rb_get_pool(adjusted_argc, adjusted_argv, self,
603                       &_global_svn_swig_rb_pool, &$2);
604  _global_pool = $2;
605  svn_swig_rb_push_pool(_global_svn_swig_rb_pool);
606}
607
608%typemap(freearg) apr_pool_t *pool
609{
610  VALUE target;
611  target = _global_vresult_address == &vresult ? self : vresult;
612  if (!svn_swig_rb_set_pool(target, _global_svn_swig_rb_pool))
613    svn_swig_rb_destroy_pool(_global_svn_swig_rb_pool);
614  svn_swig_rb_pop_pool(_global_svn_swig_rb_pool);
615}
616#endif
617
618#ifdef SWIGPERL
619%apply apr_pool_t *pool {
620    apr_pool_t *dir_pool,
621    apr_pool_t *file_pool,
622    apr_pool_t *node_pool,
623    apr_pool_t *result_pool,
624    apr_pool_t *scratch_pool
625};
626#endif
627
628#ifdef SWIGRUBY
629%apply apr_pool_t *pool {
630    apr_pool_t *dir_pool,
631    apr_pool_t *file_pool,
632    apr_pool_t *node_pool,
633    apr_pool_t *result_pool,
634    apr_pool_t *scratch_pool
635};
636#endif
637
638/* -----------------------------------------------------------------------
639 * The CALLABLE_CALLBACK typemap wraps callback types as objects which
640 * can be called directly from Python. header_wrappers.py automatically
641 * tags all callback types (in Python) with this callback.
642 *
643 * header_wrappers.py also generates a '__call__' function for the
644 * callback objects, using the funcptr_proxy macro. See proxy.swg
645 */
646
647#ifdef SWIGPYTHON
648
649/* Allocate memory for a pointer to the function pointer. */
650%typemap(in, numinputs=0) CALLABLE_CALLBACK *
651  (apr_pool_t *_global_pool = NULL, PyObject *_global_py_pool = NULL)
652{
653  if (_global_pool == NULL)
654  {
655    if (svn_swig_py_get_parent_pool(args, $descriptor(apr_pool_t *),
656                                    &_global_py_pool, &_global_pool))
657      SWIG_fail;
658  }
659  $1 = ($ltype) apr_pcalloc(_global_pool, sizeof($*ltype));
660  if ($1 == NULL) SWIG_fail;
661}
662
663
664/* Return a pointer to the function pointer.
665 * This level of indirection makes it easier for SWIG to treat
666 * this callback like an object (which can be extended using SWIG).
667 */
668
669%typemap(argout) CALLABLE_CALLBACK * {
670  %append_output(svn_swig_py_new_pointer_obj($1, $descriptor,
671                                             _global_py_pool, args));
672}
673
674/* Convert the pointer to a function pointer back into a regular
675 * function pointer
676 */
677
678%typemap(in) CALLABLE_CALLBACK {
679  $&ltype tmp =
680    svn_swig_py_must_get_ptr($input, $&descriptor, $svn_argnum);
681  if (tmp == NULL || PyErr_Occurred()) {
682    SWIG_fail;
683  }
684  $1 = *tmp;
685}
686
687/* Ensure that return values use a level of indirection.
688 *
689 * Allocate space on the heap for a pointer to the callback.
690 * The memory gets freed when the return value itself is
691 * freed.
692 */
693
694%typemap(out) CALLABLE_CALLBACK {
695  PyObject *py_pool = NULL;
696  apr_pool_t *pool = NULL;
697
698  if (svn_swig_py_get_parent_pool(args, $descriptor(apr_pool_t *),
699                                  &py_pool, &pool))
700    SWIG_fail;
701  if ($1 == NULL) {
702    $result = Py_None;
703    Py_INCREF($result);
704  } else {
705    $&ltype tmp = apr_palloc(pool, sizeof($ltype));
706    if (tmp == NULL) {
707      SWIG_fail;
708    }
709    *tmp = ($ltype) $1;
710    $result = svn_swig_py_new_pointer_obj(tmp, $&1_descriptor,
711                                          py_pool, args);
712  }
713}
714
715
716/* Ensure that constant callbacks use a level of indirection.
717 *
718 * Allocate space on the heap for a pointer to the callback.
719 * Since this constant is always in scope, we don't need to
720 * worry about ever freeing the memory.
721 */
722
723%typemap(constcode) CALLABLE_CALLBACK {
724
725  $&ltype tmp = malloc(sizeof($ltype));
726  *tmp = ($ltype) $value;
727
728  %set_constant("$symname",
729    svn_swig_py_new_pointer_obj(tmp, $&descriptor, NULL, NULL)
730  );
731
732}
733
734#endif
735
736/* -----------------------------------------------------------------------
737   Callback: svn_log_message_receiver_t
738   svn_client_log()
739   svn_ra get_log()
740   svn_repos_get_logs()
741*/
742
743%callback_typemap(svn_log_message_receiver_t receiver, void *receiver_baton,
744                  svn_swig_py_log_receiver,
745                  svn_swig_pl_thunk_log_receiver,
746                  svn_swig_rb_log_receiver)
747
748/* -----------------------------------------------------------------------
749   Callback: svn_log_entry_receiver_t
750   svn_client_log4()
751   svn_ra_get_log2()
752   svn_repos_get_logs4()
753*/
754
755%callback_typemap(svn_log_entry_receiver_t receiver, void *receiver_baton,
756                  svn_swig_py_log_entry_receiver,
757                  svn_swig_pl_thunk_log_entry_receiver,
758                  svn_swig_rb_log_entry_receiver)
759
760/* -----------------------------------------------------------------------
761   Callback: svn_commit_callback_t
762   svn_ra get_commit_editor()
763   svn_repos_get_commit_editor()
764*/
765
766#ifdef SWIGPERL
767%typemap(in) (svn_commit_callback_t callback, void *callback_baton) {
768    $1 = svn_swig_pl_thunk_commit_callback;
769    $2 = (void *)$input;
770    svn_swig_pl_hold_ref_in_pool (_global_pool, $input);
771};
772#endif
773
774#ifdef SWIGRUBY
775%typemap(in) (svn_commit_callback_t callback, void *callback_baton)
776{
777  $1 = svn_swig_rb_commit_callback;
778  $2 = (void *)svn_swig_rb_make_baton($input, _global_svn_swig_rb_pool);
779};
780
781%typemap(argout) (svn_commit_callback_t callback, void *callback_baton)
782{
783  svn_swig_rb_set_baton($result, (VALUE)$2);
784};
785#endif
786
787#ifdef SWIGPYTHON
788%typemap(in) (svn_commit_callback_t callback, void *callback_baton)
789{
790  $1 = svn_swig_py_commit_callback;
791  $2 = (void *)$input;
792}
793#endif
794
795/* -----------------------------------------------------------------------
796   Callback: svn_commit_callback2_t
797   svn_ra get_commit_editor2()
798   svn_repos_get_commit_editor4()
799   svn_client_mkdir4()
800   svn_client_delete4()
801   svn_client_import4()
802   svn_client_commit5()
803   svn_client_copy6()
804   svn_client_move6()
805   svn_client_propset_remote()
806*/
807
808#ifdef SWIGPERL
809%typemap(in) (svn_commit_callback2_t commit_callback, void *commit_baton) {
810    $1 = svn_swig_pl_thunk_commit_callback2;
811    $2 = (void *)$input;
812    svn_swig_pl_hold_ref_in_pool (_global_pool, $input);
813};
814#endif
815
816#ifdef SWIGRUBY
817%typemap(in) (svn_commit_callback2_t commit_callback, void *commit_baton)
818{
819  $1 = svn_swig_rb_commit_callback2;
820  $2 = (void *)svn_swig_rb_make_baton($input, _global_svn_swig_rb_pool);
821};
822
823%typemap(argout) (svn_commit_callback2_t commit_callback, void *commit_baton)
824{
825  svn_swig_rb_set_baton($result, (VALUE)$2);
826};
827#endif
828
829#ifdef SWIGPYTHON
830%typemap(in) (svn_commit_callback2_t commit_callback, void *commit_baton)
831{
832  $1 = svn_swig_py_commit_callback2;
833  $2 = (void *)$input;
834}
835#endif
836
837/* -----------------------------------------------------------------------
838   Callback: svn_cancel_func_t
839*/
840
841%callback_typemap(svn_cancel_func_t cancel_func, void *cancel_baton,
842                  svn_swig_py_cancel_func,
843                  svn_swig_pl_cancel_func,
844                  svn_swig_rb_cancel_func)
845
846#ifdef SWIGRUBY
847%typemap(argout) (svn_cancel_func_t cancel_func, void *cancel_baton)
848{
849  svn_swig_rb_set_baton($result, (VALUE)$2);
850};
851#endif
852
853#ifdef SWIGRUBY
854%typemap(in) (svn_wc_conflict_resolver_func_t conflict_func, void *conflict_baton)
855{
856  $1 = svn_swig_rb_conflict_resolver_func;
857  $2 = (void *)svn_swig_rb_make_baton($input, _global_svn_swig_rb_pool);
858}
859
860%typemap(argout) (svn_wc_conflict_resolver_func_t conflict_func, void *conflict_baton)
861{
862  svn_swig_rb_set_baton($result, (VALUE)$2);
863};
864#endif
865
866#ifdef SWIGRUBY
867%typemap(in) (svn_wc_get_file_t fetch_func, void *fetch_baton)
868{
869  /* ### TODO(rb support fetch_fun): implement
870  $1 = svn_swig_rb_fetch_func;
871  $2 = (void *)svn_swig_rb_make_baton($input, _global_svn_swig_rb_pool);
872  */
873  $1 = NULL;
874  $2 = NULL;
875}
876
877%typemap(argout) (svn_wc_get_file_t fetch_func, void *fetch_baton)
878{
879  svn_swig_rb_set_baton($result, (VALUE)$2);
880};
881#endif
882
883/* -----------------------------------------------------------------------
884   Callback: svn_info_receiver_t
885*/
886
887#ifdef SWIGPERL
888%typemap(in) (svn_info_receiver_t receiver, void *receiver_baton)
889{
890  $1 = svn_swig_pl_info_receiver;
891  $2 = (void *)$input;
892}
893#endif
894
895#ifdef SWIGRUBY
896%typemap(in) (svn_info_receiver_t receiver, void *receiver_baton)
897{
898  $1 = svn_swig_rb_info_receiver;
899  $2 = (void *)svn_swig_rb_make_baton($input, _global_svn_swig_rb_pool);
900}
901#endif
902
903/* -----------------------------------------------------------------------
904   Callback: svn_repos_freeze_func_t
905*/
906#ifdef SWIGPYTHON
907%typemap(in) (svn_repos_freeze_func_t freeze_func, void *freeze_baton)
908{
909  $1 = svn_swig_py_repos_freeze_func;
910  $2 = (void *)$input;
911}
912#endif
913
914/* -----------------------------------------------------------------------
915   Callback: svn_fs_freeze_func_t
916*/
917#ifdef SWIGPYTHON
918%typemap(in) (svn_fs_freeze_func_t freeze_func, void *freeze_baton)
919{
920  $1 = svn_swig_py_fs_freeze_func;
921  $2 = (void *)$input;
922}
923#endif
924
925/* -----------------------------------------------------------------------
926   Callback: svn_proplist_receiver2_t
927*/
928#ifdef SWIGPYTHON
929%typemap(in) (svn_proplist_receiver2_t receiver, void *receiver_baton)
930{
931  $1 = svn_swig_py_proplist_receiver2;
932  $2 = (void *)$input;
933}
934#endif
935
936/* -----------------------------------------------------------------------
937   Callback: svn_fs_warning_callback_t
938*/
939
940#ifdef SWIGRUBY
941%typemap(in) (svn_fs_warning_callback_t warning, void *warning_baton)
942{
943  VALUE baton = svn_swig_rb_make_baton($input, _global_svn_swig_rb_pool);
944  svn_swig_rb_fs_warning_callback_baton_register(baton, _global_pool);
945  $1 = svn_swig_rb_fs_warning_callback;
946  $2 = (void *)baton;
947}
948#endif
949#ifdef SWIGPERL
950%ignore svn_fs_set_warning_func;
951#endif
952#ifdef SWIGPYTHON
953%ignore svn_fs_set_warning_func;
954#endif
955
956/* -----------------------------------------------------------------------
957   svn_stream_t interoperability with language native io handles
958*/
959
960#ifdef SWIGPYTHON
961%typemap(in) svn_stream_t *WRAPPED_STREAM {
962    if ($input == Py_None) {
963        $1 = NULL;
964    }
965    else {
966        $1 = svn_swig_py_make_stream ($input, _global_pool);
967        if ($1 == NULL) {
968            SWIG_fail;
969        }
970    }
971}
972#endif
973
974#ifdef SWIGPERL
975%typemap(in) svn_stream_t * {
976    svn_swig_pl_make_stream (&$1, $input);
977    SPAGAIN;
978}
979
980%typemap(out) svn_stream_t * {
981    SV* tmp;
982    PUTBACK;
983    tmp = svn_swig_pl_from_stream ($1);
984    SPAGAIN;
985    $result = tmp;
986    argvi++;
987}
988
989%typemap(argout) svn_stream_t ** {
990    SV *tmp;
991    PUTBACK;
992    tmp = svn_swig_pl_from_stream(*$1);
993    SPAGAIN;
994    %append_output(tmp);
995}
996#endif
997
998#ifdef SWIGRUBY
999%typemap(in) svn_stream_t * {
1000  $1 = svn_swig_rb_make_stream($input);
1001}
1002
1003%typemap(in) svn_stream_t *MAY_BE_NULL {
1004  if (NIL_P($input)) {
1005    $1 = NULL;
1006  } else {
1007    $1 = svn_swig_rb_make_stream($input);
1008  }
1009}
1010#endif
1011
1012/* -----------------------------------------------------------------------
1013   Mapper to automatically turn Python objects into void* batons on assignment
1014*/
1015
1016#ifdef SWIGPYTHON
1017
1018%typemap(in) void *PY_AS_VOID {
1019  if ($input == Py_None) {
1020    $1 = NULL;
1021  } else if (SWIG_ConvertPtr($input, (void **) &$1, 0, 0) == -1) {
1022    $1 = (void *) $input;
1023    PyErr_Clear();
1024  }
1025}
1026
1027
1028%typemap(out) void *PY_AS_VOID {
1029  PyObject *ownerObj = obj0;
1030  PyObject *members = PyObject_GetAttrString(ownerObj, "_members");
1031
1032  $result = NULL;
1033  if (members != NULL) {
1034    $result = PyDict_GetItemString(members, "$1_name");
1035    Py_XINCREF($result);
1036    Py_DECREF(members);
1037  }
1038
1039  if ($result == NULL) {
1040    if ($1 == NULL) {
1041      $result = Py_None;
1042      Py_INCREF($result);
1043    } else {
1044      /* We don't know the type of this reference, so we'll have to
1045       * treat it as an opaque void pointer.
1046       */
1047      $result = svn_swig_py_new_pointer_obj($1, $descriptor,
1048                                            _global_py_pool, args);
1049    }
1050  }
1051
1052}
1053
1054#endif
1055
1056/* -----------------------------------------------------------------------
1057   MD5 Digest Parameters: in the Subversion C API, there are:
1058   - 'char' digests, which are hexadecimal-encoded strings.
1059   - 'unsigned char' digests, which are raw blocks of bytes.
1060   This section of typemaps relates to the second variety.
1061   The number of subtly different forms in which these appear in our
1062   APIs is absolutely scary, and we desperately must introduce some sanity
1063   when we do Subversion 2.0.
1064
1065   Function Parameters (Category 1):
1066
1067   'unsigned char digest[]'
1068   'unsigned char *digest':
1069
1070     Output parameter in: svn_fs_file_md5_checksum(), svn_io_file_checksum(),
1071                          svn_wc_transmit_text_deltas2()
1072
1073     *but* appears as an input parameter in svn_base64_from_md5() -
1074     practically, this means that svn_base64_from_md5 is in error, and
1075     should be using 'const unsigned char digest[]', but fortunately, we
1076     do not wrap the svn_base64_* APIs, so do not have to care here.
1077
1078
1079   (Category 2):
1080
1081   There is no category 2!
1082
1083
1084   Function Parameters (No typemaps):
1085
1086   'const unsigned char **read_digest' (also, 'write_digest'):
1087     These are *delayed* output parameters in svn_stream_checksummed().
1088     Would be quite complex to wrap, so this function is %ignore-d in the
1089     svn_io.h cherrypicking section.
1090
1091   'unsigned char *result_digest'
1092     This parameter serves as a buffer for the digest results of
1093     svn_txdelta_apply. As you supply data to this function via
1094     the handler callback, this digest gets filled. Since
1095     filling of this buffer is delayed, it is quite difficult
1096     to wrap.
1097
1098    FIXME: Both Ruby and Perl have broken typemaps for result_digest.
1099    The Python bindings ignore this parameter altogether.
1100
1101   Function Parameters (Category 3):
1102
1103   'const unsigned char digest[]' (also, 'd1', 'd2'):
1104   'const unsigned char *digest':
1105     Input parameters in:
1106     svn_md5_digest_to_cstring_display()
1107     svn_md5_digest_to_cstring()
1108     svn_md5_digests_match()
1109
1110   Function return values (Category 4):
1111
1112   'const unsigned char *' in svn_txdelta_md5_digest()
1113*/
1114
1115/* Category 1 */
1116
1117%typemap(in, numinputs=0) unsigned char digest[ANY]
1118  ($*1_type temp[APR_MD5_DIGESTSIZE]) "$1 = temp;";
1119
1120#ifdef SWIGPYTHON
1121%typemap(argout) unsigned char digest[ANY]
1122{
1123  %append_output(PyBytes_FromStringAndSize((const char *)$1, APR_MD5_DIGESTSIZE));
1124}
1125#endif
1126
1127#ifdef SWIGPERL
1128%typemap(argout) unsigned char digest[ANY] {
1129  %append_output(sv_2mortal(newSVpv(svn_md5_digest_to_cstring($1,
1130                                                              _global_pool),
1131                                    0)));
1132}
1133#endif
1134#ifdef SWIGRUBY
1135%typemap(argout) unsigned char digest[ANY] {
1136  char *digest_string = (char *)svn_md5_digest_to_cstring($1, _global_pool);
1137  %append_output(rb_str_new2(digest_string ? digest_string : ""));
1138}
1139#endif
1140
1141%apply unsigned char digest[ANY] { unsigned char *digest };
1142
1143#ifdef SWIGRUBY
1144/*
1145 * Skip the md5sum
1146 * FIXME: Wrap the md5sum
1147 */
1148%typemap(in, numinputs=0) unsigned char *result_digest
1149  "$1 = NULL;";
1150#endif
1151
1152#ifdef SWIGPYTHON
1153/*
1154 * Skip the md5sum
1155 * FIXME: Wrap the md5sum
1156 */
1157%typemap(in, numinputs=0) unsigned char *result_digest
1158  ($*1_type temp[APR_MD5_DIGESTSIZE]) "$1 = NULL;";
1159#endif
1160
1161#ifdef SWIGPERL
1162%typemap(in, numinputs=0) unsigned char *result_digest {
1163    $1 = (unsigned char *)apr_palloc(_global_pool, APR_MD5_DIGESTSIZE);
1164}
1165
1166%typemap(argout) unsigned char *result_digest {
1167    SV *tmp;
1168    PUTBACK;
1169    tmp = svn_swig_pl_from_md5($1);
1170    SPAGAIN;
1171    %append_output(tmp);
1172}
1173#endif
1174
1175/* Category 3 */
1176
1177/* Override the non-const typemaps defined for category 1, which would
1178   otherwise apply by default, and contribute nonsensical wrappings. */
1179%typemap(in)     const unsigned char digest[], const unsigned char *digest "";
1180%typemap(argout) const unsigned char digest[], const unsigned char *digest "";
1181
1182/* FIXME: There is a lot of coverage missing here */
1183
1184#ifdef SWIGPERL
1185%typemap(in) const unsigned char digest[] {
1186    SWIG_ConvertPtr($input, (void **)&$1, $1_descriptor, 0);
1187}
1188#endif
1189
1190#ifdef SWIGPYTHON
1191/* ### Verify if this should use '[]' like perl and ruby */
1192%typemap(in) const unsigned char *digest {
1193    if ($input == Py_None) {
1194        $1 = NULL;
1195    } else {
1196        $1 = (unsigned char *) PyBytes_AsString($input);
1197        if ($1 == NULL) SWIG_fail;
1198    }
1199}
1200#endif
1201
1202#ifdef SWIGRUBY
1203%typemap(in) const unsigned char digest[]
1204{
1205  if (NIL_P($input)) {
1206    $1 = NULL;
1207  } else if (RSTRING_LEN($input) != APR_MD5_DIGESTSIZE) {
1208    rb_raise(rb_eArgError, "digest size (%d) must be %d",
1209             RSTRING_LEN($input), APR_MD5_DIGESTSIZE);
1210  } else {
1211    $1 = ($1_ltype)StringValuePtr($input);
1212  }
1213}
1214#endif
1215
1216/* Category 4 */
1217/* FIXME: Write a typemap for category 4 */
1218
1219/* -----------------------------------------------------------------------
1220  useful convertors for svn_opt_revision_t
1221*/
1222#ifdef SWIGPERL
1223%typemap(in) svn_opt_revision_t *
1224  (svn_opt_revision_t rev, apr_pool_t *_global_pool = NULL)
1225{
1226  if (_global_pool == NULL) {
1227    _global_pool = svn_swig_pl_make_pool((SV *)NULL);
1228    SPAGAIN;
1229  }
1230  $1 = svn_swig_pl_set_revision(&rev, $input, TRUE, _global_pool);
1231}
1232#endif
1233
1234#ifdef SWIGRUBY
1235%typemap(in) svn_opt_revision_t * (svn_opt_revision_t rev) {
1236  $1 = &rev;
1237  svn_swig_rb_set_revision(&rev, $input);
1238}
1239#endif
1240
1241/* -----------------------------------------------------------------------
1242   useful convertors for svn_depth_t
1243*/
1244
1245#ifdef SWIGRUBY
1246%typemap(in) svn_depth_t {
1247  $1 = svn_swig_rb_to_depth($input);
1248}
1249#endif
1250
1251
1252/* -----------------------------------------------------------------------
1253   useful convertors for svn_mergeinfo_inheritance_t
1254*/
1255
1256#ifdef SWIGRUBY
1257%typemap(in) svn_mergeinfo_inheritance_t {
1258  $1 = svn_swig_rb_to_mergeinfo_inheritance($input);
1259}
1260#endif
1261
1262
1263/* -----------------------------------------------------------------------
1264   useful convertors for svn_merge_range_inheritance_t
1265*/
1266
1267#ifdef SWIGRUBY
1268%typemap(in) svn_merge_range_inheritance_t {
1269  $1 = svn_swig_rb_to_merge_range_inheritance($input);
1270}
1271#endif
1272
1273
1274/* -----------------------------------------------------------------------
1275   Special boolean mapping for ruby.
1276*/
1277
1278#ifdef SWIGRUBY
1279%typemap(in) svn_boolean_t "$1 = RTEST($input);";
1280%typemap(out) svn_boolean_t "$result = $1 ? Qtrue : Qfalse;";
1281
1282%typemap(in, numinputs=0) svn_boolean_t * (svn_boolean_t temp) "$1 = &temp;";
1283%typemap(argout) svn_boolean_t * {
1284  %append_output(*$1 ? Qtrue : Qfalse);
1285}
1286#endif
1287
1288/* -----------------------------------------------------------------------
1289   Filename to temporary file mapping for ruby.
1290*/
1291
1292#ifdef SWIGRUBY
1293%typemap(argout) const char **TO_TEMP_FILE
1294{
1295  %append_output(svn_swig_rb_filename_to_temp_file(*$1));
1296}
1297#endif
1298
1299/* -----------------------------------------------------------------------
1300   Handle python thread locking.
1301
1302   Swig doesn't allow us to specify a language in the %exception command,
1303   so we have to use #ifdefs for the python-specific parts.
1304*/
1305
1306%exception {
1307#ifdef SWIGPYTHON
1308    svn_swig_py_release_py_lock();
1309#endif
1310    $action
1311#ifdef SWIGPYTHON
1312    svn_swig_py_acquire_py_lock();
1313#endif
1314}
1315