1# Gmsh - Copyright (C) 1997-2021 C. Geuzaine, J.-F. Remacle
2#
3# See the LICENSE.txt file in the Gmsh root directory for license information.
4# Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5
6# Contributor(s):
7#   Jonathan Lambrechts
8
9import textwrap
10import string
11import os
12import re
13
14
15class arg:
16    def __init__(self, name, value, python_value, julia_value, cpp_type,
17                 c_type, out):
18        self.name = name
19        self.value = value
20        self.out = out
21        self.cpp = cpp_type + " " + name + ((" = " + value) if value else "")
22        self.c_arg = name
23        self.c_pre = ""
24        self.c_post = ""
25        self.c = c_type + " " + name
26        self.cwrap_arg = self.name
27        self.cwrap_pre = ""
28        self.cwrap_post = ""
29        self.python_value = python_value if python_value is not None else value
30        self.python_arg = ""
31        self.python_return = ""
32        self.python_pre = ""
33        self.julia_value = julia_value if julia_value is not None else value
34        self.julia_arg = name
35        self.julia_ctype = ""
36        self.julia_pre = ""
37        self.julia_post = ""
38        self.julia_return = name
39        self.fortran_type_post = ""
40        self.fortran_name_pre  = ""
41        self.fortran_name_post = ""
42        self.texi = name + (
43            (" = " + self.python_value) if self.python_value else "")
44
45
46# input types
47
48
49def ibool(name, value=None, python_value=None, julia_value=None):
50    a = arg(name, value, python_value, julia_value, "const bool", "const int",
51            False)
52    a.python_arg = "c_int(bool(" + name + "))"
53    a.cwrap_arg = "(int)" + name
54    a.julia_ctype = "Cint"
55    a.fortran_type = "integer(c_int), value"
56    return a
57
58
59def iint(name, value=None, python_value=None, julia_value=None):
60    a = arg(name, value, python_value, julia_value, "const int", "const int",
61            False)
62    a.python_arg = "c_int(" + name + ")"
63    a.julia_ctype = "Cint"
64    a.fortran_type = "integer(c_int), value"
65    return a
66
67
68def isize(name, value=None, python_value=None, julia_value=None):
69    a = arg(name, value, python_value, julia_value, "const std::size_t",
70            "const size_t", False)
71    a.python_arg = "c_size_t(" + name + ")"
72    a.julia_ctype = "Csize_t"
73    a.fortran_type = "integer(c_size_t), value"
74    return a
75
76
77def idouble(name, value=None, python_value=None, julia_value=None):
78    a = arg(name, value, python_value, julia_value, "const double",
79            "const double", False)
80    a.python_arg = "c_double(" + name + ")"
81    a.julia_ctype = "Cdouble"
82    a.fortran_type = "real(c_double), value"
83    return a
84
85
86def istring(name, value=None, python_value=None, julia_value=None):
87    a = arg(name, value, python_value, julia_value, "const std::string &",
88            "const char *", False)
89    a.python_arg = "c_char_p(" + name + ".encode())"
90    a.cwrap_arg = name + ".c_str()"
91    a.julia_ctype = "Ptr{Cchar}"
92    a.fortran_type = "character(len = 1, kind = c_char)"
93    a.fortran_type_post = "(*)"
94    return a
95
96
97def ivoidstar(name, value=None, python_value=None, julia_value=None):
98    a = arg(name, value, python_value, julia_value, "const void *",
99            "const void *", False)
100    a.python_arg = "c_void_p(" + name + ")"
101    a.julia_ctype = "Ptr{Cvoid}"
102    a.fortran_type = "integer(c_int)"
103    a.fortran_type_post = "(*)"
104    return a
105
106
107def ivectorint(name, value=None, python_value=None, julia_value=None):
108    if julia_value == "[]":
109        julia_value = "Cint[]"
110    a = arg(name, value, python_value, julia_value, "const std::vector<int> &",
111            "const int *", False)
112    api_name = "api_" + name + "_"
113    api_name_n = "api_" + name + "_n_"
114    a.c_pre = ("    std::vector<int> " + api_name + "(" + name + ", " + name +
115               " + " + name + "_n);\n")
116    a.c_arg = api_name
117    a.c = "int * " + name + ", size_t " + name + "_n"
118    a.cwrap_pre = ("int *" + api_name + "; size_t " + api_name_n + "; " +
119                   "vector2ptr(" + name + ", &" + api_name + ", &" +
120                   api_name_n + ");\n")
121    a.cwrap_arg = api_name + ", " + api_name_n
122    a.cwrap_post = ns + "Free(" + api_name + ");\n"
123    a.python_pre = api_name + ", " + api_name_n + " = _ivectorint(" + name + ")"
124    a.python_arg = api_name + ", " + api_name_n
125    a.julia_ctype = "Ptr{Cint}, Csize_t"
126    a.julia_arg = "convert(Vector{Cint}, " + name + "), length(" + name + ")"
127    a.fortran_type = "integer(c_int)"
128    a.fortran_type_post = "(*)\n            integer(c_size_t), value :: " + name + "_n"
129    a.fortran_name_post = ",\n     &      " + name + "_n"
130    return a
131
132
133def ivectorsize(name, value=None, python_value=None, julia_value=None):
134    if julia_value == "[]":
135        julia_value = "Csize_t[]"
136    a = arg(name, value, python_value, julia_value,
137            "const std::vector<std::size_t> &", "const size_t *", False)
138    api_name = "api_" + name + "_"
139    api_name_n = "api_" + name + "_n_"
140    a.c_pre = ("    std::vector<std::size_t> " + api_name + "(" + name + ", " +
141               name + " + " + name + "_n);\n")
142    a.c_arg = api_name
143    a.c = "size_t * " + name + ", size_t " + name + "_n"
144    a.cwrap_pre = ("size_t *" + api_name + "; size_t " + api_name_n + "; " +
145                   "vector2ptr(" + name + ", &" + api_name + ", &" +
146                   api_name_n + ");\n")
147    a.cwrap_arg = api_name + ", " + api_name_n
148    a.cwrap_post = ns + "Free(" + api_name + ");\n"
149    a.python_pre = api_name + ", " + api_name_n + " = _ivectorsize(" + name + ")"
150    a.python_arg = api_name + ", " + api_name_n
151    a.julia_ctype = "Ptr{Csize_t}, Csize_t"
152    a.julia_arg = "convert(Vector{Csize_t}, " + name + "), length(" + name + ")"
153    a.fortran_type = "integer(c_size_t)"
154    a.fortran_type_post = "(*)\n            integer(c_size_t), value :: " + name + "_n"
155    a.fortran_name_post = ",\n     &      " + name + "_n"
156    return a
157
158
159def ivectordouble(name, value=None, python_value=None, julia_value=None):
160    if julia_value == "[]":
161        julia_value = "Cdouble[]"
162    a = arg(name, value, python_value, julia_value,
163            "const std::vector<double> &", "double **", False)
164    api_name = "api_" + name + "_"
165    api_name_n = "api_" + name + "_n_"
166    a.c_pre = ("    std::vector<double> " + api_name + "(" + name + ", " +
167               name + " + " + name + "_n);\n")
168    a.c_arg = api_name
169    a.c = "double * " + name + ", size_t " + name + "_n"
170    a.cwrap_pre = ("double *" + api_name + "; size_t " + api_name_n + "; " +
171                   "vector2ptr(" + name + ", &" + api_name + ", &" +
172                   api_name_n + ");\n")
173    a.cwrap_arg = api_name + ", " + api_name_n
174    a.cwrap_post = ns + "Free(" + api_name + ");\n"
175    a.python_pre = api_name + ", " + api_name_n + " = _ivectordouble(" + name + ")"
176    a.python_arg = api_name + ", " + api_name_n
177    a.julia_ctype = "Ptr{Cdouble}, Csize_t"
178    a.julia_arg = "convert(Vector{Cdouble}, " + name + "), length(" + name + ")"
179    a.fortran_type = "real(c_double)"
180    a.fortran_type_post = "(*)\n            integer(c_size_t), value :: " + name + "_n"
181    a.fortran_name_post = ",\n     &      " + name + "_n"
182    return a
183
184
185def ivectorstring(name, value=None, python_value=None, julia_value=None):
186    a = arg(name, value, python_value, julia_value,
187            "const std::vector<std::string> &", "char **", False)
188    api_name = "api_" + name + "_"
189    api_name_n = "api_" + name + "_n_"
190    a.c_pre = ("    std::vector<std::string> " + api_name + "(" + name + ", " +
191               name + " + " + name + "_n);\n")
192    a.c_arg = api_name
193    a.c = "char ** " + name + ", size_t " + name + "_n"
194    a.cwrap_pre = ("char **" + api_name + "; size_t " + api_name_n + "; " +
195                   "vectorstring2charptrptr(" + name + ", &" + api_name +
196                   ", &" + api_name_n + ");\n")
197    a.cwrap_arg = api_name + ", " + api_name_n
198    a.cwrap_post = ("for(size_t i = 0; i < " + api_name_n + "; ++i){ " + ns +
199                    "Free(" + api_name + "[i]); } " + ns + "Free(" + api_name +
200                    ");\n")
201    a.python_pre = api_name + ", " + api_name_n + " = _ivectorstring(" + name + ")"
202    a.python_arg = api_name + ", " + api_name_n
203    a.julia_ctype = "Ptr{Ptr{Cchar}}, Csize_t"
204    a.julia_arg = name + ", length(" + name + ")"
205    a.fortran_type = "type(c_ptr)"
206    a.fortran_type_post = "(*)\n            integer(c_size_t), value :: " + name + "_n"
207    a.fortran_name_post = ",\n     &      " + name + "_n"
208    return a
209
210
211def ivectorpair(name, value=None, python_value=None, julia_value=None):
212    if julia_value == "[]":
213        julia_value = "Tuple{Cint,Cint}[]"
214    a = arg(name, value, python_value, julia_value,
215            "const " + ns + "::vectorpair &", "const int *", False)
216    api_name = "api_" + name + "_"
217    api_name_n = "api_" + name + "_n_"
218    a.c_pre = ("    " + ns + "::vectorpair " + api_name + "(" + name +
219               "_n/2);\n" + "    for(size_t i = 0; i < " + name +
220               "_n/2; ++i){\n" + "      " + api_name + "[i].first = " + name +
221               "[i * 2 + 0];\n" + "      " + api_name + "[i].second = " +
222               name + "[i * 2 + 1];\n" + "    }\n")
223    a.c_arg = api_name
224    a.c = "int * " + name + ", size_t " + name + "_n"
225    a.cwrap_pre = ("int *" + api_name + "; size_t " + api_name_n + "; " +
226                   "vectorpair2intptr(" + name + ", &" + api_name + ", &" +
227                   api_name_n + ");\n")
228    a.cwrap_arg = api_name + ", " + api_name_n
229    a.cwrap_post = ns + "Free(" + api_name + ");\n"
230    a.python_pre = api_name + ", " + api_name_n + " = _ivectorpair(" + name + ")"
231    a.python_arg = api_name + ", " + api_name_n
232    a.julia_ctype = "Ptr{Cint}, Csize_t"
233    a.julia_pre = (api_name + " = collect(Cint, Iterators.flatten(" + name +
234                   "))\n    " + api_name_n + " = length(" + api_name + ")")
235    a.julia_arg = (api_name + ", " + api_name_n)
236    a.fortran_type = "integer(c_int)"
237    a.fortran_type_post = "(*)\n            integer(c_size_t), value :: " + name + "_n"
238    a.fortran_name_post = ",\n     &      " + name + "_n"
239    return a
240
241
242def ivectorvectorint(name, value=None, python_value=None, julia_value=None):
243    if julia_value == "[]":
244        julia_value = "Vector{Cint}[]"
245    a = arg(name, value, python_value, julia_value,
246            "const std::vector<std::vector<int> > &", "const int **", False)
247    api_name = "api_" + name + "_"
248    api_name_n = "api_" + name + "_n_"
249    api_name_nn = "api_" + name + "_nn_"
250    a.c_pre = ("    std::vector<std::vector<int> > " + api_name + "(" + name +
251               "_nn);\n" + "    for(size_t i = 0; i < " + name +
252               "_nn; ++i)\n" + "      " + api_name +
253               "[i] = std::vector<int>(" + name + "[i], " + name + "[i] + " +
254               name + "_n[i]);\n")
255    a.c_arg = api_name
256    a.c = ("const int ** " + name + ", const size_t * " + name + "_n, " +
257           "size_t " + name + "_nn")
258    a.cwrap_pre = ("int **" + api_name + "; size_t *" + api_name_n + ", " +
259                   api_name_nn + "; " + "vectorvector2ptrptr(" + name + ", &" +
260                   api_name + ", &" + api_name_n + ", &" + api_name_nn +
261                   ");\n")
262    a.cwrap_arg = "(const int **)" + api_name + ", " + api_name_n + ", " + api_name_nn
263    a.cwrap_post = ("for(size_t i = 0; i < " + api_name_nn + "; ++i){ " + ns +
264                    "Free(" + api_name + "[i]); } " + ns + "Free(" + api_name +
265                    "); " + ns + "Free(" + api_name_n + ");\n")
266    a.python_pre = (api_name + ", " + api_name_n + ", " + api_name_nn +
267                    " = _ivectorvectorint(" + name + ")")
268    a.python_arg = api_name + ", " + api_name_n + ", " + api_name_nn
269    a.julia_ctype = "Ptr{Ptr{Cint}}, Ptr{Csize_t}, Csize_t"
270    a.julia_pre = (api_name_n + " = [ length(" + name +
271                   "[i]) for i in 1:length(" + name + ") ]")
272    a.julia_arg = ("convert(Vector{Vector{Cint}}," + name + "), " +
273                   api_name_n + ", length(" + name + ")")
274    a.fortran_type = "type(c_ptr), intent(out)"
275    a.fortran_type_post = ("\n            type(c_ptr), intent(out) :: " + name +
276                           "_n\n            integer(c_size_t) :: " + name + "_nn")
277    a.fortran_name_post = ",\n     &      " + name + "_n,\n     &      "  + name + "_nn"
278    return a
279
280
281def ivectorvectorsize(name, value=None, python_value=None, julia_value=None):
282    if julia_value == "[]":
283        julia_value = "Vector{Csize_t}[]"
284    a = arg(name, value, python_value, julia_value,
285            "const std::vector<std::vector<std::size_t> > &",
286            "const size_t **", False)
287    api_name = "api_" + name + "_"
288    api_name_n = "api_" + name + "_n_"
289    api_name_nn = "api_" + name + "_nn_"
290    a.c_pre = ("    std::vector<std::vector<std::size_t> > " + api_name + "(" +
291               name + "_nn);\n" + "    for(size_t i = 0; i < " + name +
292               "_nn; ++i)\n" + "      " + api_name +
293               "[i] = std::vector<std::size_t>(" + name + "[i], " + name +
294               "[i] + " + name + "_n[i]);\n")
295    a.c_arg = api_name
296    a.c = ("const size_t ** " + name + ", const size_t * " + name + "_n, " +
297           "size_t " + name + "_nn")
298    a.cwrap_pre = ("size_t **" + api_name + "; size_t *" + api_name_n + ", " +
299                   api_name_nn + "; " + "vectorvector2ptrptr(" + name + ", &" +
300                   api_name + ", &" + api_name_n + ", &" + api_name_nn +
301                   ");\n")
302    a.cwrap_arg = "(const size_t **)" + api_name + ", " + api_name_n + ", " + api_name_nn
303    a.cwrap_post = ("for(size_t i = 0; i < " + api_name_nn + "; ++i){ " + ns +
304                    "Free(" + api_name + "[i]); } " + ns + "Free(" + api_name +
305                    "); " + ns + "Free(" + api_name_n + ");\n")
306    a.python_pre = (api_name + ", " + api_name_n + ", " + api_name_nn +
307                    " = _ivectorvectorsize(" + name + ")")
308    a.python_arg = api_name + ", " + api_name_n + ", " + api_name_nn
309    a.julia_ctype = "Ptr{Ptr{Csize_t}}, Ptr{Csize_t}, Csize_t"
310    a.julia_pre = (api_name_n + " = [ length(" + name +
311                   "[i]) for i in 1:length(" + name + ") ]")
312    a.julia_arg = ("convert(Vector{Vector{Csize_t}}," + name + "), " +
313                   api_name_n + ", length(" + name + ")")
314    a.fortran_type = "type(c_ptr), intent(out)"
315    a.fortran_type_post = ("\n            type(c_ptr), intent(out) :: " + name +
316                           "_n\n            integer(c_size_t) :: " + name + "_nn")
317    a.fortran_name_post = ",\n     &      " + name + "_n,\n     &      "  + name + "_nn"
318    return a
319
320
321def ivectorvectordouble(name, value=None, python_value=None, julia_value=None):
322    if julia_value == "[]":
323        julia_value = "Vector{Cdouble}[]"
324    a = arg(name, value, python_value, julia_value,
325            "const std::vector<std::vector<double> > &", "const double**",
326            False)
327    api_name = "api_" + name + "_"
328    api_name_n = "api_" + name + "_n_"
329    api_name_nn = "api_" + name + "_nn_"
330    a.c_pre = ("    std::vector<std::vector<double> > " + api_name + "(" +
331               name + "_nn);\n" + "    for(size_t i = 0; i < " + name +
332               "_nn; ++i)\n" + "      " + api_name +
333               "[i] = std::vector<double>(" + name + "[i], " + name +
334               "[i] + " + name + "_n[i]);\n")
335    a.c_arg = api_name
336    a.c = ("const double ** " + name + ", const size_t * " + name + "_n, " +
337           "size_t " + name + "_nn")
338    a.cwrap_pre = ("double **" + api_name + "; size_t *" + api_name_n + ", " +
339                   api_name_nn + "; " + "vectorvector2ptrptr(" + name + ", &" +
340                   api_name + ", &" + api_name_n + ", &" + api_name_nn +
341                   ");\n")
342    a.cwrap_arg = "(const double **)" + api_name + ", " + api_name_n + ", " + api_name_nn
343    a.cwrap_post = ("for(size_t i = 0; i < " + api_name_nn + "; ++i){ " + ns +
344                    "Free(" + api_name + "[i]); } " + ns + "Free(" + api_name +
345                    "); " + ns + "Free(" + api_name_n + ");\n")
346    a.python_pre = (api_name + ", " + api_name_n + ", " + api_name_nn +
347                    " = _ivectorvectordouble(" + name + ")")
348    a.python_arg = api_name + ", " + api_name_n + ", " + api_name_nn
349    a.julia_ctype = "Ptr{Ptr{Cdouble}}, Ptr{Csize_t}, Csize_t"
350    a.julia_pre = (api_name_n + " = [ length(" + name +
351                   "[i]) for i in 1:length(" + name + ") ]")
352    a.julia_arg = ("convert(Vector{Vector{Cdouble}}," + name + "), " +
353                   api_name_n + ", length(" + name + ")")
354    a.fortran_type = "type(c_ptr), intent(out)"
355    a.fortran_type_post = ("\n            type(c_ptr), intent(out) :: " +
356                           name + "_n\n            integer(c_size_t) :: " + name + "_nn")
357    a.fortran_name_post = ",\n     &      " + name + "_n,\n     &      "  + name + "_nn"
358    return a
359
360
361# output types
362
363
364class oint(arg):
365    rcpp_type = "int"
366    rc_type = "int"
367    rtexi_type = "integer value"
368    rjulia_type = "Cint"
369    fortran_type = "integer(c_int)"
370    fortran_type_post = ""
371
372    def __init__(self, name, value=None, python_value=None, julia_value=None):
373        arg.__init__(self, name, value, python_value, julia_value, "int &",
374                     "int *", True)
375        api_name = "api_" + name + "_"
376        self.c_arg = "*" + name
377        self.cwrap_arg = "&" + name
378        self.python_pre = api_name + " = c_int()"
379        self.python_arg = "byref(" + api_name + ")"
380        self.python_return = api_name + ".value"
381        self.julia_ctype = "Ptr{Cint}"
382        self.julia_pre = api_name + " = Ref{Cint}()"
383        self.julia_arg = api_name
384        self.julia_return = api_name + "[]"
385
386
387class osize(arg):
388    rcpp_type = "std::size_t"
389    rc_type = "size_t"
390    rtexi_type = "size value"
391    rjulia_type = "Csize_t"
392    fortran_type = "integer(c_size_t)"
393    fortran_type_post = ""
394
395    def __init__(self, name, value=None, python_value=None, julia_value=None):
396        arg.__init__(self, name, value, python_value, julia_value,
397                     "std::size_t &", "size_t *", True)
398        api_name = "api_" + name + "_"
399        self.c_arg = "*" + name
400        self.cwrap_arg = "&" + name
401        self.python_pre = api_name + " = c_size_t()"
402        self.python_arg = "byref(" + api_name + ")"
403        self.python_return = api_name + ".value"
404        self.julia_ctype = "Ptr{Csize_t}"
405        self.julia_pre = api_name + " = Ref{Csize_t}()"
406        self.julia_arg = api_name
407        self.julia_return = api_name + "[]"
408
409
410class odouble(arg):
411    rcpp_type = "double"
412    rc_type = "double"
413    rtexi_type = "floating point value"
414    rjulia_type = "Cdouble"
415    fortran_type = "real(c_double)"
416    fortran_type_post = ""
417
418    def __init__(self, name, value=None, python_value=None, julia_value=None):
419        arg.__init__(self, name, value, python_value, julia_value, "double &",
420                     "double *", True)
421        api_name = "api_" + name + "_"
422        self.c_arg = "*" + name
423        self.cwrap_arg = "&" + name
424        self.python_pre = api_name + " = c_double()"
425        self.python_arg = "byref(" + api_name + ")"
426        self.python_return = api_name + ".value"
427        self.julia_ctype = "Ptr{Cdouble}"
428        self.julia_pre = api_name + " = Ref{Cdouble}()"
429        self.julia_arg = api_name
430        self.julia_return = api_name + "[]"
431
432
433def ostring(name, value=None, python_value=None, julia_value=None):
434    a = arg(name, value, python_value, julia_value, "std::string &", "char **",
435            True)
436    api_name = "api_" + name + "_"
437    a.c_pre = "    std::string " + api_name + ";\n"
438    a.c_arg = api_name
439    a.c_post = "    *" + name + " = strdup(" + api_name + ".c_str());\n"
440    a.cwrap_pre = "char *" + api_name + ";\n"
441    a.cwrap_arg = "&" + api_name
442    a.cwrap_post = (name + " = std::string(" + api_name + "); " + ns +
443                    "Free(" + api_name + ");\n")
444    a.python_pre = api_name + " = c_char_p()"
445    a.python_arg = "byref(" + api_name + ")"
446    a.python_return = "_ostring(" + api_name + ")"
447    a.julia_ctype = "Ptr{Ptr{Cchar}}"
448    a.julia_pre = api_name + " = Ref{Ptr{Cchar}}()"
449    a.julia_arg = api_name
450    a.julia_post = name + " = unsafe_string(" + api_name + "[])"
451    a.fortran_type = "type(c_ptr)"
452    a.fortran_type_post = "(*)"
453    return a
454
455
456def ovectorint(name, value=None, python_value=None, julia_value=None):
457    a = arg(name, value, python_value, julia_value, "std::vector<int> &",
458            "int **", True)
459    api_name = "api_" + name + "_"
460    api_name_n = api_name + "n_"
461    a.c_pre = "    std::vector<int> " + api_name + ";\n"
462    a.c_arg = api_name
463    a.c_post = "    vector2ptr(" + api_name + ", " + name + ", " + name + "_n);\n"
464    a.c = "int ** " + name + ", size_t * " + name + "_n"
465    a.cwrap_pre = "int *" + api_name + "; size_t " + api_name_n + ";\n"
466    a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n
467    a.cwrap_post = (name + ".assign(" + api_name + ", " + api_name + " + " +
468                    api_name_n + "); " + ns + "Free(" + api_name + ");\n")
469    a.python_pre = api_name + ", " + api_name_n + " = POINTER(c_int)(), c_size_t()"
470    a.python_arg = "byref(" + api_name + "), byref(" + api_name_n + ")"
471    a.python_return = "_ovectorint(" + api_name + ", " + api_name_n + ".value)"
472    a.julia_ctype = "Ptr{Ptr{Cint}}, Ptr{Csize_t}"
473    a.julia_pre = (api_name + " = Ref{Ptr{Cint}}()\n    " + api_name_n +
474                   " = Ref{Csize_t}()")
475    a.julia_arg = api_name + ", " + api_name_n
476    a.julia_post = (name + " = unsafe_wrap(Array, " + api_name + "[], " +
477                    api_name_n + "[], own = true)")
478    a.fortran_type = "type(c_ptr), intent(out)"
479    a.fortran_type_post = "\n            integer(c_size_t) :: " + name +"_n"
480    a.fortran_name_post = ",\n     &      " + name + "_n"
481    return a
482
483
484def ovectorsize(name, value=None, python_value=None, julia_value=None):
485    a = arg(name, value, python_value, julia_value,
486            "std::vector<std::size_t> &", "size_t **", True)
487    api_name = "api_" + name + "_"
488    api_name_n = api_name + "n_"
489    a.c_pre = "    std::vector<std::size_t> " + api_name + ";\n"
490    a.c_arg = api_name
491    a.c_post = "    vector2ptr(" + api_name + ", " + name + ", " + name + "_n);\n"
492    a.c = "size_t ** " + name + ", size_t * " + name + "_n"
493    a.cwrap_pre = "size_t *" + api_name + "; size_t " + api_name_n + ";\n"
494    a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n
495    a.cwrap_post = (name + ".assign(" + api_name + ", " + api_name + " + " +
496                    api_name_n + "); " + ns + "Free(" + api_name + ");\n")
497    a.python_pre = api_name + ", " + api_name_n + " = POINTER(c_size_t)(), c_size_t()"
498    a.python_arg = "byref(" + api_name + "), byref(" + api_name_n + ")"
499    a.python_return = "_ovectorsize(" + api_name + ", " + api_name_n + ".value)"
500    a.julia_ctype = "Ptr{Ptr{Csize_t}}, Ptr{Csize_t}"
501    a.julia_pre = (api_name + " = Ref{Ptr{Csize_t}}()\n    " + api_name_n +
502                   " = Ref{Csize_t}()")
503    a.julia_arg = api_name + ", " + api_name_n
504    a.julia_post = (name + " = unsafe_wrap(Array, " + api_name + "[], " +
505                    api_name_n + "[], own = true)")
506    a.fortran_type = "type(c_ptr), intent(out)"
507    a.fortran_type_post = "\n            integer(c_size_t) :: " + name + "_n"
508    a.fortran_name_post = ",\n     &      " + name + "_n"
509    return a
510
511
512def ovectordouble(name, value=None, python_value=None, julia_value=None):
513    a = arg(name, value, python_value, julia_value, "std::vector<double> &",
514            "double *", True)
515    api_name = "api_" + name + "_"
516    api_name_n = api_name + "n_"
517    a.c_pre = "    std::vector<double> " + api_name + ";\n"
518    a.c_arg = api_name
519    a.c_post = "    vector2ptr(" + api_name + ", " + name + ", " + name + "_n);\n"
520    a.c = "double ** " + name + ", size_t * " + name + "_n"
521    a.cwrap_pre = "double *" + api_name + "; size_t " + api_name_n + ";\n"
522    a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n
523    a.cwrap_post = (name + ".assign(" + api_name + ", " + api_name + " + " +
524                    api_name_n + "); " + ns + "Free(" + api_name + ");\n")
525    a.python_pre = api_name + ", " + api_name_n + " = POINTER(c_double)(), c_size_t()"
526    a.python_arg = "byref(" + api_name + "), byref(" + api_name_n + ")"
527    a.python_return = "_ovectordouble(" + api_name + ", " + api_name_n + ".value)"
528    a.julia_ctype = "Ptr{Ptr{Cdouble}}, Ptr{Csize_t}"
529    a.julia_pre = (api_name + " = Ref{Ptr{Cdouble}}()\n    " + api_name_n +
530                   " = Ref{Csize_t}()")
531    a.julia_arg = api_name + ", " + api_name_n
532    a.julia_post = (name + " = unsafe_wrap(Array, " + api_name + "[], " +
533                    api_name_n + "[], own = true)")
534    a.fortran_type = "type(c_ptr), intent(out)"
535    a.fortran_type_post = "\n            integer(c_size_t) :: " + name + "_n"
536    a.fortran_name_post = ",\n     &      " + name + "_n"
537    return a
538
539
540def ovectorstring(name, value=None, python_value=None, julia_value=None):
541    a = arg(name, value, python_value, julia_value,
542            "std::vector<std::string> &", "char **", True)
543    api_name = "api_" + name + "_"
544    api_name_n = api_name + "n_"
545    a.c_pre = "    std::vector<std::string> " + api_name + ";\n"
546    a.c_arg = api_name
547    a.c_post = ("    vectorstring2charptrptr(" + api_name + ", " + name +
548                ", " + name + "_n);\n")
549    a.c = "char *** " + name + ", size_t * " + name + "_n"
550    a.cwrap_pre = "char **" + api_name + "; size_t " + api_name_n + ";\n"
551    a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n
552    a.cwrap_post = (name + ".resize(" + api_name_n + "); " +
553                    "for(size_t i = 0; i < " + api_name_n + "; ++i){ " + name +
554                    "[i] = std::string(" + api_name + "[i]); " + ns + "Free(" +
555                    api_name + "[i]); } " + ns + "Free(" + api_name + ");\n")
556    a.python_pre = api_name + ", " + api_name_n + " = POINTER(POINTER(c_char))(), c_size_t()"
557    a.python_arg = "byref(" + api_name + "), byref(" + api_name_n + ")"
558    a.python_return = "_ovectorstring(" + api_name + ", " + api_name_n + ".value)"
559    a.julia_ctype = "Ptr{Ptr{Ptr{Cchar}}}, Ptr{Csize_t}"
560    a.julia_pre = (api_name + " = Ref{Ptr{Ptr{Cchar}}}()\n    " + api_name_n +
561                   " = Ref{Csize_t}()")
562    a.julia_arg = api_name + ", " + api_name_n
563    a.julia_post = ("tmp_" + api_name + " = unsafe_wrap(Array, " + api_name +
564                    "[], " + api_name_n + "[], own = true)\n    " + name +
565                    " = [unsafe_string(tmp_" + api_name +
566                    "[i]) for i in 1:length(tmp_" + api_name + ") ]")
567    a.fortran_type = "type(c_ptr), intent(out)"
568    a.fortran_type_post = "\n            integer(c_size_t) :: " + name + "_n"
569    a.fortran_name_post = ",\n     &      " + name + "_n"
570    return a
571
572
573def ovectorpair(name, value=None, python_value=None, julia_value=None):
574    a = arg(name, value, python_value, julia_value, ns + "::vectorpair &",
575            "int **", True)
576    api_name = "api_" + name + "_"
577    api_name_n = api_name + "n_"
578    a.c_pre = "    " + ns + "::vectorpair " + api_name + ";\n"
579    a.c_arg = api_name
580    a.c_post = "    vectorpair2intptr(" + api_name + ", " + name + ", " + name + "_n);\n"
581    a.c = "int ** " + name + ", size_t * " + name + "_n"
582    a.cwrap_pre = "int *" + api_name + "; size_t " + api_name_n + ";\n"
583    a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n
584    a.cwrap_post = (name + ".resize(" + api_name_n + " / 2); " +
585                    "for(size_t i = 0; i < " + api_name_n + " / 2; ++i){ " +
586                    name + "[i].first = " + api_name + "[i * 2 + 0]; " + name +
587                    "[i].second = " + api_name + "[i * 2 + 1]; } " + ns +
588                    "Free(" + api_name + ");\n")
589    a.python_pre = api_name + ", " + api_name_n + " = POINTER(c_int)(), c_size_t()"
590    a.python_arg = "byref(" + api_name + "), byref(" + api_name_n + ")"
591    a.python_return = "_ovectorpair(" + api_name + ", " + api_name_n + ".value)"
592    a.julia_ctype = "Ptr{Ptr{Cint}}, Ptr{Csize_t}"
593    a.julia_pre = (api_name + " = Ref{Ptr{Cint}}()\n    " + api_name_n +
594                   " = Ref{Csize_t}()")
595    a.julia_arg = api_name + ", " + api_name_n
596    a.julia_post = ("tmp_" + api_name + " = unsafe_wrap(Array, " + api_name +
597                    "[], " + api_name_n + "[], own = true)\n    " + name +
598                    " = [ (tmp_" + api_name + "[i], tmp_" + api_name +
599                    "[i+1]) " + "for i in 1:2:length(tmp_" + api_name + ") ]")
600    a.fortran_type = "type(c_ptr), intent(out)"
601    a.fortran_type_post = "\n            integer(c_size_t) :: " + name + "_n"
602    a.fortran_name_post = ",\n     &      " + name + "_n"
603    return a
604
605
606def ovectorvectorint(name, value=None, python_value=None, julia_value=None):
607    a = arg(name, value, python_value, julia_value,
608            "std::vector<std::vector<int> > &", "int **", True)
609    api_name = "api_" + name + "_"
610    api_name_n = api_name + "n_"
611    api_name_nn = api_name + "nn_"
612    a.c_pre = "    std::vector<std::vector<int> > " + api_name + ";\n"
613    a.c_arg = api_name
614    a.c_post = ("    vectorvector2ptrptr(" + api_name + ", " + name + ", " +
615                name + "_n, " + name + "_nn);\n")
616    a.c = "int *** " + name + ", size_t ** " + name + "_n, size_t *" + name + "_nn"
617    a.cwrap_pre = "int **" + api_name + "; size_t *" + api_name_n + ", " + api_name_nn + ";\n"
618    a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n + ", " + "&" + api_name_nn
619    a.cwrap_post = (name + ".resize(" + api_name_nn + "); " +
620                    "for(size_t i = 0; i < " + api_name_nn + "; ++i){ " +
621                    name + "[i].assign(" + api_name + "[i], " + api_name +
622                    "[i] + " + api_name_n + "[i]); " + ns + "Free(" +
623                    api_name + "[i]); } " + ns + "Free(" + api_name + "); " +
624                    ns + "Free(" + api_name_n + ");\n")
625    a.python_pre = (
626        api_name + ", " + api_name_n + ", " + api_name_nn +
627        " = POINTER(POINTER(c_int))(), POINTER(c_size_t)(), c_size_t()")
628    a.python_arg = ("byref(" + api_name + "), byref(" + api_name_n +
629                    "), byref(" + api_name_nn + ")")
630    a.python_return = ("_ovectorvectorint(" + api_name + ", " + api_name_n +
631                       ", " + api_name_nn + ")")
632    a.julia_ctype = "Ptr{Ptr{Ptr{Cint}}}, Ptr{Ptr{Csize_t}}, Ptr{Csize_t}"
633    a.julia_pre = (api_name + " = Ref{Ptr{Ptr{Cint}}}()\n    " + api_name_n +
634                   " = Ref{Ptr{Csize_t}}()\n    " + api_name_nn +
635                   " = Ref{Csize_t}()")
636    a.julia_arg = api_name + ", " + api_name_n + ", " + api_name_nn
637    a.julia_post = ("tmp_" + api_name + " = unsafe_wrap(Array, " + api_name +
638                    "[], " + api_name_nn + "[], own = true)\n    " + "tmp_" +
639                    api_name_n + " = unsafe_wrap(Array, " + api_name_n +
640                    "[], " + api_name_nn + "[], own = true)\n    " + name +
641                    " = [ unsafe_wrap(Array, tmp_" + api_name + "[i], " +
642                    "tmp_" + api_name_n + "[i], own = true) for i in 1:" +
643                    api_name_nn + "[] ]")
644    a.fortran_type = "type(c_ptr), intent(out)"
645    a.fortran_type_post = ("\n            type(c_ptr), intent(out) :: " + name +
646                           "_n\n            integer(c_size_t) :: " + name +"_nn")
647    a.fortran_name_post = ",\n     &      " + name + "_n,\n     &      "  + name + "_nn"
648    return a
649
650
651def ovectorvectorsize(name, value=None, python_value=None, julia_value=None):
652    a = arg(name, value, python_value, julia_value,
653            "std::vector<std::vector<std::size_t> > &", "size_t **", True)
654    api_name = "api_" + name + "_"
655    api_name_n = api_name + "n_"
656    api_name_nn = api_name + "nn_"
657    a.c_pre = "    std::vector<std::vector<std::size_t> > " + api_name + ";\n"
658    a.c_arg = api_name
659    a.c_post = ("    vectorvector2ptrptr(" + api_name + ", " + name + ", " +
660                name + "_n, " + name + "_nn);\n")
661    a.c = "size_t *** " + name + ", size_t ** " + name + "_n, size_t *" + name + "_nn"
662    a.cwrap_pre = "size_t **" + api_name + "; size_t *" + api_name_n + ", " + api_name_nn + ";\n"
663    a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n + ", " + "&" + api_name_nn
664    a.cwrap_post = (name + ".resize(" + api_name_nn + "); " +
665                    "for(size_t i = 0; i < " + api_name_nn + "; ++i){ " +
666                    name + "[i].assign(" + api_name + "[i], " + api_name +
667                    "[i] + " + api_name_n + "[i]); " + ns + "Free(" +
668                    api_name + "[i]); } " + ns + "Free(" + api_name + "); " +
669                    ns + "Free(" + api_name_n + ");\n")
670    a.python_pre = (
671        api_name + ", " + api_name_n + ", " + api_name_nn +
672        " = POINTER(POINTER(c_size_t))(), POINTER(c_size_t)(), c_size_t()")
673    a.python_arg = ("byref(" + api_name + "), byref(" + api_name_n +
674                    "), byref(" + api_name_nn + ")")
675    a.python_return = ("_ovectorvectorsize(" + api_name + ", " + api_name_n +
676                       ", " + api_name_nn + ")")
677    a.julia_ctype = "Ptr{Ptr{Ptr{Csize_t}}}, Ptr{Ptr{Csize_t}}, Ptr{Csize_t}"
678    a.julia_pre = (api_name + " = Ref{Ptr{Ptr{Csize_t}}}()\n    " +
679                   api_name_n + " = Ref{Ptr{Csize_t}}()\n    " + api_name_nn +
680                   " = Ref{Csize_t}()")
681    a.julia_arg = api_name + ", " + api_name_n + ", " + api_name_nn
682    a.julia_post = ("tmp_" + api_name + " = unsafe_wrap(Array, " + api_name +
683                    "[], " + api_name_nn + "[], own = true)\n    " + "tmp_" +
684                    api_name_n + " = unsafe_wrap(Array, " + api_name_n +
685                    "[], " + api_name_nn + "[], own = true)\n    " + name +
686                    " = [ unsafe_wrap(Array, tmp_" + api_name + "[i], " +
687                    "tmp_" + api_name_n + "[i], own = true) for i in 1:" +
688                    api_name_nn + "[] ]")
689    a.fortran_type = "type (c_ptr), intent(out)"
690    a.fortran_type_post = ("\n            type(c_ptr), intent(out) :: " + name +
691                           "_n\n            integer(c_size_t) :: " + name +"_nn")
692    a.fortran_name_post = ",\n     &      " + name + "_n,\n     &      "  + name + "_nn"
693    return a
694
695
696def ovectorvectordouble(name, value=None, python_value=None, julia_value=None):
697    a = arg(name, value, python_value, julia_value,
698            "std::vector<std::vector<double> > &", "double **", True)
699    api_name = "api_" + name + "_"
700    api_name_n = api_name + "n_"
701    api_name_nn = api_name + "nn_"
702    a.c_pre = "    std::vector<std::vector<double> > " + api_name + ";\n"
703    a.c_arg = api_name
704    a.c_post = ("    vectorvector2ptrptr(" + api_name + ", " + name + ", " +
705                name + "_n, " + name + "_nn);\n")
706    a.c = "double *** " + name + ", size_t ** " + name + "_n, size_t *" + name + "_nn"
707    a.cwrap_pre = ("double **" + api_name + "; size_t *" + api_name_n + ", " +
708                   api_name_nn + ";\n")
709    a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n + ", " + "&" + api_name_nn
710    a.cwrap_post = (name + ".resize(" + api_name_nn + "); " +
711                    "for(size_t i = 0; i < " + api_name_nn + "; ++i){ " +
712                    name + "[i].assign(" + api_name + "[i], " + api_name +
713                    "[i] + " + api_name_n + "[i]); " + ns + "Free(" +
714                    api_name + "[i]); } " + ns + "Free(" + api_name + "); " +
715                    ns + "Free(" + api_name_n + ");\n")
716    a.python_pre = (
717        api_name + ", " + api_name_n + ", " + api_name_nn +
718        " = POINTER(POINTER(c_double))(), POINTER(c_size_t)(), c_size_t()")
719    a.python_arg = ("byref(" + api_name + "), byref(" + api_name_n +
720                    "), byref(" + api_name_nn + ")")
721    a.python_return = ("_ovectorvectordouble(" + api_name + ", " + api_name_n +
722                       ", " + api_name_nn + ")")
723    a.julia_ctype = "Ptr{Ptr{Ptr{Cdouble}}}, Ptr{Ptr{Csize_t}}, Ptr{Csize_t}"
724    a.julia_pre = (api_name + " = Ref{Ptr{Ptr{Cdouble}}}()\n    " +
725                   api_name_n + " = Ref{Ptr{Csize_t}}()\n    " + api_name_nn +
726                   " = Ref{Csize_t}()")
727    a.julia_arg = api_name + ", " + api_name_n + ", " + api_name_nn
728    a.julia_post = ("tmp_" + api_name + " = unsafe_wrap(Array, " + api_name +
729                    "[], " + api_name_nn + "[], own = true)\n    " + "tmp_" +
730                    api_name_n + " = unsafe_wrap(Array, " + api_name_n +
731                    "[], " + api_name_nn + "[], own = true)\n    " + name +
732                    " = [ unsafe_wrap(Array, tmp_" + api_name + "[i], " +
733                    "tmp_" + api_name_n + "[i], own = true) for i in 1:" +
734                    api_name_nn + "[] ]")
735    a.fortran_type = "type (c_ptr), intent(out)"
736    a.fortran_type_post = ("\n            type(c_ptr), intent(out) :: " + name +
737                           "_n\n            integer (c_size_t) :: " + name + "_nn")
738    a.fortran_name_post = ",\n     &      " + name + "_n,\n     &      "  + name + "_nn"
739    return a
740
741
742def ovectorvectorpair(name, value=None, python_value=None, julia_value=None):
743    a = arg(name, value, python_value, julia_value,
744            "std::vector<" + ns + "::vectorpair> &", "int **", True)
745    api_name = "api_" + name + "_"
746    api_name_n = api_name + "n_"
747    api_name_nn = api_name + "nn_"
748    a.c_pre = "    std::vector<" + ns + "::vectorpair >" + api_name + ";\n"
749    a.c_arg = api_name
750    a.c_post = ("    vectorvectorpair2intptrptr(" + api_name + ", " + name +
751                ", " + name + "_n, " + name + "_nn);\n")
752    a.c = "int *** " + name + ", size_t ** " + name + "_n, size_t *" + name + "_nn"
753    a.cwrap_pre = "int **" + api_name + "; size_t *" + api_name_n + ", " + api_name_nn + ";\n"
754    a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n + ", " + "&" + api_name_nn
755    a.cwrap_post = (name + ".resize(" + api_name_nn + "); " +
756                    "for(size_t i = 0; i < " + api_name_nn + "; ++i){ " +
757                    name + "[i].resize(" + api_name_n + "[i] / 2); " +
758                    "for(size_t j = 0; j < " + api_name_n + "[i] / 2; ++j){ " +
759                    name + "[i][j].first = " + api_name + "[i][j * 2 + 0]; " +
760                    name + "[i][j].second = " + api_name +
761                    "[i][j * 2 + 1]; } " + ns + "Free(" + api_name +
762                    "[i]); } " + ns + "Free(" + api_name + "); " + ns +
763                    "Free(" + api_name_n + ");\n")
764    a.python_pre = (
765        api_name + ", " + api_name_n + ", " + api_name_nn +
766        " = POINTER(POINTER(c_int))(), POINTER(c_size_t)(), c_size_t()")
767    a.python_arg = ("byref(" + api_name + "), byref(" + api_name_n +
768                    "), byref(" + api_name_nn + ")")
769    a.python_return = ("_ovectorvectorpair(" + api_name + ", " + api_name_n +
770                       ", " + api_name_nn + ")")
771    a.julia_ctype = "Ptr{Ptr{Ptr{Cint}}}, Ptr{Ptr{Csize_t}}, Ptr{Csize_t}"
772    a.julia_pre = (api_name + " = Ref{Ptr{Ptr{Cint}}}()\n    " + api_name_n +
773                   " = Ref{Ptr{Csize_t}}()\n    " + api_name_nn +
774                   " = Ref{Csize_t}()")
775    a.julia_arg = api_name + ", " + api_name_n + ", " + api_name_nn
776    a.julia_post = (
777        "tmp_" + api_name + " = unsafe_wrap(Array, " + api_name + "[], " +
778        api_name_nn + "[], own = true)\n    " + "tmp_" + api_name_n +
779        " = unsafe_wrap(Array, " + api_name_n + "[], " + api_name_nn +
780        "[], own = true)\n    " + name + " = Vector{Tuple{Cint,Cint}}[]\n    " +
781        "resize!(" + name + ", " + api_name_nn + "[])\n    " + "for i in 1:" +
782        api_name_nn + "[]\n    " + "    tmp = unsafe_wrap(Array, tmp_" +
783        api_name + "[i], tmp_" + api_name_n + "[i], own = true)\n    " + "    " +
784        name + "[i] = [(tmp[i], tmp[i+1]) for i in 1:2:length(tmp)]\n    " +
785        "end")
786    a.fortran_type = "type (C_PTR), intent(out)"
787    a.fortran_type_post = ("\n            type(c_ptr), intent(out) :: " + name +
788                           "_n\n            integer (C_SIZE_T) ::" + name +"_nn")
789    a.fortran_name_post = ",\n     &      " + name + "_n,\n     &      "  + name + "_nn"
790    return a
791
792
793# special types
794
795
796def iargcargv():
797    a = arg("", None, None, None, "", "", False)
798    a.cpp = "int argc = 0, char ** argv = 0"
799    a.c_arg = "argc, argv"
800    a.c = "int argc, char ** argv"
801    a.c_pre = ""
802    a.c_post = ""
803    a.cwrap_arg = "argc, argv"
804    a.name = "argv"
805    a.python_value = "[]"
806    a.julia_value = "Vector{String}()"
807    a.python_arg = "api_argc_, api_argv_"
808    a.python_pre = "api_argc_, api_argv_ = _iargcargv(argv)"
809    a.julia_ctype = "Cint, Ptr{Ptr{Cchar}}"
810    a.julia_arg = "length(argv), argv"
811    a.texi = "(argc = 0)}, @code{argv = []"
812    a.fortran_name_pre = "argc,\n     &      "
813    a.fortran_type = "integer (C_INT), value :: argc\n            type (C_PTR)"
814    a.fortran_type_post = "(*)"
815    return a
816
817
818def isizefun(name):
819    a = arg(name, None, None, None, "", "", False)
820    a.cpp = "std::function<double(int, int, double, double, double, double)> " + name
821    a.c_arg = ("std::bind(" + name + ", std::placeholders::_1, " +
822               "std::placeholders::_2, std::placeholders::_3, " +
823               "std::placeholders::_4, std::placeholders::_5, " +
824               "std::placeholders::_6, " + name + "_data)")
825    a.c = ("double (*" + name + ")" +
826           "(int dim, int tag, double x, double y, double z, double lc, void * data), " +
827           "void * " + name + "_data")
828    a.cwrap_pre = "struct " + name + """_caller_  {
829          static double call(int dim, int tag, double x, double y, double z, double lc, void * callbackp_) {
830            return (*static_cast<std::function<double(int, int, double, double, double, double)>*> (callbackp_))(dim, tag, x, y, z, lc);
831          }
832        };
833        // FIXME memory leak
834        auto *""" + name + "_ptr_ = new std::function<double(int, int, double, double, double, double)>(" + name + """);
835"""
836    a.cwrap_arg = "&" + name + "_caller_::call, " + name + "_ptr_"
837    a.python_pre = (
838        "global api_" + name + "_type_\n" + "            api_" + name +
839        "_type_ = " +
840        "CFUNCTYPE(c_double, c_int, c_int, c_double, c_double, c_double, c_double, c_void_p)\n"
841        + "            global api_" + name + "_\n" + "            api_" +
842        name + "_ = api_" + name + "_type_(lambda dim, tag, x, y, z, lc, _ : " +
843        name + "(dim, tag, x, y, z, lc))")
844    a.python_arg = "api_" + name + "_, None"
845    a.julia_pre = (
846        "api_" + name + "__(dim, tag, x, y, z, lc, data) = " + name +
847        "(dim, tag, x, y, z, lc)\n    " + "api_" + name + "_ = @cfunction($api_" +
848        name + "__" +
849        ", Cdouble, (Cint, Cint, Cdouble, Cdouble, Cdouble, Cdouble, Ptr{Cvoid}))")
850    a.julia_arg = "api_" + name + "_, C_NULL"
851    a.julia_ctype = "Ptr{Cvoid}, Ptr{Cvoid}"
852    a.fortran_type = "type (C_FUNPTR)"
853    a.fortran_type_post = " ! to do "
854    return a
855
856
857class Module:
858    def __init__(self, name, doc):
859        self.name = name
860        self.doc = doc
861        self.fs = []
862        self.submodules = []
863
864    def add(self, name, doc, rtype, *args):
865        self.fs.append((rtype, name, args, doc, []))
866
867    def add_special(self, name, doc, special, rtype, *args):
868        self.fs.append((rtype, name, args, doc, special))
869
870    def add_module(self, name, doc):
871        module = Module(name, doc)
872        self.submodules.append(module)
873        return module
874
875
876cpp_header = """// {0}
877//
878// See the LICENSE.txt file in the {3} root directory for license information.
879// Please report all issues on {1}
880
881#ifndef {2}_H
882#define {2}_H
883
884// This file defines the {3} C++ API (v{4}.{5}.{6}).
885//
886// Do not edit it directly: it is automatically generated by `api/gen.py'.
887//
888// By design, the {3} C++ API is purely functional, and only uses elementary
889// types from the C++ standard library. See `tutorial/c++' and `demos/api' for
890// examples.
891
892#include <cmath>
893#include <vector>
894#include <string>
895#include <utility>
896#include <functional>
897
898#define {2}_API_VERSION "{4}.{5}.{6}"
899#define {2}_API_VERSION_MAJOR {4}
900#define {2}_API_VERSION_MINOR {5}
901#define {2}_API_VERSION_PATCH {6}
902
903#if defined({2}_DLL)
904#if defined({2}_DLL_EXPORT)
905#define {2}_API __declspec(dllexport)
906#else
907#define {2}_API __declspec(dllimport)
908#endif
909#else
910#define {2}_API
911#endif
912
913#ifndef M_PI
914#define M_PI (3.14159265358979323846)
915#endif
916
917namespace {7} {{
918
919  // A geometrical entity in the {3} API is represented by two integers: its
920  // dimension (dim = 0, 1, 2 or 3) and its tag (its unique, strictly positive
921  // identifier). When dealing with multiple geometrical entities of possibly
922  // different dimensions, the entities are packed as a vector of (dim, tag)
923  // integer pairs.
924  typedef std::vector<std::pair<int, int> > vectorpair;
925
926}}
927
928"""
929
930cpp_footer = """#endif
931"""
932
933c_header = """/*
934 * {0}
935 *
936 * See the LICENSE.txt file in the {3} root directory for license information.
937 * Please report all issues on {1}
938 */
939
940#ifndef {2}C_H
941#define {2}C_H
942
943/*
944 * This file defines the {3} C API (v{4}.{5}.{6}).
945 *
946 * Do not edit it directly: it is automatically generated by `api/gen.py'.
947 *
948 * By design, the {3} C API is purely functional, and only uses elementary
949 * C types. See `tutorial/c' and `demos/api' for examples.
950 */
951
952#include <stddef.h>
953
954#define {2}_API_VERSION "{4}.{5}.{6}"
955#define {2}_API_VERSION_MAJOR {4}
956#define {2}_API_VERSION_MINOR {5}
957#define {2}_API_VERSION_PATCH {6}
958
959#if defined({2}_DLL)
960#if defined({2}_DLL_EXPORT)
961#define {2}_API __declspec(dllexport)
962#else
963#define {2}_API __declspec(dllimport)
964#endif
965#else
966#define {2}_API
967#endif
968
969{2}_API void {7}Free(void *p);
970{2}_API void *{7}Malloc(size_t n);
971"""
972
973c_footer = """
974#endif
975"""
976
977c_cpp_header = """// {0}
978//
979// See the LICENSE.txt file in the {4} root directory for license information.
980// Please report all issues on {1}
981
982#include <string.h>
983#include <stdlib.h>
984#include "{2}.h"
985
986extern \"C\" {{
987  #include "{2}c.h"
988}}
989
990{3}_API void *{2}Malloc(size_t n)
991{{
992  return malloc(n);
993}}
994
995{3}_API void {2}Free(void *p)
996{{
997  if(p) free(p);
998}}
999"""
1000
1001c_cpp_utils = """
1002void vectorvectorpair2intptrptr(const std::vector<{0}::vectorpair > &v, int ***p, size_t **size, size_t *sizeSize)
1003{{
1004  *p = (int**){0}Malloc(sizeof(int*) * v.size());
1005  *size = (size_t*){0}Malloc(sizeof(size_t) * v.size());
1006  for(size_t i = 0; i < v.size(); ++i)
1007    vectorpair2intptr(v[i], &(*p)[i], &((*size)[i]));
1008  *sizeSize = v.size();
1009}}
1010"""
1011
1012cwrap_header = """// {0}
1013//
1014// See the LICENSE.txt file in the {3} root directory for license information.
1015// Please report all issues on {1}
1016
1017#ifndef {2}_H
1018#define {2}_H
1019
1020// This file redefines the {3} C++ API in terms of the C API (v{4}.{5}.{6}).
1021//
1022// This is provided as a convenience for users of the binary {3} SDK whose C++
1023// compiler ABI is not compatible with the ABI of the C++ compiler used to create
1024// the SDK (and who can thus not directly use the C++ API defined in `{7}.h').
1025//
1026// To use this header file in your C++ code, simply rename it as `{7}.h'.
1027//
1028// Note that using this header file will lead to (slightly) reduced performance
1029// compared to using the native {3} C++ API from the original `{7}.h', as it
1030// entails additional data copies between this C++ wrapper, the C API and the
1031// native C++ code.
1032//
1033// Do not edit this file directly: it is automatically generated by `api/gen.py'.
1034
1035#include <cmath>
1036#include <vector>
1037#include <string>
1038#include <utility>
1039#include <functional>
1040
1041#ifndef M_PI
1042#define M_PI (3.14159265358979323846)
1043#endif
1044
1045extern \"C\" {{
1046  #include "{7}c.h"
1047}}
1048
1049namespace {7} {{
1050
1051  // A geometrical entity in the {3} API is represented by two integers: its
1052  // dimension (dim = 0, 1, 2 or 3) and its tag (its unique, strictly positive
1053  // identifier). When dealing with multiple geometrical entities of possibly
1054  // different dimensions, the entities are packed as a vector of (dim, tag)
1055  // integer pairs.
1056  typedef std::vector<std::pair<int, int> > vectorpair;
1057
1058}}
1059
1060"""
1061
1062cwrap_utils = """
1063template<typename t>
1064{1}void vector2ptr(const std::vector<t> &v, t **p, size_t *size)
1065{{
1066  *p = (t*){0}Malloc(sizeof(t) * v.size());
1067  for(size_t i = 0; i < v.size(); ++i){{
1068    (*p)[i] = v[i];
1069  }}
1070  *size = v.size();
1071}}
1072
1073{1}void vectorpair2intptr(const {0}::vectorpair &v, int **p, size_t *size)
1074{{
1075  *p = (int*){0}Malloc(sizeof(int) * v.size() * 2);
1076  for(size_t i = 0; i < v.size(); ++i){{
1077    (*p)[i * 2 + 0] = v[i].first;
1078    (*p)[i * 2 + 1] = v[i].second;
1079  }}
1080  *size = v.size() * 2;
1081}}
1082
1083{1}void vectorstring2charptrptr(const std::vector<std::string> &v, char ***p, size_t *size)
1084{{
1085  *p = (char**){0}Malloc(sizeof(char*) * v.size());
1086  for(size_t i = 0; i < v.size(); ++i){{
1087    (*p)[i] = (char*){0}Malloc(sizeof(char) * (v[i].size() + 1));
1088    for(size_t j = 0; j < v[i].size(); j++) (*p)[i][j] = v[i][j];
1089    (*p)[i][v[i].size()] = '\\0';
1090  }}
1091  *size = v.size();
1092}}
1093
1094template<typename t>
1095{1}void vectorvector2ptrptr(const std::vector<std::vector<t> > &v, t ***p, size_t **size, size_t *sizeSize)
1096{{
1097  *p = (t**){0}Malloc(sizeof(t*) * v.size());
1098  *size = (size_t*){0}Malloc(sizeof(size_t) * v.size());
1099  for(size_t i = 0; i < v.size(); ++i)
1100    vector2ptr(v[i], &((*p)[i]), &((*size)[i]));
1101  *sizeSize = v.size();
1102}}
1103"""
1104
1105cwrap_footer = """#endif
1106"""
1107
1108python_header = """# {0}
1109#
1110# See the LICENSE.txt file in the {2} root directory for license information.
1111# Please report all issues on {1}
1112
1113# This file defines the {2} Python API (v{3}.{4}.{5}).
1114#
1115# Do not edit it directly: it is automatically generated by `api/gen.py'.
1116#
1117# By design, the {2} Python API is purely functional, and only uses elementary
1118# Python types (as well as `numpy' arrays if `numpy' is available). See
1119# `tutorial/python' and `demos/api' for examples.
1120
1121from ctypes import *
1122from ctypes.util import find_library
1123import signal
1124import os
1125import platform
1126from math import pi
1127
1128{6}_API_VERSION = "{3}.{4}.{5}"
1129{6}_API_VERSION_MAJOR = {3}
1130{6}_API_VERSION_MINOR = {4}
1131{6}_API_VERSION_PATCH = {5}
1132
1133__version__ = {6}_API_VERSION
1134
1135oldsig = signal.signal(signal.SIGINT, signal.SIG_DFL)
1136moduledir = os.path.dirname(os.path.realpath(__file__))
1137if platform.system() == "Windows":
1138    libname = "{7}-{3}.{4}.dll"
1139    libdir = os.path.dirname(moduledir)
1140elif platform.system() == "Darwin":
1141    libname = "lib{7}.{3}.{4}.dylib"
1142    libdir = os.path.dirname(os.path.dirname(moduledir))
1143else:
1144    libname = "lib{7}.so.{3}.{4}"
1145    libdir = os.path.dirname(os.path.dirname(moduledir))
1146
1147libpath = os.path.join(libdir, libname)
1148if not os.path.exists(libpath):
1149    libpath = os.path.join(libdir, "Lib", libname)
1150if not os.path.exists(libpath):
1151    libpath = os.path.join(moduledir, libname)
1152if not os.path.exists(libpath):
1153    if platform.system() == "Windows":
1154        libpath = find_library("{7}-{3}.{4}")
1155    else:
1156        libpath = find_library("{7}")
1157
1158lib = CDLL(libpath)
1159
1160try_numpy = True # set this to False to never use numpy
1161
1162use_numpy = False
1163if try_numpy:
1164    try:
1165        import numpy
1166        try:
1167            from weakref import finalize as weakreffinalize
1168        except:
1169            from backports.weakref import finalize as weakreffinalize
1170        use_numpy = True
1171    except:
1172        pass
1173
1174# Utility functions, not part of the Gmsh Python API
1175
1176def _ostring(s):
1177    sp = s.value.decode("utf-8")
1178    lib.{7}Free(s)
1179    return sp
1180
1181def _ovectorpair(ptr, size):
1182    v = list((ptr[i * 2], ptr[i * 2 + 1]) for i in range(size//2))
1183    lib.{7}Free(ptr)
1184    return v
1185
1186def _ovectorint(ptr, size):
1187    if use_numpy:
1188        if size == 0 :
1189            lib.{7}Free(ptr)
1190            return numpy.ndarray((0,),numpy.int32)
1191        v = numpy.ctypeslib.as_array(ptr, (size, ))
1192        weakreffinalize(v, lib.{7}Free, ptr)
1193    else:
1194        v = list(ptr[i] for i in range(size))
1195        lib.{7}Free(ptr)
1196    return v
1197
1198def _ovectorsize(ptr, size):
1199    if use_numpy:
1200        if size == 0 :
1201            lib.{7}Free(ptr)
1202            return numpy.ndarray((0,),numpy.uintp)
1203        v = numpy.ctypeslib.as_array(ptr, (size, ))
1204        weakreffinalize(v, lib.{7}Free, ptr)
1205    else:
1206        v = list(ptr[i] for i in range(size))
1207        lib.{7}Free(ptr)
1208    return v
1209
1210def _ovectordouble(ptr, size):
1211    if use_numpy:
1212        if size == 0 :
1213            lib.{7}Free(ptr)
1214            return numpy.ndarray((0,),numpy.float64)
1215        v = numpy.ctypeslib.as_array(ptr, (size, ))
1216        weakreffinalize(v, lib.{7}Free, ptr)
1217    else:
1218        v = list(ptr[i] for i in range(size))
1219        lib.{7}Free(ptr)
1220    return v
1221
1222def _ovectorstring(ptr, size):
1223    v = list(_ostring(cast(ptr[i], c_char_p)) for i in range(size))
1224    lib.{7}Free(ptr)
1225    return v
1226
1227def _ovectorvectorint(ptr, size, n):
1228    v = [_ovectorint(pointer(ptr[i].contents), size[i]) for i in range(n.value)]
1229    lib.{7}Free(size)
1230    lib.{7}Free(ptr)
1231    return v
1232
1233def _ovectorvectorsize(ptr, size, n):
1234    v = [_ovectorsize(pointer(ptr[i].contents), size[i]) for i in range(n.value)]
1235    lib.{7}Free(size)
1236    lib.{7}Free(ptr)
1237    return v
1238
1239def _ovectorvectordouble(ptr, size, n):
1240    v = [_ovectordouble(pointer(ptr[i].contents), size[i]) for i in range(n.value)]
1241    lib.{7}Free(size)
1242    lib.{7}Free(ptr)
1243    return v
1244
1245def _ovectorvectorpair(ptr, size, n):
1246    v = [_ovectorpair(pointer(ptr[i].contents), size[i]) for i in range(n.value)]
1247    lib.{7}Free(size)
1248    lib.{7}Free(ptr)
1249    return v
1250
1251def _ivectorint(o):
1252    if use_numpy:
1253        array = numpy.ascontiguousarray(o, numpy.int32)
1254        if(len(o) and array.ndim != 1):
1255            raise Exception("Invalid data for input vector of integers")
1256        ct = array.ctypes
1257        ct.array = array
1258        return ct, c_size_t(len(o))
1259    else:
1260        return (c_int * len(o))(*o), c_size_t(len(o))
1261
1262def _ivectorsize(o):
1263    if use_numpy:
1264        array = numpy.ascontiguousarray(o, numpy.uintp)
1265        if(len(o) and array.ndim != 1):
1266            raise Exception("Invalid data for input vector of sizes")
1267        ct = array.ctypes
1268        ct.array = array
1269        return ct, c_size_t(len(o))
1270    else:
1271        return (c_size_t * len(o))(*o), c_size_t(len(o))
1272
1273def _ivectordouble(o):
1274    if use_numpy:
1275        array = numpy.ascontiguousarray(o, numpy.float64)
1276        if(len(o) and array.ndim != 1):
1277            raise Exception("Invalid data for input vector of doubles")
1278        ct = array.ctypes
1279        ct.array = array
1280        return  ct, c_size_t(len(o))
1281    else:
1282        return (c_double * len(o))(*o), c_size_t(len(o))
1283
1284def _ivectorpair(o):
1285    if use_numpy:
1286        array = numpy.ascontiguousarray(o, numpy.int32)
1287        if(len(o) and (array.ndim != 2 or array.shape[1] != 2)):
1288            raise Exception("Invalid data for input vector of pairs")
1289        ct = array.ctypes
1290        ct.array = array
1291        return ct, c_size_t(len(o) * 2)
1292    else:
1293        if(len(o) and len(o[0]) != 2):
1294            raise Exception("Invalid data for input vector of pairs")
1295        return ((c_int * 2) * len(o))(*o), c_size_t(len(o) * 2)
1296
1297def _ivectorstring(o):
1298    return (c_char_p * len(o))(*(s.encode() for s in o)), c_size_t(len(o))
1299
1300def _ivectorvectorint(os):
1301    n = len(os)
1302    parrays = [_ivectorint(o) for o in os]
1303    sizes = (c_size_t * n)(*(a[1] for a in parrays))
1304    arrays = (POINTER(c_int) * n)(*(cast(a[0], POINTER(c_int)) for a in parrays))
1305    arrays.ref = [a[0] for a in parrays]
1306    size = c_size_t(n)
1307    return arrays, sizes, size
1308
1309def _ivectorvectorsize(os):
1310    n = len(os)
1311    parrays = [_ivectorsize(o) for o in os]
1312    sizes = (c_size_t * n)(*(a[1] for a in parrays))
1313    arrays = (POINTER(c_size_t) * n)(*(cast(a[0], POINTER(c_size_t)) for a in parrays))
1314    arrays.ref = [a[0] for a in parrays]
1315    size = c_size_t(n)
1316    return arrays, sizes, size
1317
1318def _ivectorvectordouble(os):
1319    n = len(os)
1320    parrays = [_ivectordouble(o) for o in os]
1321    sizes = (c_size_t * n)(*(a[1] for a in parrays))
1322    arrays = (POINTER(c_double) * n)(*(cast(a[0], POINTER(c_double)) for a in parrays))
1323    arrays.ref = [a[0] for a in parrays]
1324    size = c_size_t(n)
1325    return arrays, sizes, size
1326
1327def _iargcargv(o):
1328    return c_int(len(o)), (c_char_p * len(o))(*(s.encode() for s in o))
1329
1330# Gmsh Python API begins here
1331"""
1332
1333julia_header = """# {0}
1334#
1335# See the LICENSE.txt file in the {2} root directory for license information.
1336# Please report all issues on {1}
1337
1338# This file defines the {2} Julia API (v{3}.{4}.{5}).
1339#
1340# Do not edit it directly: it is automatically generated by `api/gen.py'.
1341#
1342# By design, the {2} Julia API is purely functional, and only uses elementary
1343# Julia types. See `tutorial/julia' and `demos/api' for examples.
1344"""
1345
1346
1347fortran_header = """c
1348c  {0}
1349c
1350c  See the LICENSE.txt file in the {3} root directory for license information.
1351c  Please report all issues on {1}
1352c
1353
1354!DEC$ IF DEFINED ({2}F_H)
1355!DEC$ ELSE
1356!DEC$ DEFINE {2}F_H
1357
1358c
1359c  This file defines the {3} Fortran API (v{4}.{5}.{6}).
1360c
1361c  Do not edit it directly: it is automatically generated by `api/gen.py'.
1362c
1363c  By design, the {3} Fortran API is purely functional, and only uses elementary
1364c  Fortran types. See `tutorial/fortran' and `demos/api' for examples.
1365c
1366
1367!DEC$ DEFINE {2}_API_VERSION_MAJOR = {4}
1368!DEC$ DEFINE {2}_API_VERSION_MINOR = {5}
1369!DEC$ DEFINE {2}_API_VERSION_PATCH = {6}
1370
1371      module gmsh_fortran
1372
1373        use, intrinsic :: iso_c_binding
1374
1375        character(len = 5), parameter :: {2}_API_VERSION = "{4}.{5}.{6}"
1376        real(c_double), parameter::M_PI = 3.14159265358979323846d0
1377
1378        interface
1379"""
1380
1381fortran_footer = """
1382        end interface
1383      end module gmsh_fortran
1384
1385!DEC$ ENDIF
1386"""
1387
1388
1389def capi(s):
1390    return s[:1].upper() + s[1:]
1391
1392
1393class API:
1394    def __init__(
1395        self,
1396        version_major,
1397        version_minor,
1398        version_patch,
1399        namespace = "gmsh",
1400        code = "Gmsh",
1401        copyright = "Gmsh - Copyright (C) 1997-2021 C. Geuzaine, J.-F. Remacle",
1402        issues = "https://gitlab.onelab.info/gmsh/gmsh/issues."):
1403        self.version_major = version_major
1404        self.version_minor = version_minor
1405        self.version_patch = version_patch
1406        global ns
1407        ns = namespace
1408        self.code = code
1409        self.copyright = copyright
1410        self.issues = issues
1411        self.modules = []
1412        self.api_lineno = {'cpp': {}, 'c': {}, 'py': {}, 'jl': {}, 'f': {}}
1413
1414    def add_module(self, name, doc):
1415        module = Module(name, doc)
1416        self.modules.append(module)
1417        return module
1418
1419    def fwrite(self, f, s):
1420        self.current_lineno += s.count('\n')
1421        f.write(s)
1422
1423    def flog(self, lang, fname):
1424        self.api_lineno[lang][fname] = self.current_lineno
1425
1426    def write_cpp(self):
1427        def write_module(module, indent, cpp_mpath):
1428            cpp_mpath += module.name + "::"
1429            self.fwrite(
1430                f, indent + "namespace " + module.name + " { // " +
1431                capi(module.doc) + "\n\n")
1432            indent += "  "
1433            for rtype, name, args, doc, special in module.fs:
1434                rt = rtype.rcpp_type if rtype else "void"
1435                self.fwrite(
1436                    f,
1437                    indent + "// " + cpp_mpath + name + "\n" + indent + "//\n")
1438                self.fwrite(
1439                    f, indent + "// " + ("\n" + indent + "// ").join(
1440                        textwrap.wrap(doc, 80 - len(indent))) + "\n")
1441                fnameapi = indent + ns.upper(
1442                ) + "_API " + rt + " " + name + "("
1443                self.flog('cpp', cpp_mpath.replace('::', '/') + name)
1444                self.fwrite(f, fnameapi)
1445                if args:
1446                    self.fwrite(f, (",\n" + ' ' * len(fnameapi)).join(
1447                        a.cpp for a in args))
1448                self.fwrite(f, ");\n\n")
1449            for m in module.submodules:
1450                write_module(m, indent, cpp_mpath)
1451            self.fwrite(f,
1452                        indent[:-2] + "} // namespace " + module.name + "\n\n")
1453
1454        self.current_lineno = 1
1455        with open(ns + ".h", "w") as f:
1456            self.fwrite(
1457                f,
1458                cpp_header.format(self.copyright, self.issues, ns.upper(),
1459                                  self.code, self.version_major,
1460                                  self.version_minor, self.version_patch, ns))
1461            for m in self.modules:
1462                write_module(m, "", "")
1463            self.fwrite(f, cpp_footer)
1464
1465    def write_c(self):
1466        def write_module(module, c_namespace, cpp_namespace, indent):
1467            cpp_namespace += module.name + "::"
1468            if c_namespace:
1469                c_namespace += module.name[0].upper() + module.name[1:]
1470            else:
1471                c_namespace = module.name
1472            fcwrap.write(indent + "namespace " + module.name + " { // " +
1473                         capi(module.doc) + "\n\n")
1474            indent += "  "
1475            for rtype, name, args, doc, special in module.fs:
1476                # *c.h
1477                fname = c_namespace + name[0].upper() + name[1:]
1478                self.fwrite(
1479                    f,
1480                    "\n/* " + "\n * ".join(textwrap.wrap(doc, 75)) + " */\n")
1481                fnameapi = ns.upper() + "_API " + (rtype.rc_type if rtype else
1482                                                   "void") + " " + fname + "("
1483                self.flog('c', cpp_namespace.replace('::', '/') + name)
1484                self.fwrite(
1485                    f, fnameapi + (",\n" + ' ' * len(fnameapi)).join(
1486                        list((a.c for a in args + (oint("ierr"), )))) + ");\n")
1487
1488                if "rawc" not in special:
1489                    # *c.cpp
1490                    fc.write(ns.upper() + "_API " +
1491                             (rtype.rc_type if rtype else "void"))
1492                    fc.write(
1493                        " " + fname + "(" +
1494                        ", ".join(list((a.c for a in args +
1495                                        (oint("ierr"), )))) + ")\n{\n")
1496                    if rtype:
1497                        fc.write("  " + rtype.rc_type + " result_api_ = 0;\n")
1498                    fc.write("  if(ierr) *ierr = 0;\n")
1499                    fc.write("  try {\n")
1500                    fc.write("".join((a.c_pre for a in args)))
1501                    fc.write("    ")
1502                    if rtype:
1503                        fc.write("result_api_ = ")
1504                    fc.write(cpp_namespace + name + "(" +
1505                             ", ".join(list((a.c_arg for a in args))) + ");\n")
1506                    fc.write("".join((a.c_post for a in args)))
1507                    fc.write("  }\n  catch(...){\n    " +
1508                             "if(ierr) *ierr = 1;\n  }\n")
1509                    if rtype:
1510                        fc.write("  return result_api_;\n")
1511                    fc.write("}\n\n")
1512                # *.h_cwrap
1513                fcwrap.write(indent + "// " +
1514                             ("\n" + indent +
1515                              "// ").join(textwrap.wrap(doc, 80 -
1516                                                        len(indent))) + "\n")
1517                rt = rtype.rcpp_type if rtype else "void"
1518                fnameapi = indent + "inline " + rt + " " + name + "("
1519                fcwrap.write(fnameapi)
1520                if args:
1521                    fcwrap.write(
1522                        (",\n" + ' ' * len(fnameapi)).join(a.cpp
1523                                                           for a in args))
1524                fcwrap.write(")\n" + indent + "{\n" + indent +
1525                             "  int ierr = 0;\n")
1526                for a in args:
1527                    if a.cwrap_pre:
1528                        fcwrap.write(indent + "  " + a.cwrap_pre)
1529                fcwrap.write(indent + "  ")
1530                if rtype:
1531                    fcwrap.write(rt + " result_api_ = ")
1532                fcwrap.write(fname + "(" + ", ".join((a.cwrap_arg
1533                                                      for a in args)))
1534                if args:
1535                    fcwrap.write(", &ierr);\n")
1536                else:
1537                    fcwrap.write("&ierr);\n")
1538                if name == 'getLastError':  # special case for getLastError() function
1539                    fcwrap.write(
1540                        indent + "  " +
1541                        'if(ierr) throw "Could not get last error";\n')
1542                else:
1543                    fcwrap.write(indent + "  " +
1544                                 "if(ierr) throwLastError();\n")
1545                for a in args:
1546                    if a.cwrap_post:
1547                        fcwrap.write(indent + "  " + a.cwrap_post)
1548                if rtype:
1549                    fcwrap.write(indent + "  " + "return result_api_;\n")
1550                fcwrap.write(indent + "}\n\n")
1551            for m in module.submodules:
1552                write_module(m, c_namespace, cpp_namespace, indent)
1553            fcwrap.write(indent[:-2] + "} // namespace " + module.name +
1554                         "\n\n")
1555
1556        self.current_lineno = 1
1557        with open(ns + "c.h", "w") as f:
1558            with open(ns + "c.cpp", "w") as fc:
1559                with open(ns + ".h_cwrap", "w") as fcwrap:
1560                    self.fwrite(
1561                        f,
1562                        c_header.format(self.copyright, self.issues,
1563                                        ns.upper(), self.code,
1564                                        self.version_major, self.version_minor,
1565                                        self.version_patch, ns))
1566                    fc.write(
1567                        c_cpp_header.format(self.copyright, self.issues, ns,
1568                                            ns.upper(), self.code))
1569                    fc.write(cwrap_utils.format(ns, ""))
1570                    fc.write(c_cpp_utils.format(ns))
1571                    fc.write("\n")
1572                    fcwrap.write(
1573                        cwrap_header.format(self.copyright, self.issues,
1574                                            ns.upper(), self.code,
1575                                            self.version_major,
1576                                            self.version_minor,
1577                                            self.version_patch, ns))
1578                    fcwrap.write("namespace " + ns + " {\n")
1579                    s = cwrap_utils.format(ns, "inline ").split('\n')
1580                    for line in s:
1581                        fcwrap.write("  " + line + "\n")
1582                    fcwrap.write("  inline void throwLastError()\n")
1583                    fcwrap.write("  {\n")
1584                    fcwrap.write('     int ierr = 0;\n')
1585                    fcwrap.write('     char *api_error_;\n')
1586                    fcwrap.write(
1587                        '     gmshLoggerGetLastError(&api_error_, &ierr);\n')
1588                    fcwrap.write(
1589                        '     if(ierr) throw "Could not get last error";\n')
1590                    fcwrap.write(
1591                        '     std::string error = std::string(api_error_);\n')
1592                    fcwrap.write('     gmshFree(api_error_);\n')
1593                    fcwrap.write('     throw error;\n')
1594                    fcwrap.write("  }\n\n")
1595                    fcwrap.write("}\n\n")
1596                    for module in self.modules:
1597                        write_module(module, "", "", "")
1598                    self.fwrite(f, c_footer)
1599                    fcwrap.write(cwrap_footer)
1600
1601    def write_python(self):
1602        def parg(a):
1603            return a.name + (("=" + a.python_value) if a.python_value else "")
1604
1605        def write_function(f, fun, c_mpath, py_mpath, indent):
1606            (rtype, name, args, doc, special) = fun
1607            if "onlycc++" in special: return
1608            if "nopython" in special: return
1609            iargs = list(a for a in args if not a.out)
1610            oargs = list(a for a in args if a.out)
1611            self.fwrite(f, "\n")
1612            if c_mpath != ns:
1613                self.fwrite(f, indent + "@staticmethod\n")
1614            self.flog('py', py_mpath.replace('.', '/') + name)
1615            self.fwrite(
1616                f, indent + "def " + name + "(" + ", ".join(
1617                    (parg(a) for a in iargs)) + "):\n")
1618            ind = indent + "    "
1619            self.fwrite(f, ind + '"""\n')
1620            self.fwrite(
1621                f, ind + py_mpath + name + "(" +
1622                ", ".join(parg(a) for a in iargs) + ")\n\n")
1623            self.fwrite(
1624                f,
1625                ind + ("\n" + ind).join(textwrap.wrap(doc, 75)) + "\n")
1626            if rtype or oargs:
1627                self.fwrite(
1628                    f, "\n" + ind + "Return " +
1629                    ", ".join(([("an " if rtype.rtexi_type ==
1630                                 "integer value" else "a ") +
1631                                rtype.rtexi_type] if rtype else []) +
1632                              [("`" + a.name + "'") for a in oargs]) + ".\n")
1633            self.fwrite(f, ind + '"""\n')
1634            for a in args:
1635                if a.python_pre: self.fwrite(f, ind + a.python_pre + "\n")
1636            self.fwrite(f, ind + "ierr = c_int()\n")
1637            c_name = c_mpath + name[0].upper() + name[1:]
1638            if rtype is odouble:
1639                self.fwrite(f, ind + "lib." + c_name + ".restype = c_double\n")
1640            self.fwrite(
1641                f, ind + "api_result_ = " if
1642                ((rtype is oint) or (rtype is odouble)) else (ind))
1643            self.fwrite(
1644                f, "lib." + c_name + "(\n    " + ind +
1645                (",\n" + ind + "    ").join(
1646                    tuple((a.python_arg
1647                           for a in args)) + ("byref(ierr)", )) + ")\n")
1648            if name == "finalize":  # special case for finalize() function
1649                self.fwrite(f, ind + "if oldsig is not None:\n")
1650                self.fwrite(
1651                    f, ind + "    signal.signal(signal.SIGINT, oldsig)\n")
1652            self.fwrite(f, ind + "if ierr.value != 0:\n")
1653            if name == "getLastError":  # special case for getLastError() function
1654                self.fwrite(
1655                    f, ind +
1656                    "    raise Exception('Could not get last error')\n")
1657            else:
1658                self.fwrite(
1659                    f, ind + "    raise Exception(logger.getLastError())\n")
1660            r = (["api_result_"]) if rtype else []
1661            r += list((o.python_return for o in oargs))
1662            if len(r) != 0:
1663                if len(r) == 1:
1664                    self.fwrite(f, ind + "return " + r[0] + "\n")
1665                else:
1666                    self.fwrite(
1667                        f, ind + "return (\n" + ind + "    " +
1668                        (",\n" + ind + "    ").join(r) + ")\n")
1669            # define alias with underscore (standard python style)
1670            name_ = re.sub('([A-Z]+)', r'_\1', name).lower()
1671            if name != name_:
1672                self.fwrite(f, indent + name_ + " = " + name + "\n")
1673
1674        def write_module(f, m, c_mpath, py_mpath, indent):
1675            if c_mpath:
1676                c_mpath += m.name[0].upper() + m.name[1:]
1677                py_mpath += m.name + "."
1678            else:
1679                c_mpath = m.name
1680                py_mpath = m.name + "."
1681            for fun in m.fs:
1682                write_function(f, fun, c_mpath, py_mpath, indent)
1683            for module in m.submodules:
1684                self.fwrite(f,
1685                            "\n\n" + indent + "class " + module.name + ":\n")
1686                indentm = indent + "    "
1687                self.fwrite(f, indentm + '"""\n')
1688                self.fwrite(
1689                    f, indentm + ("\n" + indentm).join(
1690                        textwrap.wrap(capi(module.doc), 75)) + "\n")
1691                self.fwrite(f, indentm + '"""\n')
1692                write_module(f, module, c_mpath, py_mpath, indentm)
1693
1694        self.current_lineno = 1
1695        with open(ns + ".py", "w") as f:
1696            self.fwrite(
1697                f,
1698                python_header.format(self.copyright, self.issues, self.code,
1699                                     self.version_major, self.version_minor,
1700                                     self.version_patch, ns.upper(), ns))
1701            for module in self.modules:
1702                write_module(f, module, "", "", "")
1703
1704    def write_julia(self):
1705        def parg(a):
1706            return a.name + ((" = " + a.julia_value) if a.julia_value else "")
1707
1708        def write_function(f, fun, c_mpath, jl_mpath):
1709            (rtype, name, args, doc, special) = fun
1710            if "onlycc++" in special: return
1711            if "nojulia" in special: return
1712            iargs = list(a for a in args if not a.out)
1713            oargs = list(a for a in args if a.out)
1714            self.fwrite(f, '\n"""\n    ')
1715            self.fwrite(
1716                f, jl_mpath + name + "(" + ", ".join(parg(a)
1717                                                     for a in iargs) + ")\n\n")
1718            self.fwrite(
1719                f, "\n".join(textwrap.wrap(doc, 80)).replace("'", "`") + "\n")
1720            if rtype or oargs:
1721                self.fwrite(
1722                    f, "\nReturn " +
1723                    ", ".join(([("an " if rtype.rtexi_type ==
1724                                 "integer value" else "a ") +
1725                                rtype.rtexi_type] if rtype else []) +
1726                              [("`" + a.name + "`") for a in oargs]) + ".\n")
1727            self.fwrite(f, '"""\n')
1728            self.flog('jl', jl_mpath.replace('.', '/') + name)
1729            self.fwrite(
1730                f, "function " + name + "(" + ", ".join(
1731                    (parg(a) for a in iargs)) + ")\n")
1732            for a in args:
1733                if a.julia_pre: self.fwrite(f, "    " + a.julia_pre + "\n")
1734            self.fwrite(f, "    ierr = Ref{Cint}()\n    ")
1735            self.fwrite(
1736                f, "api_result_ = " if
1737                ((rtype is oint) or (rtype is odouble)) else "")
1738            c_name = c_mpath + name[0].upper() + name[1:]
1739            self.fwrite(
1740                f, "ccall((:" + c_name + ", " +
1741                ("" if c_mpath == ns else ns + ".") + "lib), " +
1742                ("Cvoid" if rtype is None else rtype.rjulia_type) + ",\n" +
1743                " " * 10 + "(" + ", ".join(
1744                    (tuple(a.julia_ctype for a in args) + ("Ptr{Cint}", ))) +
1745                ("," if not len(args) else "") + "),\n" + " " * 10 +
1746                ", ".join(tuple(a.julia_arg
1747                                for a in args) + ("ierr", )) + ")\n")
1748            if name == "getLastError":  # special case for getLastError() function
1749                self.fwrite(
1750                    f,
1751                    '    ierr[] != 0 && error("Could not get last error")\n')
1752            else:
1753                self.fwrite(
1754                    f,
1755                    '    ierr[] != 0 && error(gmsh.logger.getLastError())\n')
1756            for a in args:
1757                if a.julia_post: self.fwrite(f, "    " + a.julia_post + "\n")
1758            r = (["api_result_"]) if rtype else []
1759            r += list((o.julia_return for o in oargs))
1760            self.fwrite(f, "    return ")
1761            if len(r) == 0:
1762                self.fwrite(f, "nothing")
1763            else:
1764                self.fwrite(f, ", ".join(r))
1765            self.fwrite(f, "\nend\n")
1766            # define alias with underscore (closer to Julia style)
1767            name_ = re.sub('([A-Z]+)', r'_\1', name).lower()
1768            if name != name_:
1769                self.fwrite(f, "const " + name_ + " = " + name + "\n")
1770
1771        def write_module(f, m, c_mpath, jl_mpath, level):
1772            self.fwrite(f, '\n"""\n    ')
1773            self.fwrite(f, "module " + jl_mpath + m.name + "\n\n")
1774            self.fwrite(f, "\n".join(textwrap.wrap(capi(m.doc), 80)) + "\n")
1775            self.fwrite(f, '"""\n')
1776            self.fwrite(f, "module " + m.name + "\n\n")
1777            if level == 1:
1778                self.fwrite(
1779                    f, 'const {0}_API_VERSION = "{1}.{2}.{3}"\n'.format(
1780                        ns.upper(), self.version_major, self.version_minor,
1781                        self.version_patch))
1782                self.fwrite(
1783                    f, 'const {0}_API_VERSION_MAJOR = {1}\n'.format(
1784                        ns.upper(), self.version_major))
1785                self.fwrite(
1786                    f, 'const {0}_API_VERSION_MINOR = {1}\n'.format(
1787                        ns.upper(), self.version_minor))
1788                self.fwrite(
1789                    f, 'const {0}_API_VERSION_PATCH = {1}\n'.format(
1790                        ns.upper(), self.version_patch))
1791                self.fwrite(f, 'const libdir = dirname(@__FILE__)\n')
1792                self.fwrite(
1793                    f, 'const libname = Sys.iswindows() ? "' + ns +
1794                    '-{0}.{1}'.format(self.version_major, self.version_minor) +
1795                    '.dll" : "lib' + ns + '"\n')
1796                self.fwrite(f, 'import Libdl\n')
1797                self.fwrite(
1798                    f, 'const lib = Libdl.find_library([libname], [libdir])\n')
1799            else:
1800                self.fwrite(f, "import " + ("." * level) + ns + "\n")
1801            if c_mpath:
1802                c_mpath += m.name[0].upper() + m.name[1:]
1803                jl_mpath += m.name + "."
1804            else:
1805                c_mpath = m.name
1806                jl_mpath = m.name + "."
1807            for fun in m.fs:
1808                write_function(f, fun, c_mpath, jl_mpath)
1809            for module in m.submodules:
1810                write_module(f, module, c_mpath, jl_mpath, level + 1)
1811            self.fwrite(f, "\nend # end of module " + m.name + "\n")
1812
1813        self.current_lineno = 1
1814        with open(ns + ".jl", "w") as f:
1815            self.fwrite(
1816                f,
1817                julia_header.format(self.copyright, self.issues, self.code,
1818                                    self.version_major, self.version_minor,
1819                                    self.version_patch))
1820            for module in self.modules:
1821                write_module(f, module, "", "", 1)
1822
1823
1824    def write_fortran(self):
1825        def write_module(module, c_namespace, cpp_namespace, indent):
1826            cpp_namespace += module.name + "::"
1827            if c_namespace:
1828                c_namespace += module.name[0].upper() + module.name[1:]
1829            else:
1830                c_namespace = module.name
1831
1832            indent += "  "
1833            for rtype, name, args, doc, special in module.fs:
1834                # *f.h
1835                fname = c_namespace + name[0].upper() + name[1:]
1836
1837# output doc
1838                self.fwrite(
1839                    f,
1840                    "\n!  " + "\n!  ".join(textwrap.wrap(doc, 75)) + "\n")
1841                fnameapi = "!  " + ns.upper() + "_API " + (rtype.rc_type if rtype else
1842                                                   "void") + " " + fname + "("
1843                self.flog('f', cpp_namespace.replace('::', '/') + name)
1844
1845                if (len(fname) < 45) :
1846
1847# output fortran header
1848                        fnamef = ' '*8 + ("function" if rtype else "subroutine") + ' ' + fname + "("
1849                        self.fwrite(
1850                            f, fnamef + "\n     &      " + (",\n     &      ").join(
1851                                list((a.fortran_name_pre + a.name + a.fortran_name_post for a in args + (oint("ierr"), )))) + ")\n")
1852
1853                        left = "          "
1854                        self.fwrite(
1855                            f,
1856                            "     &    bind(C, name = \"" + fname + "\")" + "\n")
1857                        self.fwrite(
1858                            f,
1859                            left + "use, intrinsic :: iso_c_binding" + "\n")
1860                        if rtype :
1861                            self.fwrite(
1862                                f,
1863                                left + (rtype.fortran_type) + "::" + fname + "\n")
1864
1865                        self.fwrite(
1866                            f, ("").join(
1867                            list(( left + "  " + a.fortran_type + "::"
1868                                   + a.name + a.fortran_type_post
1869                                   + "\n" for a in args + (oint("ierr"), ) ))
1870                                        )
1871                                   )
1872
1873                        self.fwrite(
1874                            f,
1875                            left + "end " + ("function" if rtype else "subroutine")
1876                            + " " + fname + "\n")
1877
1878            for m in module.submodules:
1879                write_module(m, c_namespace, cpp_namespace, indent)
1880
1881        self.current_lineno = 1
1882        with open(ns + "f.h", "w") as f:
1883                    self.fwrite(
1884                        f,
1885                        fortran_header.format(self.copyright, self.issues,
1886                                        ns.upper(), self.code,
1887                                        self.version_major, self.version_minor,
1888                                        self.version_patch, ns))
1889                    for module in self.modules:
1890                        write_module(module, "", "", "")
1891                    self.fwrite(f, fortran_footer)
1892
1893
1894    def write_texi(self):
1895        def tryint(s):
1896            try:
1897                return int(s)
1898            except:
1899                return s
1900
1901        def alphanum_key(s):
1902            return [tryint(c) for c in re.split('([0-9]+)', s)]
1903
1904        def get_file_data(path, ext):
1905            data = []
1906            for r, d, f in os.walk(path):
1907                for file in f:
1908                    if file.endswith(ext):
1909                        filename = os.path.join(r, file)
1910                        contents = []
1911                        for line in open(filename, 'r'):
1912                            contents.append(line)
1913                        data.append([filename, contents])
1914            data.sort(key=lambda x: alphanum_key(x[0]))
1915            return data
1916
1917        def find_function(lang, name, data):
1918            only_unique = False  # only report unique matches?
1919            in_comments = False  # report matches in comments?
1920            if lang == 'Python':
1921                func = name.replace('/', '.')
1922                comment = '#'
1923            else:
1924                func = name.replace('/', '::')
1925                comment = '//'
1926            match = []
1927            unique = set()
1928            for file in data:
1929                l = 0
1930                for line in file[1]:
1931                    l = l + 1
1932                    # allow white space between func name and (
1933                    if re.search(func + '\s*\(', line):
1934                        strip = re.sub(r'\s+', '', line)
1935                        # don't report matches in comments
1936                        if not in_comments and strip.startswith(comment):
1937                            continue
1938                        # only report a given match once
1939                        if (not only_unique) or (strip not in unique):
1940                            match.append((file[0], l))
1941                            unique.add(strip)
1942                            break  # report only one match per file
1943                        else:
1944                            unique.add(strip)
1945            return match
1946
1947        def write_module(module, path, node, node_next, node_prev, cpp_data,
1948                         py_data):
1949            f.write("@node " + node + ", " + node_next + ", " + node_prev +
1950                    ", Gmsh API\n")
1951            f.write("@section Namespace @code{" + path + "}: " + module.doc +
1952                    "\n\n")
1953            f.write("@ftable @code\n")
1954            for rtype, name, args, doc, special in module.fs:
1955                tfull = path + '/' + name
1956                if len(tfull) > 40:  # insert discretionary hyphen if too long
1957                    for i in range(40, len(tfull)):
1958                        if tfull[i].isupper():
1959                            tfull = tfull[:i] + '@-' + tfull[i:]
1960                            break
1961                f.write("@item " + tfull + "\n")
1962                tdoc = doc.replace("`", "@code{").replace("'", "}")
1963                f.write("\n".join(textwrap.wrap(tdoc, 80)) + "\n\n")
1964                f.write("@table @asis\n")
1965                iargs = list(a for a in args if not a.out)
1966                oargs = list(a for a in args if a.out)
1967                f.write("@item " + "Input:\n" + (", ".join(
1968                    ("@code{" + iarg.texi + "}")
1969                    for iarg in iargs) if len(iargs) else "-") + "\n")
1970                f.write("@item " + "Output:\n" + (", ".join(
1971                    ("@code{" + oarg.name + "}")
1972                    for oarg in oargs) if len(oargs) else "-") + "\n")
1973                f.write("@item " + "Return:\n" +
1974                        (rtype.rtexi_type if rtype else "-") + "\n")
1975                f.write("@item " + "Language-specific definition:\n")
1976                f.write("@url{@value{GITLAB-PREFIX}/api/gmsh.h#L" +
1977                        str(self.api_lineno['cpp'][path + '/' + name]) +
1978                        ",C++}")
1979                f.write(", @url{@value{GITLAB-PREFIX}/api/gmshc.h#L" +
1980                        str(self.api_lineno['c'][path + '/' + name]) + ",C}")
1981                try:
1982                    f.write(", @url{@value{GITLAB-PREFIX}/api/gmsh.py#L" +
1983                            str(self.api_lineno['py'][path + '/' + name]) +
1984                            ",Python}")
1985                except:
1986                    pass
1987                try:
1988                    f.write(", @url{@value{GITLAB-PREFIX}/api/gmsh.jl#L" +
1989                            str(self.api_lineno['jl'][path + '/' + name]) +
1990                            ",Julia}")
1991                except:
1992                    pass
1993                f.write("\n")
1994                cpp = find_function('C++', path + '/' + name, cpp_data)
1995                py = find_function('Python', path + '/' + name, py_data)
1996
1997                def write_matches(lang, matches, max_matches):
1998                    f.write(lang + ' (')
1999                    for i in range(min(max_matches,
2000                                       len(matches))):  # write max 5 matches
2001                        if i > 0: f.write(', ')
2002                        f.write('@url{@value{GITLAB-PREFIX}/' +
2003                                matches[i][0][3:] + '#L' + str(matches[i][1]) +
2004                                ',' + os.path.basename(matches[i][0]) + '}')
2005                    if len(matches) > max_matches: f.write(', ...')
2006                    f.write(')')
2007
2008                if len(cpp) or len(py):
2009                    f.write("@item " + "Examples:\n")
2010                    if len(cpp):
2011                        write_matches("C++", cpp, 5)
2012                        if len(py): f.write(', ')
2013                    if len(py):
2014                        write_matches("Python", py, 5)
2015                    f.write("\n")
2016                f.write("@end table\n\n")
2017            f.write("@end ftable\n\n")
2018
2019        with open("../doc/texinfo/api.texi", "w") as f:
2020            f.write(
2021                "@c This file was generated by api/gen.py: do not edit manually!\n\n"
2022            )
2023
2024            def flatten_module(flat, module, path):
2025                p = path + ("/" if len(path) else "") + module.name
2026                flat.append((module, p))
2027                for m in module.submodules:
2028                    flatten_module(flat, m, p)
2029
2030            def node_name(n):
2031                return "Namespace " + n[1]
2032
2033            flat = []
2034            for m in self.modules:
2035                flatten_module(flat, m, "")
2036            N = len(flat)
2037            f.write("@menu\n")
2038            for i in range(N):
2039                f.write("* " + node_name(flat[i]) + "::\n")
2040            f.write("@end menu\n\n")
2041            cpp_data = get_file_data('../tutorial', '.cpp')
2042            cpp_data.extend(get_file_data('../demos/api', '.cpp'))
2043            py_data = get_file_data('../tutorial', '.py')
2044            py_data.extend(get_file_data('../demos/api', '.py'))
2045            for i in range(N):
2046                write_module(flat[i][0], flat[i][1], node_name(flat[i]),
2047                             "" if i == N - 1 else node_name(flat[i + 1]),
2048                             "" if i == 0 else node_name(flat[i - 1]),
2049                             cpp_data, py_data)
2050