X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=generator%2Fwrappi_c.ml;h=099a7c2c35d5594b3e5d3acf1ce02996965dbee9;hb=0571e7d0a290a9c3e0f3880363d0f2dbe93fc616;hp=1a04234eb377e89a20599dfb65f4856e617cfa7f;hpb=6964a24290a2d645b3155353e08750f37930146a;p=wrappi.git diff --git a/generator/wrappi_c.ml b/generator/wrappi_c.ml index 1a04234..099a7c2 100644 --- a/generator/wrappi_c.ml +++ b/generator/wrappi_c.ml @@ -23,31 +23,76 @@ 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 -> "intXXX" (* XXX depends on preconditions *) + | 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 -> 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" | TUnion name -> sprintf "union wrap_%s" name let c_of_rtype = function - | RErr -> "int" + | RVoid -> "void" + | 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 "extern %s wrap_%s (wrap_h *w" (c_of_rtype ret) ep.ep_name; + + (* Required parameters. *) + List.iter ( + fun (name, t, _) -> + let t = c_of_ptype ~param:true t in + let sep = (* "const char *" - omit space after asterisk *) + let len = String.length t in + if isalnum t.[len-1] then " " else "" in + pr ", %s%s%s" t sep name + ) req; + + (* Optional parameters. *) + if opt <> [] then + pr ", ..."; + + 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 @@ -67,35 +112,64 @@ 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); -/* API entry points. */ "; - iter_entry_points api ( - fun ep -> - let ret, req, opt = ep.ep_ftype in - pr "extern %s wrap_%s (wrap_h *w" (c_of_rtype ret) ep.ep_name; - - (* Required parameters. *) - List.iter ( - fun (name, t, _) -> - let t = c_of_ptype ~param:true t in - let sep = (* "const char *" - omit space after asterisk *) - let len = String.length t in - if isalnum t.[len-1] then " " else "" in - pr ", %s%s%s" t sep name - ) req; - - (* Optional parameters. *) - if opt <> [] then - pr ", ..."; + (* Separate the local and remote functions. *) + pr "\ +/* Handle functions. */ +"; + iter_entry_points api (fun ep -> if ep.ep_local then pr_extern_decl ep); - pr ");\n" + pr "\ - ); +/* API entry points. */ +"; + iter_entry_points api (fun ep -> if not ep.ep_local then pr_extern_decl ep); pr "\ @@ -106,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