1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
|
(***********************************************************************)
(* *)
(* CamlIDL *)
(* *)
(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
(* *)
(* Copyright 1999 Institut National de Recherche en Informatique et *)
(* en Automatique. All rights reserved. This file is distributed *)
(* under the terms of the GNU Lesser General Public License LGPL v2.1 *)
(* *)
(***********************************************************************)
(* $Id: normalize.ml,v 1.22 2002-01-16 16:15:32 xleroy Exp $ *)
(* Normalization of IDL types after parsing *)
open Printf
open Utils
open Idltypes
open Typedef
open Funct
open Constdecl
open Intf
open File
let structs = (Hashtbl.create 13 : (string, struct_decl) Hashtbl.t)
let unions = (Hashtbl.create 13 : (string, union_decl) Hashtbl.t)
let enums = (Hashtbl.create 13 : (string, enum_decl) Hashtbl.t)
let intfs = (Hashtbl.create 13 : (string, interface) Hashtbl.t)
let typedefs =(Hashtbl.create 13 : (string, type_decl) Hashtbl.t)
let find_typedef s =
try
Hashtbl.find typedefs s
with Not_found ->
error("unknown type name " ^ s)
let expand_typedef s = (find_typedef s).td_type
let _ =
Typedef.find := find_typedef;
Lexpr.expand_typedef := expand_typedef
let all_comps = ref ([] : component list)
let currstamp = ref 0
let newstamp () = incr currstamp; !currstamp
let in_fundecl = ref false
let error_if_fundecl kind =
if !in_fundecl then
error (sprintf "anonymous %s in function parameters or result type" kind)
let make_module_name filename =
Filename.chop_extension (Filename.basename filename)
type char_class = Narrow | Wide
let rec classify_char = function
Type_int((Char | UChar | Byte), _) -> Some Narrow
| Type_int(UShort, _) -> Some Wide
| Type_named(modname, tyname) -> classify_char (expand_typedef tyname)
| Type_const ty -> classify_char ty
| _ -> None
(* Generic function to handle declarations and definitions of struct,
unions, enums and interfaces *)
let process_declarator kind tbl name sourcedecl
proj_contents make_decl update_decl record_decl =
if name = "" then begin
(* Unnamed definition *)
if !in_fundecl then
error (sprintf "anonymous %s in function parameters or result type" kind);
let newdecl = make_decl() in
update_decl newdecl sourcedecl;
record_decl newdecl;
newdecl
end else if proj_contents sourcedecl = [] then begin
(* Reference to previous definition, or forward declaration *)
try
Hashtbl.find tbl name
with Not_found ->
let newdecl = make_decl() in
Hashtbl.add tbl name newdecl;
record_decl (make_decl()); (* record with contents still empty *)
newdecl
end else begin
(* Named definition *)
let decl =
try
Hashtbl.find tbl name
with Not_found ->
let newdecl = make_decl() in
Hashtbl.add tbl name newdecl;
newdecl in
(* Check we're not redefining *)
if proj_contents decl <> [] then
error (sprintf "redefinition of %s %s" kind name);
(* Process the components *)
update_decl decl sourcedecl;
(* Record the full declaration *)
record_decl decl;
decl
end
(* Normalize types and declarators *)
let rec normalize_type = function
Type_pointer(kind, ty_elt) ->
Type_pointer(kind, normalize_type ty_elt)
| Type_array(attr, ty_elt) -> begin
let norm_ty_elt = normalize_type ty_elt in
if not attr.is_string then Type_array(attr, norm_ty_elt) else
match classify_char norm_ty_elt with
| None -> error "[string] argument applies only to \
char array or pointer to char"
| Some Narrow -> Type_array(attr, norm_ty_elt)
| Some Wide ->
let attr' = {attr with is_string = false; null_terminated = true} in
Type_array(attr', norm_ty_elt)
end
| Type_struct sd ->
Type_struct(enter_struct sd)
| Type_union(ud, discr) ->
Type_union(enter_union ud, discr)
| Type_enum (en, attr) ->
Type_enum(enter_enum en, attr)
| Type_named(_, s) ->
begin try
let itf = Hashtbl.find intfs s in
Type_interface(itf.intf_mod, itf.intf_name)
with Not_found ->
try
let td = Hashtbl.find typedefs s in
Type_named(td.td_mod, td.td_name)
with Not_found ->
error("Unknown type name " ^ s)
end
| Type_const ty ->
Type_const(normalize_type ty)
| ty -> ty
and normalize_field f =
{f with field_typ = normalize_type f.field_typ}
and normalize_case c =
match c.case_field with
None -> c
| Some f -> {c with case_field = Some(normalize_field f)}
and enter_struct sd =
process_declarator "struct" structs sd.sd_name sd
(fun sd -> sd.sd_fields)
(fun () ->
{ sd_name = sd.sd_name; sd_mod = !module_name;
sd_stamp = 0; sd_fields = [] })
(fun sd' sd ->
sd'.sd_stamp <- newstamp();
sd'.sd_fields <- List.map normalize_field sd.sd_fields)
(fun sd ->
all_comps := Comp_structdecl sd :: !all_comps)
and enter_union ud =
process_declarator "union" unions ud.ud_name ud
(fun ud -> ud.ud_cases)
(fun () ->
{ ud_name = ud.ud_name; ud_mod = !module_name;
ud_stamp = 0; ud_cases = [] })
(fun ud' ud ->
ud'.ud_stamp <- newstamp();
ud'.ud_cases <- List.map normalize_case ud.ud_cases)
(fun ud ->
all_comps := Comp_uniondecl ud :: !all_comps)
and enter_enum en =
process_declarator "enum" enums en.en_name en
(fun en -> en.en_consts)
(fun () ->
{ en_name = en.en_name; en_mod = !module_name;
en_stamp = 0; en_consts = [] })
(fun en' en ->
en'.en_stamp <- newstamp();
en'.en_consts <- en.en_consts)
(fun en ->
all_comps := Comp_enumdecl en :: !all_comps)
let normalize_fundecl fd =
current_function := fd.fun_name;
in_fundecl := true;
let res =
{ fd with
fun_mod = !module_name;
fun_res = normalize_type fd.fun_res;
fun_params =
List.map (fun (n, io, ty) -> (n,io, normalize_type ty)) fd.fun_params }
in
in_fundecl := false;
current_function := "";
res
let normalize_constdecl cd =
{ cd with cd_type = normalize_type cd.cd_type }
let enter_typedecl td =
let td' =
{ td with td_mod = !module_name;
td_type = if td.td_abstract
then td.td_type
else normalize_type td.td_type } in
all_comps := Comp_typedecl td' :: !all_comps;
Hashtbl.add typedefs td'.td_name td'
let enter_interface i =
process_declarator "interface" intfs i.intf_name i
(fun i -> i.intf_methods)
(fun () ->
{ intf_name = i.intf_name; intf_mod = !module_name;
intf_super = i.intf_super; intf_methods = []; intf_uid = "" })
(fun i' i ->
let super =
try
Hashtbl.find intfs i.intf_super.intf_name
with Not_found ->
error (sprintf "unknown interface %s as super-interface of %s"
i.intf_super.intf_name i.intf_name) in
i'.intf_uid <- i.intf_uid;
i'.intf_super <- super;
i'.intf_methods <- List.map normalize_fundecl i.intf_methods)
(fun i ->
all_comps := Comp_interface i :: !all_comps)
let rec normalize_component = function
Comp_typedecl td -> enter_typedecl td
| Comp_structdecl sd -> ignore(enter_struct sd)
| Comp_uniondecl ud -> ignore(enter_union ud)
| Comp_enumdecl en -> ignore(enter_enum en)
| Comp_fundecl fd ->
all_comps := Comp_fundecl(normalize_fundecl fd) :: !all_comps
| Comp_constdecl cd ->
all_comps := Comp_constdecl(normalize_constdecl cd) :: !all_comps
| Comp_diversion(ty, s) ->
all_comps := Comp_diversion(ty, s) :: !all_comps
| Comp_interface intf -> ignore(enter_interface intf)
| Comp_import(filename, comps) ->
let name = make_module_name filename in
let saved_name = !module_name in
module_name := name;
let comps' = normalize_components comps in
module_name := saved_name;
all_comps := Comp_import(name, comps') :: !all_comps
and normalize_components comps =
let saved_all_comps = !all_comps in
all_comps := [];
List.iter normalize_component comps;
let ac = List.rev !all_comps in
all_comps := saved_all_comps;
ac
(* Main entry point *)
let normalize_file filename =
Hashtbl.clear structs;
Hashtbl.clear unions;
Hashtbl.clear enums;
Hashtbl.clear intfs;
Hashtbl.clear typedefs;
List.iter (fun td -> Hashtbl.add typedefs td.td_name td) Predef.typedefs;
List.iter (fun i -> Hashtbl.add intfs i.intf_name i) Predef.interfaces;
module_name := make_module_name filename;
let res =
normalize_components (Fixlabels.prefix_file (Parse.read_file filename)) in
Hashtbl.clear structs;
Hashtbl.clear unions;
Hashtbl.clear enums;
Hashtbl.clear intfs;
res
|