Generator main program.
authorRichard W.M. Jones <rjones@redhat.com>
Thu, 29 Dec 2011 13:54:27 +0000 (13:54 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Thu, 29 Dec 2011 13:54:27 +0000 (13:54 +0000)
16 files changed:
.gitignore
APIs/.depend [new file with mode: 0644]
APIs/Makefile.am
configure.ac
generator-lib/.depend
generator-lib/Makefile.am
generator-lib/config.ml.in [new file with mode: 0644]
generator-lib/wrappi_globals.ml [new file with mode: 0644]
generator-lib/wrappi_globals.mli [new file with mode: 0644]
generator-lib/wrappi_types.ml
generator-lib/wrappi_types.mli [new file with mode: 0644]
generator-macros/.depend
generator-macros/pa_wrap.ml
generator/.depend
generator/Makefile.am
generator/wrappi_main.ml [new file with mode: 0644]

index 862ad54..ec9a5fb 100644 (file)
@@ -16,6 +16,8 @@ Makefile.in
 /config.status
 /config.sub
 /configure
+/generator-lib/config.ml
+/generator/generator
 /install-sh
 /libtool
 /ltmain.sh
diff --git a/APIs/.depend b/APIs/.depend
new file mode 100644 (file)
index 0000000..640631a
--- /dev/null
@@ -0,0 +1,2 @@
+mkdir.cmo:
+mkdir.cmx:
index 0edf67d..b386941 100644 (file)
@@ -15,7 +15,7 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-OCAMLCFLAGS = -g -warn-error CDEFLMPSUVYZX
+OCAMLCFLAGS = -g -warn-error CDEFLMPSUVYZX -I ../generator-lib
 OCAMLOPTFLAGS = $(OCAMLCFLAGS)
 
 PP = -pp '$(CAMLP4O) ../generator-macros/pa_wrap.cmo -impl'
@@ -23,13 +23,28 @@ PP = -pp '$(CAMLP4O) ../generator-macros/pa_wrap.cmo -impl'
 #API_FILES = $(wildcard *.api)
 API_FILES = mkdir.api mknod.api
 
-OBJ_FILES = $(patsubst %.api,%.cmo,$(API_FILES))
+OBJECTS = $(patsubst %.api,%.cmo,$(API_FILES))
 
-noinst_SCRIPTS = $(OBJ_FILES)
+noinst_SCRIPTS = apis.cma
 
-%.cmo: %.api
+apis.cma: $(OBJECTS) ../generator-lib/generator_lib.cma
+       $(OCAMLFIND) ocamlc -linkall -a $(OBJECTS) -o apis.cma
+
+%.cmo: %.api ../generator-lib/generator_lib.cma
        $(OCAMLFIND) ocamlc $(OCAMLOPTFLAGS) $(PP) -impl $< -c -o $@
 
 CLEANFILES = *.cmi *.cmo *.cmx *~
 
+depend: .depend
+
+.depend: $(API_FILES)
+       rm -f $@ $@-t
+       $(OCAMLFIND) ocamldep $(PP) -impl $^ | \
+         $(SED) -e 's/ *$$//' | \
+         $(SED) -e :a -e '/ *\\$$/N; s/ *\\\n */ /; ta' | \
+         LANG=C sort > $@-t
+       mv $@-t $@
+
+include .depend
+
 SUFFIXES = .cmo .cmi .cmx .ml .mli .mll .mly .api
index fb2717b..1182568 100644 (file)
@@ -59,6 +59,7 @@ AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_FILES([Makefile
                  APIs/Makefile
                  generator/Makefile
+                 generator-lib/config.ml
                  generator-lib/Makefile
                  generator-macros/Makefile
                  lib/Makefile])
index e69de29..9373889 100644 (file)
@@ -0,0 +1,5 @@
+config.cmo:
+config.cmx:
+wrappi_globals.cmi: wrappi_types.cmi
+wrappi_globals.cmo: wrappi_types.cmi wrappi_globals.cmi
+wrappi_globals.cmx: wrappi_types.cmx wrappi_globals.cmi
index 809965b..a4a6111 100644 (file)
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-OCAMLCFLAGS = -g -warn-error CDEFLMPSUVYZX
+OCAMLCFLAGS = -g -warn-error CDEFLMPSUVYZX -I +camlp4
 OCAMLOPTFLAGS = $(OCAMLCFLAGS)
 
-OBJECTS = wrappi_types.cmo
+# In alphabetical order.
+SOURCES = \
+       config.ml \
+       wrappi_globals.mli \
+       wrappi_globals.ml
+       wrappi_types.mli \
+       wrappi_types.ml
+
+# In dependency order.
+OBJECTS = \
+       config.cmo \
+       wrappi_types.cmo \
+       wrappi_globals.cmo
 
 noinst_SCRIPTS = generator_lib.cma
 
 generator_lib.cma: $(OBJECTS)
-       $(OCAMLMKLIB) $^ -o generator_lib
+       $(OCAMLFIND) ocamlc -a $^ -o generator_lib.cma
 
 %.cmi: %.mli
        $(OCAMLFIND) ocamlc $(OCAMLCFLAGS) -c $< -o $@
@@ -36,7 +48,7 @@ CLEANFILES = *.cmi *.cmo *.cmx *~
 
 depend: .depend
 
-.depend: $(wildcard *.mli) $(wildcard *.ml)
+.depend: $(SOURCES)
        rm -f $@ $@-t
        $(OCAMLFIND) ocamldep $^ | \
          $(SED) -e 's/ *$$//' | \
diff --git a/generator-lib/config.ml.in b/generator-lib/config.ml.in
new file mode 100644 (file)
index 0000000..3c3ce90
--- /dev/null
@@ -0,0 +1,20 @@
+(* wrappi
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+let package_name = "@PACKAGE_NAME@"
+let package_version = "@PACKAGE_VERSION@"
diff --git a/generator-lib/wrappi_globals.ml b/generator-lib/wrappi_globals.ml
new file mode 100644 (file)
index 0000000..5d68a4f
--- /dev/null
@@ -0,0 +1,30 @@
+(* wrappi
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+open Wrappi_types
+
+(* Could return these in any order we want since they are all
+ * independent, but for neatness let's choose to return them in name
+ * order.
+ *)
+
+let eps = ref []
+let add_entry_point ep = eps := ep :: !eps
+
+let get_entry_points () =
+  List.sort (fun { ep_name = a } { ep_name = b } -> compare a b ) !eps
diff --git a/generator-lib/wrappi_globals.mli b/generator-lib/wrappi_globals.mli
new file mode 100644 (file)
index 0000000..488cda8
--- /dev/null
@@ -0,0 +1,26 @@
+(* wrappi
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+(** Globals.
+
+    These global lists are built up when the generator starts
+    running, populated by each compiled API file that is linked
+    in during each file's initializer. *)
+
+val add_entry_point : Wrappi_types.entry_point -> unit
+val get_entry_points : unit -> Wrappi_types.entry_point list
index 3f3ca58..7c3dfde 100644 (file)
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *)
 
+open Camlp4.PreCast
+
+open Printf
+
 type any_type = TInt32 | TInt64 | Type of string
 
+type parameter = string * any_type
+
 type return_type = RErr | Return of any_type
+
+type c_code = string
+
+type entry_point = {
+  (*ep_loc : Camlp4.PreCast.Loc.t;*)
+  ep_name : string;
+  ep_params : parameter list;
+  ep_return : return_type;
+  ep_code : c_code option;
+}
+
+let string_of_any_type = function
+  | TInt32 -> "int32"
+  | TInt64 -> "int64"
+  | Type s -> s
+let string_of_return_type = function
+  | RErr -> "err"
+  | Return t -> string_of_any_type t
+let string_of_parameter (name, t) =
+  sprintf "%s %s" (string_of_any_type t) name
+let string_of_parameters params =
+  "(" ^ String.concat ", " (List.map string_of_parameter params) ^ ")"
+let string_of_c_code code = code
+let string_of_entry_point ep =
+  sprintf "entry_point %s %s %s <<%s>>"
+    (*(Loc.to_string ep.ep_loc)*)
+    (string_of_return_type ep.ep_return)
+    ep.ep_name
+    (string_of_parameters ep.ep_params)
+    (match ep.ep_code with
+    | None -> "/* implicit */"
+    | Some code -> string_of_c_code code)
diff --git a/generator-lib/wrappi_types.mli b/generator-lib/wrappi_types.mli
new file mode 100644 (file)
index 0000000..6120aff
--- /dev/null
@@ -0,0 +1,47 @@
+(* wrappi
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+type any_type = TInt32 | TInt64 | Type of string
+(** Any API parameter or return type. *)
+
+type parameter = string * any_type
+(** API parameter (argument name and type). *)
+
+type return_type = RErr | Return of any_type
+(** API return type.  A superset of {!any_type} because we allow the
+    special value [RErr] for dealing with errno. *)
+
+type c_code = string
+(** C code. *)
+
+type entry_point = {
+  (*ep_loc : Camlp4.PreCast.Loc.t;*)
+  ep_name : string;
+  ep_params : parameter list;
+  ep_return : return_type;
+  ep_code : c_code option;
+}
+(** An API entry point. *)
+
+val string_of_any_type : any_type -> string
+val string_of_return_type : return_type -> string
+val string_of_parameter : parameter -> string
+val string_of_parameters : parameter list -> string
+val string_of_c_code : c_code -> string
+val string_of_entry_point : entry_point -> string
+(** Convert structures to strings for printing, debugging etc. *)
index c44a80c..baa61b8 100644 (file)
@@ -1,4 +1,2 @@
-pa_wrap.cmo: wrappi_types.cmo
-pa_wrap.cmx: wrappi_types.cmx
-wrappi_types.cmo:
-wrappi_types.cmx:
+pa_wrap.cmo:
+pa_wrap.cmx:
index c8e8af8..54e3676 100644 (file)
@@ -18,6 +18,7 @@
 
 (* For general information about camlp4, see:
  * http://brion.inria.fr/gallium/index.php/Camlp4
+ *
  * For information about quotations, see:
  * http://brion.inria.fr/gallium/index.php/Quotation
  *)
@@ -28,14 +29,37 @@ open Ast
 
 open Wrappi_types
 
+(* Convert a plain list into a list AST. *)
+let rec expr_of_list _loc = function
+  | [] -> <:expr< [] >>
+  | h::t -> let t = expr_of_list _loc t in <:expr< $h$ :: $t$ >>
+
+(* Convert an optional type into an option AST. *)
+let expr_of_option _loc = function
+  | None -> <:expr< None >>
+  | Some x -> <:expr< Some $x$ >>
+
 let add_entry_point _loc name parameters return_type code =
-  (* XXX *)
-  <:str_item< >>
+  let parameters = List.map (
+    fun (name, t) -> <:expr< ($str:name$, $t$) >>
+  ) parameters in
+  let parameters = expr_of_list _loc parameters in
+
+  let code = expr_of_option _loc code in
+
+  <:str_item<
+    let ep = { Wrappi_types.ep_name = $str:name$;
+               ep_params = $parameters$;
+               ep_return = $return_type$;
+               ep_code = $code$ } in
+    Wrappi_globals.add_entry_point ep
+  >>
 
 let () =
   (* Quotation expander for C code. *)
   let c_quotation_expander _loc _ code =
     (* XXX Expand %- or $- expressions in code. *)
+    (* XXX Escape >> in code. *)
     ExStr (_loc, code)
   in
   Quotation.add "c" Quotation.DynAst.expr_tag c_quotation_expander;
@@ -51,19 +75,19 @@ EXTEND Gram
 
   (* A parameter or return type. *)
   any_type: [
-    [ "int32" -> TInt32 ]
-  | [ "int64" -> TInt64 ]
-  | [ t = LIDENT -> Type t ]
+    [ "int32" -> <:expr< Wrappi_types.TInt32 >> ]
+  | [ "int64" -> <:expr< Wrappi_types.TInt64 >> ]
+  | [ t = LIDENT -> <:expr< Wrappi_types.Type $str:t$ >> ]
   ];
 
   (* A return type. *)
   return_type: [
-    [ "err" -> RErr ]
-  | [ t = any_type -> Return t ]
+    [ "err" -> <:expr< Wrappi_types.RErr >> ]
+  | [ t = any_type -> <:expr< Wrappi_types.Return $t$ >> ]
   ];
 
   (* A single function parameter. *)
-  parameter: [[ t = any_type; name = LIDENT -> (t, name) ]];
+  parameter: [[ t = any_type; name = LIDENT -> (name, t) ]];
 
   str_item: LEVEL "top" [
     [ "entry_point";
index e69de29..062bc8e 100644 (file)
@@ -0,0 +1,2 @@
+wrappi_main.cmo:
+wrappi_main.cmx:
index 6cfc2c2..3b0d6b4 100644 (file)
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-OCAMLCFLAGS = -g -warn-error CDEFLMPSUVYZX
+OCAMLCFLAGS = -g -warn-error CDEFLMPSUVYZX -I ../generator-lib
 OCAMLOPTFLAGS = $(OCAMLCFLAGS)
 
+# In alphabetical order.
+SOURCES = wrappi_main.ml
+
+# In dependency order.
+OBJECTS = wrappi_main.cmo
+
+noinst_SCRIPTS = generator
+
+generator: $(OBJECTS) ../generator-lib/generator_lib.cma ../APIs/apis.cma
+       $(OCAMLFIND) ocamlc $(OCAMLCFLAGS) \
+         ../generator-lib/generator_lib.cma ../APIs/apis.cma \
+         $(OBJECTS) \
+         -o $@
+
 %.cmi: %.mli
        $(OCAMLFIND) ocamlc $(OCAMLCFLAGS) -c $< -o $@
 %.cmo: %.ml
diff --git a/generator/wrappi_main.ml b/generator/wrappi_main.ml
new file mode 100644 (file)
index 0000000..aaf3719
--- /dev/null
@@ -0,0 +1,59 @@
+(* wrappi
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+open Printf
+
+let eps = Wrappi_globals.get_entry_points ()
+
+let dump_and_exit () =
+  printf "entry points:\n";
+
+  List.iter (fun ep ->
+    printf "  %s\n" (Wrappi_types.string_of_entry_point ep)
+  ) eps;
+
+  exit 0
+
+(* Parse command line arguments. *)
+let () =
+  let display_version () =
+    printf "%s %s\n" Config.package_name Config.package_version;
+    exit 0
+  in
+
+  let argspec = Arg.align [
+    "--dump", Arg.Unit dump_and_exit, " Dump API data and exit.";
+    "--version", Arg.Unit display_version, " Display version number and exit.";
+  ] in
+  let anon_fun str = raise (Arg.Bad "generator: unknown parameter") in
+  let usage_msg = "wrappi generator: generates lots of code
+
+To run the generator normally (note it MUST be run from the top
+level SOURCE directory):
+
+  ./generator/generator
+
+Options are for debugging only:
+
+  ./generator/generator [--options]
+
+OPTIONS" in
+  Arg.parse argspec anon_fun usage_msg
+
+let () =
+  printf "generator, %d entry points\n" (List.length eps)