+(* 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 Camlp4.PreCast
+
+open Wrappi_types
+open Wrappi_utils
+
+open Printf
+
+let check_not_defined name new_ map thing get_loc =
+ try
+ let old = StringMap.find name map in
+ eprintf "generator: %s %s redefined\n" thing name;
+ let old_loc = get_loc old in
+ let new_loc = get_loc new_ in
+ eprintf " first definition at %s:%d\n"
+ (Loc.file_name old_loc) (Loc.start_line old_loc);
+ eprintf " second definition at %s:%d\n"
+ (Loc.file_name new_loc) (Loc.start_line new_loc);
+ exit 1
+ with
+ Not_found -> ()
+
+let tds = ref StringMap.empty
+let add_typedef td =
+ let name = td.td_name in
+ check_not_defined name td !tds "typedef" (fun td -> td.td_loc);
+ tds := StringMap.add name td !tds
+
+let ens = ref StringMap.empty
+let add_enum en =
+ let name = en.en_name in
+ check_not_defined name en !ens "enum" (fun en -> en.en_loc);
+ ens := StringMap.add name en !ens
+
+let sds = ref StringMap.empty
+let add_struct sd =
+ let name = sd.sd_name in
+ check_not_defined name sd !sds "struct" (fun sd -> sd.sd_loc);
+ sds := StringMap.add name sd !sds
+
+let uns = ref StringMap.empty
+let add_union un =
+ let name = un.un_name in
+ check_not_defined name un !uns "union" (fun un -> un.un_loc);
+ uns := StringMap.add name un !uns
+
+let eps = ref StringMap.empty
+let add_entry_point ep =
+ let name = ep.ep_name in
+ check_not_defined name ep !eps "entry_point" (fun ep -> ep.ep_loc);
+ eps := StringMap.add name ep !eps
+
+let rec resolve_typedefs thing name loc = function
+ | (TBool
+ | TBuffer
+ | TEnum _
+ | TFile
+ | TInt
+ | TInt32
+ | TInt64
+ | TString
+ | TStruct _
+ | TUInt32
+ | TUInt64
+ | TUnion _) as t -> t
+
+ | THash t -> THash (resolve_typedefs thing name loc t)
+ | TList t -> TList (resolve_typedefs thing name loc t)
+ | TNullable t -> TNullable (resolve_typedefs thing name loc t)
+
+ | TTypedef tname ->
+ try (StringMap.find tname !tds).td_type
+ with Not_found ->
+ eprintf "generator: could not resolve typedef %s\n" tname;
+ eprintf " in definition of %s %s at %s:%d\n"
+ thing name (Loc.file_name loc) (Loc.start_line loc);
+ exit 1
+
+let resolve_typedefs_in_ret thing name loc = function
+ | RErr as t -> t
+ | Return t -> Return (resolve_typedefs thing name loc t)
+
+let get_api () =
+ let tds = !tds in
+ let ens = !ens in
+ let sds = !sds in
+ let uns = !uns in
+ let eps = !eps in
+
+ (* Resolve typedefs in all ptypes in everything. *)
+ let sds = StringMap.map (
+ fun sd ->
+ let fields = sd.sd_fields in
+ let fields =
+ Array.map (resolve_typedefs "enum" sd.sd_name sd.sd_loc) fields in
+ { sd with sd_fields = fields }
+ ) sds in
+
+ let uns = StringMap.map (
+ fun un ->
+ let fields = un.un_fields in
+ let fields =
+ Array.map (resolve_typedefs "union" un.un_name un.un_loc) fields in
+ { un with un_fields = fields }
+ ) uns in
+
+ let eps = StringMap.map (
+ fun ep ->
+ let name = ep.ep_name in
+ let loc = ep.ep_loc in
+ let ret, req, opt = ep.ep_ftype in
+ let ret = resolve_typedefs_in_ret "entry_point" name loc ret in
+ let req = List.map (
+ fun (n, t, prec) ->
+ n, resolve_typedefs "entry_point" name loc t, prec
+ ) req in
+ let opt = List.map (
+ fun (n, t, prec) ->
+ n, resolve_typedefs "entry_point" name loc t, prec
+ ) opt in
+ { ep with ep_ftype = (ret, req, opt) }
+ ) eps in
+
+ { api_typedefs = tds;
+ api_enums = ens;
+ api_structs = sds;
+ api_unions = uns;
+ api_entry_points = eps }