diff options
Diffstat (limited to 'cparser/Cutil.ml')
-rw-r--r-- | cparser/Cutil.ml | 57 |
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 |