1/*
2 * Copyright 2018, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12
13/*- macro show_input_parameter(p, namespace_prefix='') -*/
14    /*- if p.direction == 'in' -*/
15        /*-- if p.array --*/
16            size_t /*? namespace_prefix ?*//*? p.name ?*/_sz,
17            /*- if p.type == 'string' -*/
18                char **
19            /*- else -*/
20                const /*? macros.show_type(p.type) ?*/ *
21            /*- endif -*/
22        /*-- elif p.type == 'string' --*/
23            const char *
24        /*- else -*/
25            /*?- macros.show_type(p.type) -?*/
26        /*- endif -*/ /*? namespace_prefix ?*//*? p.name -?*/
27    /*- else -*/
28        /*- if p.array -*/
29            /*- if p.direction == 'refin' -*/
30                const
31            /*- endif -*/
32            size_t * /*? namespace_prefix ?*//*? p.name ?*/_sz,
33            /*- if p.type == 'string' -*/
34                char ***
35            /*- else -*/
36                /*?- macros.show_type(p.type) ?*/ **
37            /*- endif -*/
38        /*- elif p.type == 'string' -*/
39            char **
40        /*- else -*/
41            /*- if p.direction == 'refin' -*/
42                const
43            /*- endif -*/
44            /*?- macros.show_type(p.type) ?*/ *
45        /*- endif -*/
46        /*? namespace_prefix ?*//*? p.name ?*/
47    /*- endif -*/
48/*- endmacro -*/
49
50/*- macro show_input_parameter_list(parameters, valid_directions, namespace_prefix='') -*/
51    /*-- for p in parameters --*/
52        /*?- assert(p.direction in valid_directions) -?*/
53        /*?- show_input_parameter(p, namespace_prefix) ?*//*- if not loop.last -*/,/*- endif -*/
54    /*-- endfor --*/
55/*- endmacro -*/
56
57/*- macro show_output_parameter(p, namespace_prefix='') -*/
58    /*- if p.array -*/
59        size_t * /*? namespace_prefix ?*//*? p.name ?*/_sz,
60        /*?- macros.show_type(p.type) -?*/ ** /*?- namespace_prefix ?*//*? p.name -?*/
61    /*- else -*/
62        /*?- macros.show_type(p.type) -?*/ * /*?- namespace_prefix ?*//*? p.name -?*/
63    /*- endif -*/
64/*- endmacro -*/
65
66/*- macro show_output_parameter_list(parameters, namespace_prefix='') -*/
67    /*-- for p in parameters --*/
68        /*?- show_output_parameter(p, namespace_prefix) -?*//*-- if not loop.last --*/,/*-- endif --*/
69    /*-- endfor --*/
70/*- endmacro -*/
71
72/*# Generates code for marshalling input parameters to an RPC invocation
73  #     name: Name of this method
74  #     function: Name of function to create
75  #     method_index: Index of this method in the containing interface
76  #     methods_len: Total number of methods in this interface
77  #     input_parameters: All input parameters to this method
78  #*/
79/*- macro make_marshal_input_symbols(name, function, method_index, methods_len, input_parameters) -*/
80    /*# Validate that our arguments are the correct type #*/
81    /*? assert(isinstance(name, six.string_types)) ?*/
82    /*? assert(isinstance(function, six.string_types)) ?*/
83    /*? assert(isinstance(method_index, six.integer_types)) ?*/
84    /*? assert(isinstance(methods_len, six.integer_types)) ?*/
85    /*? assert(isinstance(input_parameters, (list, tuple))) ?*/
86
87    static unsigned /*? function ?*/(void * base, size_t size
88    /*-- if len(input_parameters) > 0 --*/
89        ,
90    /*-- endif -*/
91    /*?- show_input_parameter_list(input_parameters, ['in', 'refin', 'inout'], namespace_prefix="p_") -?*/
92    ) {
93
94        unsigned offset = 0;
95
96        /*- if methods_len > 1 -*/
97            /* Marshal the method index. */
98            /*? macros.type_to_fit_integer(methods_len) ?*/ method_index = /*? method_index ?*/;
99            offset = MARSHAL_PARAM(&method_index, base, size, offset, "/*? name ?*/", "method_index");
100        /*- endif -*/
101
102        /*- for p in input_parameters -*/
103            /*-- if loop.first -*/
104                /* Marshal the parameters. */
105            /*-- endif -*/
106            /*?- assert(isinstance(p.type, six.string_types)) ?*/
107
108            /*#- Construct parameter pointers. We do this here to consolidate where we
109             * are taking the address of local variables. In future, we need to avoid
110             * doing this for verification.
111             #*/
112            /*-- set ptr = "p_%s_ptr" % p.name -*/
113            /*-- set ptr_sz = "p_%s_ptr_sz" % p.name -*/
114            /*-- set ptr_str = "p_%s_ptr_str" % p.name -*/
115            /*-- set ptr_arr = "p_%s_ptr_arr" % p.name -*/
116            /*-- if p.direction == 'in' -*/
117                /*-- if p.array -*/
118                    size_t * /*? ptr_sz ?*/ = &p_/*? p.name ?*/_sz;
119                    * /*? ptr_sz ?*/ = p_/*? p.name ?*/_sz;
120                    /*-- if p.type == 'string' -*/
121                        char ** /*? ptr_arr ?*/ = p_/*? p.name ?*/;
122                    /*-- else -*/
123                        const /*? macros.show_type(p.type) ?*/ * /*? ptr_arr ?*/ = p_/*? p.name ?*/;
124                    /*-- endif -*/
125                /*-- elif p.type == 'string' -*/
126                    const char * /*? ptr_str ?*/ = p_/*? p.name ?*/;
127                /*-- else -*/
128                    /*? macros.show_type(p.type) ?*/ * /*? ptr ?*/ = &p_/*? p.name ?*/;
129                /*-- endif -*/
130            /*-- else -*/
131                /*-- if p.array -*/
132                    const size_t * /*? ptr_sz ?*/ = p_/*? p.name ?*/_sz;
133                    /*-- if p.type == 'string' -*/
134                        char ** /*? ptr_arr ?*/ = * p_/*? p.name ?*/;
135                    /*-- else -*/
136                        const /*? macros.show_type(p.type) ?*/ * /*? ptr_arr ?*/ = * p_/*? p.name ?*/;
137                    /*-- endif -*/
138                /*-- elif p.type == 'string' -*/
139                    const char * /*? ptr_str ?*/ = * p_/*? p.name ?*/;
140                /*-- else -*/
141                    const /*? macros.show_type(p.type) ?*/ * /*? ptr ?*/ = p_/*? p.name ?*/;
142                /*-- endif -*/
143            /*-- endif -*/
144
145            /*-- if p.array -*/
146                /*-- if p.type == 'string' -*/
147                    offset = MARSHAL_STRING_ARRAY_PARAM(/*? ptr_arr ?*/, /*? ptr_sz ?*/, base, size, offset, "/*? name ?*/", "/*? p.name ?*/");
148                /*-- else -*/
149                    offset = MARSHAL_ARRAY_PARAM(/*? ptr_arr ?*/, /*? ptr_sz ?*/, base, size, offset, "/*? name ?*/", "/*? p.name ?*/");
150                /*-- endif -*/
151            /*-- elif p.type == 'string' -*/
152                offset = MARSHAL_STRING_PARAM(/*? ptr_str ?*/, base, size, offset, "/*? name ?*/", "/*? p.name ?*/");
153            /*-- else -*/
154                offset = MARSHAL_PARAM(/*? ptr ?*/, base, size, offset, "/*? name ?*/", "/*? p.name ?*/");
155            /*-- endif -*/
156        /*- endfor -*/
157
158        assert(offset <= size &&
159            "uncaught buffer overflow while marshalling inputs for /*? name ?*/");
160
161        return offset;
162    }
163/*- endmacro -*/
164
165/*# Emits a call to the C symbol that will marshal input parameters
166  # function: Name of function to invoke
167  # buffer: Buffer symbol (or expression) to marshal into
168  # size: Length of the buffer; possibly not generation-time constant
169  # input_parameters: All input parameters to this method
170  #*/
171/*- macro call_marshal_input(function, buffer, size, input_parameters, namespace_prefix='') -*/
172    /*#- Validate our arguments are the correct types #*/
173    /*?- assert(isinstance(function, six.string_types)) ?*/
174    /*?- assert(isinstance(buffer, six.string_types)) ?*/
175    /*?- assert(isinstance(size, (six.string_types,six.integer_types))) ?*/
176    /*?- assert(isinstance(input_parameters, (list, tuple))) ?*/
177
178    /*?- function ?*/(/*? buffer ?*/, /*? size ?*/
179    /*-- for p in input_parameters --*/,
180        /*- if p.array -*//*? namespace_prefix ?*//*? p.name ?*/_sz,/*- endif -*/
181        /*?- namespace_prefix ?*//*? p.name ?*/
182    /*-- endfor --*/
183    )
184/*- endmacro -*/
185
186
187/*# Generates code for marshalling out parameters to an RPC invocation
188  #     name: Name of this method
189  #     function: Name of function to create
190  #     method_index: Index of this method in the containing interface
191  #     output_parameters: All output parameters to this method
192  #     return_type: Return type of this interface
193  #     allow_trailing_data: Whether to ignore checks for remaining bytes after a message
194  #*/
195/*# Whether to ignore checks for remaining bytes after a message #*/
196/*- macro make_unmarshal_output_symbols(name, function, method_index, output_parameters, return_type, allow_trailing_data) -*/
197    /*# Validate our argument types #*/
198    /*? assert(isinstance(name, six.string_types)) ?*/
199    /*? assert(isinstance(function, six.string_types)) ?*/
200    /*? assert(isinstance(method_index, six.integer_types)) ?*/
201    /*? assert(isinstance(output_parameters, (list, tuple))) ?*/
202    /*? assert(return_type is none or isinstance(return_type, six.string_types)) ?*/
203    /*? assert(isinstance(allow_trailing_data, bool)) ?*/
204
205    static int /*? function ?*/(void * base, unsigned size
206    /*-- if return_type is not none or len(output_parameters) > 0 --*/
207        ,
208    /*-- endif -*/
209    /*-- if return_type is not none -*/
210        /*?- macros.show_type(return_type) ?*/ * return_value
211        /*-- if len(output_parameters) > 0 -*/,/*- endif -*/
212    /*-- endif -*/
213    /*?- show_output_parameter_list(output_parameters, namespace_prefix="p_") ?*/
214    ) {
215
216        unsigned offset = 0;
217
218        /*- if return_type is not none -*/
219            /* Unmarshal the return value. */
220            /*-- if return_type == 'string' -*/
221                offset = UNMARSHAL_STRING_PARAM(return_value, base, size, offset, "/*? name ?*/", "return value", ({return -1;}));
222            /*-- else -*/
223                offset = UNMARSHAL_PARAM(return_value, base, size, offset, "/*? name ?*/", "return value", ({return -1;}));
224            /*- endif -*/
225        /*- endif -*/
226
227        /*-- for index, p in enumerate(output_parameters) -*/
228            /*-- if loop.first -*/
229                /* Unmarshal the parameters. */
230            /*-- endif -*/
231            /*?- assert(isinstance(p.type, six.string_types)) ?*/
232            /*-- if p.array -*/
233                /*-- if p.direction == 'inout' -*/
234                    /*-- if p.type == 'string' -*/
235                        /* At this point p_/*? p.name ?*/_sz should still contain the old size */
236                        for (int i = 0; i < * p_/*? p.name ?*/_sz; i ++) {
237                            free((* p_/*? p.name ?*/)[i]);
238                        }
239                    /*-- endif -*/
240                    free(* p_/*? p.name ?*/);
241                /*-- endif -*/
242            /*-- elif p.type == 'string' -*/
243                /*-- if p.direction == 'inout' -*/
244                    free(* p_/*? p.name ?*/);
245                /*-- endif -*/
246            /*-- endif -*/
247
248            /*-- if p.array -*/
249                /*-- if p.type == 'string' -*/
250                    offset = UNMARSHAL_STRING_ARRAY_PARAM(p_/*? p.name ?*/, p_/*? p.name ?*/_sz, base, size, offset, "/*? name ?*/", "/*? p.name ?*/", ({goto cleanup_/*? index ?*/;}));
251                /*-- else -*/
252                    offset = UNMARSHAL_ARRAY_PARAM(p_/*? p.name ?*/, p_/*? p.name ?*/_sz, base, size, offset, "/*? name ?*/", "/*? p.name ?*/", ({goto cleanup_/*? index ?*/;}));
253                /*-- endif -*/
254            /*-- elif p.type == 'string' -*/
255                offset = UNMARSHAL_STRING_PARAM(p_/*? p.name ?*/, base, size, offset, "/*? name ?*/", "/*? p.name ?*/", ({goto cleanup_/*? index ?*/;}));
256            /*-- else -*/
257                offset = UNMARSHAL_PARAM(p_/*? p.name ?*/, base, size, offset, "/*? name ?*/", "/*? p.name ?*/", ({goto cleanup_/*? index ?*/;}));
258            /*-- endif -*/
259        /*- endfor -*/
260
261        /*- if not allow_trailing_data -*/
262        /* Error if there is still payload that hasn't been processed */
263        ERR_IF_MALFORMED_RPC_EXCESS_PAYLOAD(size, offset, "/*? name ?*/", ({
264            goto cleanup_/*? len(output_parameters) ?*/;
265        }));
266    /*- endif -*/
267
268    return 0;
269
270    /*- for index, q in enumerate(output_parameters) | reverse -*/
271cleanup_/*? index + 1 ?*/:
272        /*- if q.array -*/
273            /*- if q.type == 'string' -*/
274                for (int i = 0; i < * p_/*? q.name ?*/_sz; i++) {
275                    free((* p_/*? q.name ?*/)[i]);
276                }
277            /*- endif -*/
278            free(* p_/*? q.name ?*/);
279        /*- elif q.type == 'string' -*/
280            free(* p_/*? q.name ?*/);
281        /*- endif -*/
282    /*- endfor -*/
283cleanup_0:
284            /*-- if return_type == 'string' -*/
285                free(* return_value);
286            /*-- endif -*/
287            return -1;
288    }
289/*- endmacro -*/
290
291
292/*# Emits a call to the C symbol that will unmarshal output parameters
293  # function: Name of function to invoke
294  # buffer: Buffer symbol (or expression) to marshal into
295  # size: Name of a variable storing the byte length of the message
296  # output_parameters: All output parameters to this method
297  # return_type: Return type of this interface
298  # ret_ptr: Pointer for the return value
299  #*/
300/*- macro call_unmarshal_output(function, buffer, size, output_parameters, return_type, ret_ptr, namespace_prefix='') -*/
301    /*#- Validate the types of our arguments #*/
302    /*?- assert(isinstance(function, six.string_types)) ?*/
303    /*?- assert(isinstance(buffer, six.string_types)) ?*/
304    /*?- assert(isinstance(size, (six.string_types,six.integer_types))) ?*/
305    /*?- assert(isinstance(output_parameters, (list, tuple))) ?*/
306    /*?- assert(return_type is none or isinstance(return_type, six.string_types)) ?*/
307
308    /*?- function ?*/(/*? buffer ?*/,
309    /*?- size ?*/
310    /*-- if return_type is not none -*/,
311        /*?- ret_ptr ?*/
312    /*-- endif -*/
313    /*-- for p in output_parameters -*/,
314    /*-- if p.array -*/
315        /*?- namespace_prefix ?*//*? p.name ?*/_sz,
316    /*-- endif -*/
317    /*?- namespace_prefix ?*//*? p.name ?*/
318    /*-- endfor --*/
319    )
320/*- endmacro -*/
321
322/*# Generates code for marshalling out parameters to an RPC invocation
323  #     name: Name of this method
324  #     function: Name of function to create
325  #     methods_len: Total number of methods in this interface
326  #     input_parameters: All input parameters to this method
327  #     allow_trailing_data: Whether to ignore checks for remaining bytes after a message
328  #*/
329/*- macro make_unmarshal_input_symbols(name, function, methods_len, input_parameters, allow_trailing_data) -*/
330    /*# Validate the types of our arguments #*/
331    /*? assert(isinstance(name, six.string_types)) ?*/
332    /*? assert(isinstance(function, six.string_types)) ?*/
333    /*? assert(isinstance(methods_len, six.integer_types)) ?*/
334    /*? assert(isinstance(input_parameters, (list, tuple))) ?*/
335
336    static int /*? function ?*/(void * base, unsigned size
337    /*-- if len(input_parameters) > 0 --*/
338        ,
339    /*-- endif --*/
340    /*? show_output_parameter_list(input_parameters, namespace_prefix="p_") -?*/
341    ) {
342
343        unsigned offset = 0;
344
345        /*- if methods_len > 1 -*/
346            /* Step over the method index. */
347            offset += sizeof(/*? macros.type_to_fit_integer(methods_len) ?*/);
348        /*- endif -*/
349
350        /*- for index, p in enumerate(input_parameters) -*/
351            /*-- if loop.first -*/
352                /* Unmarshal input parameters. */
353            /*-- endif -*/
354            /*?- assert(isinstance(p.type, six.string_types)) ?*/
355             /*-- if p.array -*/
356                /*-- if p.type == 'string' -*/
357                    offset = UNMARSHAL_STRING_ARRAY_PARAM(p_/*? p.name ?*/, p_/*? p.name ?*/_sz, base, size, offset, "/*? name ?*/", "/*? p.name ?*/", ({goto cleanup_/*? index ?*/;}));
358                /*-- else -*/
359                    offset = UNMARSHAL_ARRAY_PARAM(p_/*? p.name ?*/, p_/*? p.name ?*/_sz, base, size, offset, "/*? name ?*/", "/*? p.name ?*/", ({goto cleanup_/*? index ?*/;}));
360                /*-- endif -*/
361            /*-- elif p.type == 'string' -*/
362                offset = UNMARSHAL_STRING_PARAM(p_/*? p.name ?*/, base, size, offset, "/*? name ?*/", "/*? p.name ?*/", ({goto cleanup_/*? index ?*/;}));
363            /*-- else -*/
364                offset = UNMARSHAL_PARAM(p_/*? p.name ?*/, base, size, offset, "/*? name ?*/", "/*? p.name ?*/", ({goto cleanup_/*? index ?*/;}));
365            /*-- endif -*/
366        /*-- endfor -*/
367
368        /*- if not allow_trailing_data -*/
369            ERR_IF_MALFORMED_RPC_EXCESS_PAYLOAD(size, offset, "/*? name ?*/", ({
370                goto cleanup_/*? len(input_parameters) ?*/;
371            }));
372        /*- endif -*/
373
374        return 0;
375        /*-- for index, q in enumerate(input_parameters) | reverse -*/
376cleanup_/*? index + 1 ?*/:
377            /*-- if q.array -*/
378                /*-- if q.type == 'string' -*/
379                    for (int i = 0; i < * p_/*? q.name ?*/_sz; i ++) {
380                        free((* p_/*? q.name ?*/)[i]);
381                    }
382                /*-- endif -*/
383                free(* p_/*? q.name ?*/);
384            /*-- elif q.type == 'string' -*/
385                free(* p_/*? q.name ?*/);
386            /*-- endif -*/
387        /*-- endfor -*/
388cleanup_0:
389        return -1;
390
391    }
392/*- endmacro -*/
393
394/*# Emits a call to the C symbol that will unmarshal output parameters
395  # function: Name of function to invoke
396  # buffer: Buffer symbol (or expression) to marshal into
397  # size: Name of a variable storing the byte length of the message
398  # input_parameters: All input parameters to this method
399  #*/
400/*- macro call_unmarshal_input(function, buffer, size, input_parameters, namespace_prefix='') -*/
401    /*#- Validate our arguments are the expected type #*/
402    /*?- assert(isinstance(function, six.string_types)) ?*/
403    /*?- assert(isinstance(buffer, six.string_types)) ?*/
404    /*?- assert(isinstance(size, (six.string_types,six.integer_types))) ?*/
405    /*?- assert(isinstance(input_parameters, (list, tuple))) ?*/
406
407    /*?- function ?*/(/*? buffer ?*/, /*? size ?*/
408    /*-- for p in input_parameters -*/,
409        /*-- if p.array --*/
410            /*? namespace_prefix ?*//*? p.name ?*/_sz_ptr,
411        /*-- endif --*/
412        /*? namespace_prefix ?*//*? p.name ?*/_ptr
413    /*-- endfor --*/
414    )
415/*- endmacro -*/
416
417/*# Generates code for marshalling out parameters to an RPC invocation
418  #     name: Name of this method
419  #     function: Name of function to create
420  #     output_parameters: All output parameters to this method
421  #     return_type: Return type of this interface
422  #*/
423/*- macro make_marshal_output_symbols(name, function, output_parameters, return_type) -*/
424    /*# Validate our arguments are the correct type #*/
425    /*? assert(isinstance(name, six.string_types)) ?*/
426    /*? assert(isinstance(function, six.string_types)) ?*/
427    /*? assert(isinstance(output_parameters, (list, tuple))) ?*/
428    /*? assert(return_type is none or isinstance(return_type, six.string_types)) ?*/
429
430    static unsigned /*? function ?*/(void * base, unsigned size
431    /*-- if return_type is not none -*/,
432        /*-- if return_type == 'string' --*/
433            char ** return_var
434        /*-- else --*/
435            const /*? macros.show_type(return_type) ?*/ * return_var
436        /*-- endif -*/
437    /*-- endif -*/
438    /*-- if len(output_parameters) > 0 --*/
439        ,
440    /*-- endif -*/
441    /*?- show_input_parameter_list(output_parameters, ['out', 'inout'], namespace_prefix="p_") ?*/
442    ) {
443
444        unsigned offset = 0;
445
446        /*- if return_type is not none -*/
447            /* Marshal the return value. */
448            /*- if return_type == 'string' -*/
449                offset = MARSHAL_STRING_PARAM(* return_var, base, size, offset, "/*? name ?*/", "return value");
450            /*- else -*/
451                offset = MARSHAL_PARAM(return_var, base, size, offset, "/*? name ?*/", "return value");
452            /*- endif -*/
453        /*- endif -*/
454
455        /*-- for p in output_parameters -*/
456            /*-- if loop.first -*/
457                /* Marshal output parameters. */
458            /*-- endif -*/
459            /*?- assert(isinstance(p.type, six.string_types)) ?*/
460            /*-- if p.array -*/
461                /*-- if p.type == 'string' -*/
462                    offset = MARSHAL_STRING_ARRAY_PARAM((* p_/*? p.name ?*/), p_/*? p.name ?*/_sz, base, size, offset, "/*? name ?*/", "/*? p.name ?*/");
463                /*-- else -*/
464                    offset = MARSHAL_ARRAY_PARAM((* p_/*? p.name ?*/), p_/*? p.name ?*/_sz, base, size, offset, "/*? name ?*/", "/*? p.name ?*/");
465                /*-- endif -*/
466            /*-- elif p.type == 'string' -*/
467                offset = MARSHAL_STRING_PARAM(* p_/*? p.name ?*/, base, size, offset, "/*? name ?*/", "/*? p.name ?*/");
468            /*-- else -*/
469                offset = MARSHAL_PARAM(p_/*? p.name ?*/, base, size, offset, "/*? name ?*/", "/*? p.name ?*/");
470            /*-- endif -*/
471        /*- endfor -*/
472
473        assert(offset <= size &&
474            "uncaught buffer overflow while marshalling outputs for /*? name ?*/");
475
476        return offset;
477    }
478/*- endmacro -*/
479
480/*# Emits a call to the C symbol that will unmarshal output parameters
481  # function: Name of function to invoke
482  # buffer: Buffer symbol (or expression) to marshal into
483  # size: Length of the buffer; possibly not generation-time constant
484  # output_parameters: All output parameters to this method
485  # return_type: Return type of this interface
486  # ret_ptr: Pointer for the return value
487  #*/
488/*- macro call_marshal_output(function, buffer, size, output_parameters, return_type, ret_ptr, namespace_prefix='') -*/
489    /*#- Validate our arguments are the correct type #*/
490    /*?- assert(isinstance(function, six.string_types)) ?*/
491    /*?- assert(isinstance(buffer, six.string_types)) ?*/
492    /*?- assert(isinstance(size, (six.string_types,six.integer_types))) ?*/
493    /*?- assert(isinstance(output_parameters, (list, tuple))) ?*/
494    /*?- assert(return_type is none or isinstance(return_type, six.string_types)) ?*/
495
496    /*?- function ?*/(/*? buffer ?*/, /*? size ?*/
497    /*-- if return_type is not none -*/,
498        /*?- assert(isinstance(ret_ptr, six.string_types)) ?*/
499        /*?- ret_ptr ?*/
500    /*-- endif -*/
501    /*-- for p in output_parameters -*/,
502        /*-- if p.array -*/
503            /*?- namespace_prefix ?*//*? p.name ?*/_sz_ptr,
504        /*-- endif -*/
505        /*?- namespace_prefix ?*//*? p.name ?*/_ptr
506    /*-- endfor --*/
507    )
508/*- endmacro -*/
509