let c_of_rtype = function
| RVoid -> "void"
+ | RStaticString -> "const char *"
| Return t -> c_of_ptype ~param:false t
-let pr_decl ep =
+let pr_defn ?(impl = false) ep =
let ret, req, opt = ep.ep_ftype in
- pr "%s\n" (c_of_rtype ret);
- pr "wrap_%s (wrap_h *w" ep.ep_name;
+
+ if not impl then (
+ pr "%s\n" (c_of_rtype ret);
+ pr "wrap_%s (wrap_h *w" ep.ep_name
+ ) else (
+ pr "static %s\n" (c_of_rtype ret);
+ pr "impl_%s (struct wrap_internal_h *w" ep.ep_name
+ );
(* Required parameters. *)
List.iter (
generate_header CStyle LGPLv2plus;
pr "\
+/* Automatically generated implementation of '%s'.
+ * This API was defined in '%s' at line %d.
+ */
+
+" ep.ep_name (Loc.file_name ep.ep_loc) (Loc.start_line ep.ep_loc);
+
+ pr "\
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
";
List.iter (pr "#include <%s>\n") ep.ep_includes;
pr "\
#include \"wrappi.h\"
-
#include \"internal.h\"
-/* Automatically generated implementation of '%s'.
- * This API was defined in '%s' at line %d.
- */
+";
-" ep.ep_name (Loc.file_name ep.ep_loc) (Loc.start_line ep.ep_loc);
+ pr_defn ~impl:(not ep.ep_local) ep;
- (* Depending on whether this is a local or remote function, include
- * different definitions here.
+ pr "{\n";
+
+ (match ep.ep_code with
+ | None -> () (* XXX implicit code *)
+ | Some { cc_loc = loc; cc_code = code } ->
+ pr "#line %d \"%s\"\n" (Loc.start_line loc) (Loc.file_name loc);
+ pr "%s" code
+ );
+
+ pr "}\n";
+
+ (* For remote functions only, we now need to generate the
+ * local binding code.
*)
- (*if ep.ep_local then ... *)
+ if not ep.ep_local then (
+ pr "\n";
- pr_decl ep;
+ pr_defn ep;
- pr "\
-{
-#line %d \"%s\"
-" (Loc.start_line ep.ep_loc) (Loc.file_name ep.ep_loc);
+ pr "{\n";
+ pr " assert (w->scheme == NULL); /* XXX */;\n";
+ pr "\n";
+ pr " ";
- (match ep.ep_code with
- | None -> ()
- | Some code -> pr "%s" code
- );
+ let ret, req, opt = ep.ep_ftype in
+
+ (match ret with
+ | RVoid -> ()
+ | _ -> pr "return "
+ );
+
+ pr "impl_%s ((struct wrap_internal_h *)w" ep.ep_name;
+
+ (* Required parameters. *)
+ List.iter (fun (name, _, _) -> pr ", %s" name) req;
+
+ (* Optional parameters. *)
+ if opt <> [] then
+ assert false; (* XXX not implemented *)
+
+ pr ");\n";
+
+ (match ret with
+ | RVoid -> pr " return;\n"
+ | _ -> ()
+ );
- pr "}\n"
+ pr "}\n"
+ )
(* Make a unique, reproducible filename for each entry point. *)
let filename_of_ep ep =
pr "local_implementation_files := \\\n";
- loop (List.filter (fun ep -> ep.ep_local) eps);
+ loop (List.filter (fun ep -> ep.ep_local && ep.ep_code <> None) eps);
pr "\n";
pr "remote_implementation_files := \\\n";
iter_entry_points api (
fun ep ->
- let filename = filename_of_ep ep in
+ (* Local entry points which don't have associated code are
+ * assumed to be implemented in hand-written code elsewhere under
+ * lib/.
+ *)
+ if not ep.ep_local || ep.ep_code <> None then (
+ let filename = filename_of_ep ep in
- gitignores := ("/" ^ filename) :: !gitignores;
+ gitignores := ("/" ^ filename) :: !gitignores;
- output_to ("lib/" ^ filename) generate_implementation ep
+ output_to ("lib/" ^ filename) generate_implementation ep
+ )
);
let gitignores = List.rev !gitignores in