open Printf
+let inputs = ["wrappi_c.ml"]
+
let c_of_ptype ~param = function
| TBool -> "int"
| TBuffer -> assert false (* XXX not implemented *)
- | TEnum name -> sprintf "enum wrap_%s" name
+ | TEnum name -> sprintf "wrap_%s_enum" name
| TFile -> if param then "const char *" else "char *"
| THash t -> if param then "char * const *" else "char **"
| TInt -> "int" (* XXX not int, correct type depends on preconditions *)
| TNullable TString -> if param then "const char *" else "char *"
| TNullable _ -> assert false (* XXX may be implemented in future *)
| TString -> if param then "const char *" else "char *"
- | TStruct name -> sprintf "struct wrap_%s" name
+ | TStruct name ->
+ if param then sprintf "const struct wrap_%s *" name
+ else sprintf "struct wrap_%s *" name
| TTypedef name -> assert false (* should never happen *)
| TUInt32 -> "uint32_t"
| TUInt64 -> "uint64_t"
| RStaticString -> "const char *"
| Return t -> c_of_ptype ~param:false t
+let field_of_ptype = function
+ | TBool -> "int"
+ | TBuffer -> assert false (* XXX not implemented *)
+ | TEnum name -> sprintf "wrap_%s_enum" name
+ | TFile -> assert false (* cannot occur in a struct *)
+ | THash t -> "char **"
+ | TInt -> "int" (* XXX not int, correct type depends on preconditions *)
+ | TInt32 -> "int32_t"
+ | TInt64 -> "int64_t"
+ | TList t -> assert false (* XXX not implemented *)
+ | TNullable TString -> "char *"
+ | TNullable _ -> assert false (* XXX may be implemented in future *)
+ | TString -> "char *"
+ | TStruct name -> assert false (* we don't allow struct/union here *)
+ | TTypedef name -> assert false (* should never happen *)
+ | TUInt32 -> "uint32_t"
+ | TUInt64 -> "uint64_t"
+ | TUnion name -> assert false (* we don't allow struct/union here *)
+
(* Print the extern... declaration of a single entry point. *)
let pr_extern_decl ep =
let ret, req, opt = ep.ep_ftype in
pr ");\n"
let generate_lib_wrappi_h api =
- generate_header CStyle LGPLv2plus;
+ generate_header inputs CStyle LGPLv2plus;
pr "\
/* Please read the wrappi(1) man page for full documentation. If you
/* The handle. */
typedef struct wrap_h wrap_h;
+/* Types. */
+";
+
+ iter_enums api (
+ fun en ->
+ let name = en.en_name in
+
+ (* The C compiler may choose to declare the sizeof(enum) ==
+ * sizeof(char), and adding fields to such an enum later could
+ * cause ABI breakage. (See the gcc --fshort-enums option for one
+ * example of this). Therefore use the enum just to declare the
+ * values, and typedef the enum as an int.
+ *)
+ pr "enum {\n";
+
+ Array.iteri (
+ fun i id ->
+ pr " WRAP_%s_%s = %d,\n"
+ (String.uppercase name) (String.uppercase id) i
+ ) en.en_identifiers;
+ pr "};\n";
+ pr "typedef int wrap_%s_enum;\n" name;
+ pr "\n";
+ );
+
+ iter_structs api (
+ fun sd ->
+ let name = sd.sd_name in
+
+ pr "struct wrap_%s {\n" name;
+
+ Array.iter (
+ fun (name, t) ->
+ pr " %s %s;\n" (field_of_ptype t) name
+ ) sd.sd_fields;
+ pr "};\n";
+ pr "void wrap_free_%s (struct wrap_%s *);\n" name name;
+ pr "\n"
+ );
+
+ pr "\
/* Connection management. */
extern wrap_h *wrap_create (void);
extern void wrap_close (wrap_h *w);
#endif /* WRAPPI_H_ */
"
+(* Functions for freeing structs are part of the C bindings. We don't
+ * want them to be exposed in other languages, although they will be
+ * used by other bindings.
+ *)
+let generate_lib_free_structs_c api =
+ generate_header inputs CStyle LGPLv2plus;
+
+ pr "\
+#include <stdlib.h>
+
+#include \"wrappi.h\"
+";
+
+ iter_structs api (
+ fun sd ->
+ pr "\n";
+
+ let name = sd.sd_name in
+
+ pr "void\n";
+ pr "wrap_free_%s (struct wrap_%s *v)\n" name name;
+ pr "{\n";
+
+ Array.iter (
+ fun (n, t) ->
+ match t with
+ | TBool | TEnum _ | TInt | TInt32 | TInt64 | TUInt32 | TUInt64 ->
+ () (* these don't need to be freed *)
+ | TBuffer -> assert false (* XXX not implemented *)
+ | TFile
+ | TNullable TString
+ | TString ->
+ pr " free (v->%s);\n" n
+ | THash t -> assert false (* XXX not implemented *)
+ | TList t -> assert false (* XXX not implemented *)
+ | TNullable _ -> assert false (* XXX may be implemented in future *)
+ | TStruct name -> assert false (* cannot occur in structs *)
+ | TTypedef name -> assert false (* should never happen *)
+ | TUnion name -> assert false (* cannot occur in structs *)
+ ) sd.sd_fields;
+ pr " free (v);\n";
+ pr "}\n"
+ )
+
let generate api =
- output_to "lib/wrappi.h" generate_lib_wrappi_h api
+ output_to "lib/wrappi.h" generate_lib_wrappi_h api;
+ output_to "lib/free_structs.c" generate_lib_free_structs_c api