-
Notifications
You must be signed in to change notification settings - Fork 142
/
Copy pathgen_wrappers.jl
171 lines (157 loc) · 6.38 KB
/
gen_wrappers.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# Generate ../src/api/functions.jl
# Run `julia --project=.. gen_wrappers.jl`` to execute this script
const group_url_dict = Dict{String,String}([
func_urls[1] => func_urls[2] for
func_urls in split.(readlines("DoxygenTagParser/hdf5_group_urls.tsv"))
])
group_url_dict["H5FD"] = group_url_dict["VFL"]
include(joinpath(@__DIR__, "bind_generator.jl"))
# Read in the API definition macros from the definitions file
defs = read(joinpath(@__DIR__, "api_defs.jl"), String)
# Have Julia expand/run the @bind macro to generate expressions for all of the functions
exprs = Base.include_string(
@__MODULE__, "@macroexpand1 begin\n" * defs * "\nend", "api_defs.jl"
)
# Insert the conditional version helper expression
prepend!(exprs.args, _libhdf5_build_ver_expr.args)
Base.remove_linenums!(exprs)
# Definitions which are not automatically generated, but should still be documented as
# part of the raw low-level API:
append!(bound_api["H5O"], [
# defined in src/api/helpers.jl
"h5o_get_info1",
])
append!(bound_api["H5P"], [
# defined in src/api/helpers.jl
"h5p_get_class_name",
"h5p_get_fapl_mpio",
"h5p_set_fapl_mpio",
])
append!(bound_api["H5T"], [
# defined in src/api/helpers.jl
"h5t_get_member_name",
"h5t_get_tag",
])
# Now dump the text representation to disk
open(joinpath(@__DIR__, "..", "src", "api", "functions.jl"), "w") do fid
println(
fid,
"""
#! format: off
# This file is autogenerated by HDF5.jl's `gen/gen_wrappers.jl` and should not be editted.
#
# To add new bindings, define the binding in `gen/api_defs.jl`, re-run
# `gen/gen_wrappers.jl`, and commit the updated `src/api/functions.jl`.
"""
)
function triplequote(s::String, indent="", prefix="")
ret = indent * prefix * "\"\"\"\n"
for l in eachline(IOBuffer(s))
ret *= isempty(l) ? "\n" : indent * l * "\n"
end
ret *= indent * "\"\"\"\n"
return ret
end
ismacro(ex, sym, n=0) =
isexpr(ex, :macrocall) && length(ex.args) >= n + 2 && ex.args[1] == sym
for funcblock in exprs.args
if ismacro(funcblock, Symbol("@doc"), 2)
# Pretty print the doc macro as just a juxtaposed doc string and function
# definition; the `@doc` construction is necessary in AST form for the docs
# to be included in interactive use of `@bind`, but in source form we can
# rely on Julia's parsing behavior.
print(fid, triplequote(funcblock.args[3]), funcblock.args[4], "\n\n")
elseif ismacro(funcblock, Symbol("@static"), 1) &&
isexpr(funcblock.args[3], :if, 2) &&
ismacro(funcblock.args[3].args[2], Symbol("@doc"), 2)
# Within a @static block, we have to keep the @doc prefix, but we can still
# switch to triple-quoting and there's special parsing to allow the function
# definition to be on the next line.
#
# Work around the expression printer in this more complex case by printing
# to a buffer and string-replacing a sentinel value
docstr = funcblock.args[3].args[2].args[3]
funcblock.args[3].args[2].args[3] = "SENTINEL_DOC"
buf = sprint(print, funcblock)
# Two-step deindent since `r"^\s{4}(\s{4})?"m => s"\1"` errors: see JuliaLang/julia#31456
buf = replace(buf, r"^\s{4}"m => s"") # deindent
buf = replace(buf, r"^(\s{4})\s{4}"m => s"\1") # deindent
# Now format the doc string and replace (note need to indent `function`)
buf = replace(
buf,
r"^\s+@doc \"SENTINEL_DOC\" "m =>
triplequote(docstr, " "^4, "@doc ") * " "^4
)
print(fid, buf, "\n\n")
else
# passthrough
print(fid, funcblock, "\n\n")
end
end
# Remove last endline
truncate(fid, position(fid) - 1)
end
# Also generate auto-docs that simply list all of the bound API functions
apidocs = ""
for (mod, desc, urltail) in (
("H5", "General Library Functions", "Library"),
("H5A", "Attribute Interface", "Attributes"),
("H5D", "Dataset Interface", "Datasets"),
("H5E", "Error Interface", "Error+Handling"),
("H5F", "File Interface", "Files"),
("H5G", "Group Interface", "Groups"),
("H5I", "Identifier Interface", "Identifiers"),
("H5L", "Link Interface", "Links"),
("H5O", "Object Interface", "Objects"),
("H5PL", "Plugin Interface", "Plugins"),
("H5P", "Property Interface", "Property+Lists"),
("H5R", "Reference Interface", "References"),
("H5S", "Dataspace Interface", "Dataspaces"),
("H5T", "Datatype Interface", "Datatypes"),
("H5Z", "Filter Interface", "Filters"),
("H5FD", "File Drivers", "File+Drivers"),
("H5DO", "Optimized Functions Interface", "Optimizations"),
("H5DS", "Dimension Scale Interface", "Dimension+Scales"),
("H5LT", "Lite Interface", "Lite"),
("H5TB", "Table Interface", "Tables"),
)
global apidocs
funclist = sort!(bound_api[mod])
index = join(["- [`$f`](@ref $f)" for f in funclist], "\n")
funcs = join(funclist, "\n")
apidocs *= """
---
## [[`$mod`]($(get(group_url_dict, mod, "https://docs.hdfgroup.org/hdf5/v1_14/"))) — $desc](@id $mod)
$index
```@docs
$funcs
```
"""
end
open(joinpath(@__DIR__, "..", "docs", "src", "api_bindings.md"), "w") do fid
write(
fid,
"""
```@raw html
<!-- This file is auto-generated and should not be manually editted. To update, run the
gen/gen_wrappers.jl script -->
```
```@meta
CurrentModule = HDF5.API
```
# Low-level library bindings
At the lowest level, `HDF5.jl` operates by calling the public API of the HDF5 shared
library through a set of `ccall` wrapper functions.
This page documents the function names and nominal C argument types of the API which
have bindings in this package.
Note that in many cases, high-level data types are valid arguments through automatic
`ccall` conversions.
For instance, `HDF5.Datatype` objects will be automatically converted to their `hid_t` ID
by Julia's `cconvert`+`unsafe_convert` `ccall` rules.
There are additional helper wrappers (often for out-argument functions) which are not
documented here.
$apidocs
"""
)
end
nothing