Add more realistic type system.
[wrappi.git] / generator / wrappi_c.ml
index 62fb48d..1a04234 100644 (file)
@@ -23,17 +23,28 @@ open Wrappi_boilerplate
 
 open Printf
 
-let c_of_any_type = function
-  | TFilePerm -> "int"
+let c_of_ptype ~param = function
+  | TBool -> "int"
+  | TBuffer -> assert false (* XXX not implemented *)
+  | TEnum name -> sprintf "enum wrap_%s" name
+  | TFile -> if param then "const char *" else "char *"
+  | THash t -> if param then "char * const *" else "char **"
+  | TInt -> "intXXX" (* XXX depends on preconditions *)
   | TInt32 -> "int32_t"
   | TInt64 -> "int64_t"
-  | TPathname -> "const char *"
+  | 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
+  | TTypedef name -> assert false (* should never happen *)
   | TUInt32 -> "uint32_t"
   | TUInt64 -> "uint64_t"
+  | TUnion name -> sprintf "union wrap_%s" name
 
-let c_of_return_type = function
+let c_of_rtype = function
   | RErr -> "int"
-  | Return t -> c_of_any_type t
+  | Return t -> c_of_ptype ~param:false t
 
 let generate_lib_wrappi_h api =
   generate_header CStyle LGPLv2plus;
@@ -63,20 +74,28 @@ extern void wrap_close (wrap_h *w);
 /* API entry points. */
 ";
 
-  List.iter (
+  iter_entry_points api (
     fun ep ->
-      pr "extern %s wrap_%s (wrap_h *w, %s);\n"
-        (c_of_return_type ep.ep_return)
-        ep.ep_name
-        (String.concat ", "
-           (List.map (
-             fun (name, t) ->
-               let t = c_of_any_type t in
-               let last_char = t.[String.length t - 1] in
-               let sep = if isalnum last_char then " " else "" in
-               sprintf "%s%s%s" t sep name
-            ) ep.ep_params))
-  ) api.api_entry_points;
+      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"
+
+  );
 
   pr "\