From bb1329db94910f6739c839bee52177f1b3c4e695 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Thu, 29 Dec 2011 13:54:27 +0000 Subject: [PATCH] Generator main program. --- .gitignore | 2 ++ APIs/.depend | 2 ++ APIs/Makefile.am | 23 +++++++++++++--- configure.ac | 1 + generator-lib/.depend | 5 ++++ generator-lib/Makefile.am | 20 +++++++++++--- generator-lib/config.ml.in | 20 ++++++++++++++ generator-lib/wrappi_globals.ml | 30 ++++++++++++++++++++ generator-lib/wrappi_globals.mli | 26 ++++++++++++++++++ generator-lib/wrappi_types.ml | 38 ++++++++++++++++++++++++++ generator-lib/wrappi_types.mli | 47 ++++++++++++++++++++++++++++++++ generator-macros/.depend | 6 ++-- generator-macros/pa_wrap.ml | 40 +++++++++++++++++++++------ generator/.depend | 2 ++ generator/Makefile.am | 16 ++++++++++- generator/wrappi_main.ml | 59 ++++++++++++++++++++++++++++++++++++++++ 16 files changed, 316 insertions(+), 21 deletions(-) create mode 100644 APIs/.depend create mode 100644 generator-lib/config.ml.in create mode 100644 generator-lib/wrappi_globals.ml create mode 100644 generator-lib/wrappi_globals.mli create mode 100644 generator-lib/wrappi_types.mli create mode 100644 generator/wrappi_main.ml diff --git a/.gitignore b/.gitignore index 862ad54..ec9a5fb 100644 --- a/.gitignore +++ b/.gitignore @@ -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 index 0000000..640631a --- /dev/null +++ b/APIs/.depend @@ -0,0 +1,2 @@ +mkdir.cmo: +mkdir.cmx: diff --git a/APIs/Makefile.am b/APIs/Makefile.am index 0edf67d..b386941 100644 --- a/APIs/Makefile.am +++ b/APIs/Makefile.am @@ -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 diff --git a/configure.ac b/configure.ac index fb2717b..1182568 100644 --- a/configure.ac +++ b/configure.ac @@ -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]) diff --git a/generator-lib/.depend b/generator-lib/.depend index e69de29..9373889 100644 --- a/generator-lib/.depend +++ b/generator-lib/.depend @@ -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 diff --git a/generator-lib/Makefile.am b/generator-lib/Makefile.am index 809965b..a4a6111 100644 --- a/generator-lib/Makefile.am +++ b/generator-lib/Makefile.am @@ -15,15 +15,27 @@ # 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 index 0000000..3c3ce90 --- /dev/null +++ b/generator-lib/config.ml.in @@ -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 index 0000000..5d68a4f --- /dev/null +++ b/generator-lib/wrappi_globals.ml @@ -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 index 0000000..488cda8 --- /dev/null +++ b/generator-lib/wrappi_globals.mli @@ -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 diff --git a/generator-lib/wrappi_types.ml b/generator-lib/wrappi_types.ml index 3f3ca58..7c3dfde 100644 --- a/generator-lib/wrappi_types.ml +++ b/generator-lib/wrappi_types.ml @@ -16,6 +16,44 @@ * 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 index 0000000..6120aff --- /dev/null +++ b/generator-lib/wrappi_types.mli @@ -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. *) diff --git a/generator-macros/.depend b/generator-macros/.depend index c44a80c..baa61b8 100644 --- a/generator-macros/.depend +++ b/generator-macros/.depend @@ -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: diff --git a/generator-macros/pa_wrap.ml b/generator-macros/pa_wrap.ml index c8e8af8..54e3676 100644 --- a/generator-macros/pa_wrap.ml +++ b/generator-macros/pa_wrap.ml @@ -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"; diff --git a/generator/.depend b/generator/.depend index e69de29..062bc8e 100644 --- a/generator/.depend +++ b/generator/.depend @@ -0,0 +1,2 @@ +wrappi_main.cmo: +wrappi_main.cmx: diff --git a/generator/Makefile.am b/generator/Makefile.am index 6cfc2c2..3b0d6b4 100644 --- a/generator/Makefile.am +++ b/generator/Makefile.am @@ -15,9 +15,23 @@ # 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 index 0000000..aaf3719 --- /dev/null +++ b/generator/wrappi_main.ml @@ -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) -- 1.8.3.1