File: docs.ml

package info (click to toggle)
libnbd 1.22.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 10,636 kB
  • sloc: ansic: 53,855; ml: 12,311; sh: 8,499; python: 4,595; makefile: 2,902; perl: 165; cpp: 24
file content (287 lines) | stat: -rw-r--r-- 8,716 bytes parent folder | download
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
(* hey emacs, this is OCaml code: -*- tuareg -*- *)
(* nbd client library in userspace: generate the C API and documentation
 * Copyright Red Hat
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *)

open Printf

open API
open Utils

(* We generate a fragment of Makefile.am containing the list
 * of generated functions, used in rules for building the manual
 * pages.  We exploit GNU make's sinclude to use this file without
 * upsetting automake.
 *)
let generate_docs_Makefile_inc () =
  generate_header HashStyle;

  pr "api_built += \\\n";
  List.iter (
    fun (name, _) ->
      pr "\tnbd_%s \\\n" name;
  ) handle_calls;
  pr "\t$(NULL)\n"

let generate_docs_api_links_pod () =
  let pages =
    List.map (fun (name, _) -> sprintf "nbd_%s(3)" name) handle_calls in
  let pages =
    "nbd_create(3)" ::
    "nbd_close(3)" ::
    "nbd_get_error(3)" ::
    "nbd_get_errno(3)" ::
    pages in
  let pages = List.sort compare pages in

  List.iteri (
    fun i page ->
      if i > 0 then pr ",\n";
      pr "L<%s>" page
  ) pages;
  pr ".\n"

let generate_docs_api_flag_links_pod () =
  let pages =
    filter_map (
      fun (name, _) ->
        if (is_prefix name "is_" && name <> "is_uri") ||
             is_prefix name "can_" then
          Some (sprintf "nbd_%s(3)" name)
        else
          None
    ) handle_calls in
  let pages = List.sort compare pages in

  List.iteri (
    fun i page ->
      if i > 0 then pr ",\n";
      pr "L<%s>" page
  ) pages;
  pr ".\n"

let print_docs_closure { cbname; cbargs } =
  pr " typedef struct {\n";
  pr "   int (*callback) ";
  C.print_cbarg_list ~wrap:true ~maxcol:60 cbargs;
  pr ";\n";
  pr "   void *user_data;\n";
  pr "   void (*free) (void *user_data);\n";
  pr " } nbd_%s_callback;\n" cbname

let generate_docs_nbd_pod name { args; optargs; ret;
                                 shortdesc; longdesc; example; see_also;
                                 permitted_states; may_set_error;
                                 first_version = (major, minor) } () =
  pr "=head1 NAME\n";
  pr "\n";
  pr "nbd_%s -" name;
  (* Don't use pr_wrap here because it leaves trailing whitespace. *)
  let words = nsplit " " shortdesc in
  List.iter (
    fun word ->
      if output_column () + String.length word > 70 then pr "\n%s" word
      else pr " %s" word
  ) words;
  pr "\n";
  pr "\n";

  pr "=head1 SYNOPSIS\n";
  pr "\n";
  pr " #include <libnbd.h>\n";
  pr "\n";

  List.iter (
    function
    | Closure cb -> print_docs_closure cb; pr "\n"
    | _ -> ()
  ) args;
  List.iter (
    function
    | OClosure cb -> print_docs_closure cb; pr "\n"
    | _ -> ()
  ) optargs;

  pr " ";
  C.print_call ~wrap:true ~maxcol:60 name args optargs ret;
  pr ";\n";
  pr "\n";

  pr "=head1 DESCRIPTION\n";
  pr "\n";
  pr "%s\n" longdesc;
  pr "\n";

  pr "=head1 RETURN VALUE\n";
  pr "\n";
  let errcode = C.errcode_of_ret ret in
  (match ret with
   | RBool ->
      pr "This call returns a boolean value.\n"
   | RStaticString ->
      pr "This call returns a statically allocated string, valid for the\n";
      pr "lifetime of the process or until libnbd is unloaded by\n";
      pr "L<dlclose(3)>.  You B<must not> try to free the string.\n"
   | RErr ->
      pr "If the call is successful the function returns C<0>.\n"
   | RFd ->
      pr "This call returns a file descriptor.\n"
   | RInt ->
      pr "This call returns an integer E<ge> C<0>.\n";
   | RInt64 ->
      pr "This call returns a 64 bit signed integer E<ge> C<0>.\n";
   | RCookie ->
      pr "This call returns the 64 bit cookie of the command.\n";
      pr "The cookie is E<ge> C<1>.\n";
      pr "Cookies are unique (per libnbd handle, not globally).\n"
   | RSizeT ->
      pr "This call returns an integer size E<ge> C<0>.\n";
   | RString ->
      pr "This call returns a string.  The caller must free the\n";
      pr "returned string to avoid a memory leak.\n";
   | RUInt ->
      pr "This call returns a bitmask.\n";
   | RUIntPtr ->
      pr "This call returns a C<uintptr_t>.\n";
   | RUInt64 ->
      pr "This call returns a counter.\n";
   | REnum { enum_prefix } ->
      pr "This call returns one of the LIBNBD_%s_* values.\n" enum_prefix;
   | RFlags { flag_prefix } ->
      pr "This call returns a bitmask of LIBNBD_%s_* values.\n" flag_prefix;
  );
  pr "\n";

  pr "=head1 ERRORS\n";
  pr "\n";

  if may_set_error then (
    let value = match errcode with
      | Some value -> value
      | None -> assert false in
    pr "On error C<%s> is returned.\n" value;
    pr "\n";
    pr "Refer to L<libnbd(3)/ERROR HANDLING>\n";
    pr "for how to get further details of the error.\n"
  )
  else
    pr "This function does not fail.\n";
  pr "\n";

  pr "The following parameters must not be NULL: C<h>";
  List.iter (
    fun arg ->
      let nns = C.arg_attr_nonnull arg in
      if List.mem true nns then pr ", C<%s>" (List.hd (C.name_of_arg arg))
  ) args;
  List.iter (
    fun arg ->
      let nns = C.optarg_attr_nonnull arg in
      if List.mem true nns then pr ", C<%s>" (C.name_of_optarg arg)
  ) optargs;
  pr ".\n";
  pr "For more information see L<libnbd(3)/Non-NULL parameters>.\n";
  pr "\n";

  if permitted_states <> [] then (
    pr "=head1 HANDLE STATE\n";
    pr "\n";
    pr "nbd_%s\ncan be called when the handle is in the following %s:\n"
      name (if List.length permitted_states = 1 then "state" else "states");
    pr "\n";
    pr " ┌─────────────────────────────────────┬─────────────────────────┐\n";
    let row ps description =
      let permitted = List.mem ps permitted_states in
      pr " │ %-35s │ %s %-20s │\n" description
        (if permitted then "✅" else "❌")
        (if permitted then "allowed" else "error")
    in
    List.iter (
      fun ps ->
      match ps with
      | Created ->     row ps "Handle created, before connecting"
      | Connecting ->  row ps "Connecting"
      | Negotiating -> row ps "Connecting & handshaking (opt_mode)"
      | Connected ->   row ps "Connected to the server"
      | Closed ->      row ps "Connection shut down"
      | Dead ->        row ps "Handle dead"
    ) all_permitted_states;
    pr " └─────────────────────────────────────┴─────────────────────────┘\n";
    pr "\n"
  );

  pr "=head1 VERSION\n";
  pr "\n";
  pr "This function first appeared in libnbd %d.%d.\n" major minor;
  pr "\n";
  pr "If you need to test if this function is available at compile time\n";
  pr "check if the following macro is defined:\n";
  pr "\n";
  pr " #define LIBNBD_HAVE_NBD_%s 1\n" (String.uppercase_ascii name);
  pr "\n";

  (match example with
   | None -> ()
   | Some filename ->
      pr "=head1 EXAMPLE\n";
      pr "\n";
      pr "This example is also available as F<%s>\n" filename;
      pr "in the libnbd source code.\n";
      pr "\n";
      let chan = open_in filename in
      (try
         while true do
           let line = input_line chan in
           let len = String.length line in
           if len > 60 then
             failwithf "%s: %s: line too long in example" name filename;
           if len = 0 then pr "\n" else pr " %s\n" line
         done
       with End_of_file -> ()
      );
      close_in chan;
      pr "\n"
  );

  let () =
    pr "=head1 SEE ALSO\n";
    pr "\n";
    let other_links = extract_links longdesc in
    let std_links = [MainPageLink; Link "create"] in
    let links = see_also @ other_links @ std_links in
    let links = sort_uniq_links links in
    List.iter verify_link links;
    let links = List.map pod_of_link links in
    let comma = ref false in
    List.iter (
      fun pod ->
        if !comma then pr ",\n"; comma := true;
        pr "%s" pod
    ) links;
    pr ".\n\n" in

  pr "\
=head1 AUTHORS

Eric Blake

Richard W.M. Jones

=head1 COPYRIGHT

Copyright Red Hat
"