aboutsummaryrefslogtreecommitdiffstats
path: root/cparser/Cutil.ml
diff options
context:
space:
mode:
Diffstat (limited to 'cparser/Cutil.ml')
-rw-r--r--cparser/Cutil.ml57
1 files changed, 51 insertions, 6 deletions
diff --git a/cparser/Cutil.ml b/cparser/Cutil.ml
index f5d5c425..2334966c 100644
--- a/cparser/Cutil.ml
+++ b/cparser/Cutil.ml
@@ -37,6 +37,15 @@ module IdentMap = Map.Make(Ident)
(* Operations on attributes *)
+(* Normalize the name of an attribute, removing starting and trailing '__' *)
+
+let re_normalize_attrname = Str.regexp "^__\\(.*\\)__$"
+
+let normalize_attrname a =
+ if Str.string_match re_normalize_attrname a 0
+ then Str.matched_group 1 a
+ else a
+
(* Lists of attributes are kept sorted in increasing order *)
let rec add_attributes (al1: attributes) (al2: attributes) =
@@ -83,18 +92,35 @@ let rec remove_custom_attributes (names: string list) (al: attributes) =
| a :: tl ->
a :: remove_custom_attributes names tl
+(* Classification of attributes *)
+
+type attribute_class =
+ | Attr_name (* Attribute applies to the names being declared *)
+ | Attr_type (* Attribute applies to types *)
+ | Attr_struct (* Attribute applies to struct, union and enum *)
+ | Attr_function (* Attribute applies to function types and decls *)
+ | Attr_unknown (* Unknown attribute *)
+
+let attr_class : (string, attribute_class) Hashtbl.t = Hashtbl.create 32
+
+let declare_attribute name cls =
+ Hashtbl.replace attr_class (normalize_attrname name) cls
+
+let declare_attributes l =
+ List.iter (fun (n,c) -> declare_attribute n c) l
+
+let class_of_attribute = function
+ | AConst | AVolatile | ARestrict | AAlignas _ -> Attr_type
+ | Attr(name, args) ->
+ try Hashtbl.find attr_class (normalize_attrname name)
+ with Not_found -> Attr_unknown
+
(* Is an attribute a ISO C standard attribute? *)
let attr_is_standard = function
| AConst | AVolatile | ARestrict -> true
| AAlignas _ | Attr _ -> false
-(* Is an attribute type-related (true) or variable-related (false)? *)
-
-let attr_is_type_related = function
- | Attr(("packed" | "__packed__"), _) -> true
- | _ -> false
-
(* Is an attribute applicable to a whole array (true) or only to
array elements (false)? *)
@@ -533,6 +559,25 @@ let sizeof_struct env members =
end
in sizeof_rec 0 members
+(* Compute the offset of a struct member *)
+let offsetof env ty field =
+ let rec sub acc name = function
+ | [] -> List.rev acc
+ | m::rem -> if m.fld_name = name then
+ List.rev acc
+ else
+ sub (m::acc) name rem in
+ match unroll env ty with
+ | TStruct (id,_) ->
+ let str = Env.find_struct env id in
+ let pre = sub [] field.fld_name str.ci_members in
+ begin match sizeof_struct env pre, alignof env field.fld_typ with
+ | Some s, Some a ->
+ align s a
+ | _ -> assert false end
+ | TUnion _ -> 0
+ | _ -> assert false
+
(* Simplified version to compute offsets on structs without bitfields *)
let struct_layout env members =
let rec struct_layout_rec mem ofs = function