X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=generator%2Fwrappi_c.ml;h=099a7c2c35d5594b3e5d3acf1ce02996965dbee9;hb=0571e7d0a290a9c3e0f3880363d0f2dbe93fc616;hp=7f9c1b49c7550c59da01df42a62d423cc7f2060c;hpb=53126578ee08c0bd3b3987959fb7d768deb5aedc;p=wrappi.git diff --git a/generator/wrappi_c.ml b/generator/wrappi_c.ml index 7f9c1b4..099a7c2 100644 --- a/generator/wrappi_c.ml +++ b/generator/wrappi_c.ml @@ -23,10 +23,12 @@ open Wrappi_boilerplate 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 *) @@ -36,7 +38,9 @@ let c_of_ptype ~param = function | 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" @@ -47,6 +51,25 @@ let c_of_rtype = function | 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 @@ -69,7 +92,7 @@ let pr_extern_decl ep = 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 @@ -89,6 +112,47 @@ extern \"C\" { /* 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); @@ -116,5 +180,50 @@ 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 + +#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