Add enums.
[wrappi.git] / generator / wrappi_c.ml
index 7f9c1b4..80b832b 100644 (file)
@@ -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 *)
@@ -69,7 +71,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 +91,35 @@ 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 "  WRAP_%s_ENUM_MAX = %d\n"
+        (String.uppercase name) (Array.length en.en_identifiers);
+      pr "};\n";
+      pr "typedef int wrap_%s_enum;\n" name;
+      pr "\n";
+  );
+
+  pr "\
 /* Connection management. */
 extern wrap_h *wrap_create (void);
 extern void wrap_close (wrap_h *w);