123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672 |
- /*
- * Copyright (C) 2011-2018 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
- %{
- open Util (* for failwithf *)
- (* Here we defined some helper routines to check attributes.
- *
- * An alternative approach is to code these rules in Lexer/Parser but
- * it has several drawbacks:
- *
- * 1. Bad extensibility;
- * 2. It grows the table size and down-graded the parsing time;
- * 3. It makes error reporting rigid this way.
- *)
- let get_string_from_attr (v: Ast.attr_value) (err_func: int -> string) =
- match v with
- Ast.AString s -> s
- | Ast.ANumber n -> err_func n
- (* Check whether 'size' is specified. *)
- let has_size (sattr: Ast.ptr_size) =
- sattr.Ast.ps_size <> None
-
- (* Check whether 'count' is specified. *)
- let has_count (sattr: Ast.ptr_size) =
- sattr.Ast.ps_count <> None
- (* Pointers can have the following attributes:
- *
- * 'size' - specifies the size of the pointer.
- * e.g. size = 4, size = val ('val' is a parameter);
- *
- * 'count' - indicates how many of items is managed by the pointer
- * e.g. count = 100, count = n ('n' is a parameter);
- *
- * 'string' - indicate the pointer is managing a C string;
- * 'wstring' - indicate the pointer is managing a wide char string.
- *
- * 'isptr' - to specify that the foreign type is a pointer.
- * 'isary' - to specify that the foreign type is an array.
- * 'readonly' - to specify that the foreign type has a 'const' qualifier.
- *
- * 'user_check' - inhibit Edger8r from generating code to check the pointer.
- *
- * 'in' - the pointer is used as input
- * 'out' - the pointer is used as output
- *
- * Note that 'size' can be used together with 'count'.
- * 'string' and 'wstring' indicates 'isptr',
- * and they cannot be used with only an 'out' attribute.
- *)
- let get_ptr_attr (attr_list: (string * Ast.attr_value) list) =
- let get_new_dir (cds: string) (cda: Ast.ptr_direction) (old: Ast.ptr_direction) =
- if old = Ast.PtrNoDirection then cda
- else if old = Ast.PtrInOut then failwithf "duplicated attribute: `%s'" cds
- else if old = cda then failwithf "duplicated attribute: `%s'" cds
- else Ast.PtrInOut
- in
- (* only one 'size' attribute allowed. *)
- let get_new_size (new_value: Ast.attr_value) (old_ptr_size: Ast.ptr_size) =
- if has_size old_ptr_size then
- failwithf "duplicated attribute: `size'"
- else new_value
- in
- (* only one 'count' attribute allowed. *)
- let get_new_count (new_value: Ast.attr_value) (old_ptr_size: Ast.ptr_size) =
- if has_count old_ptr_size then
- failwithf "duplicated attribute: `count'"
- else new_value
- in
- let update_attr (key: string) (value: Ast.attr_value) (res: Ast.ptr_attr) =
- match key with
- "size" ->
- { res with Ast.pa_size = { res.Ast.pa_size with Ast.ps_size = Some(get_new_size value res.Ast.pa_size)}}
- | "count" ->
- { res with Ast.pa_size = { res.Ast.pa_size with Ast.ps_count = Some(get_new_count value res.Ast.pa_size)}}
- | "sizefunc" ->
- failwithf "The attribute 'sizefunc' is deprecated. Please use 'size' attribute instead."
- | "string" -> { res with Ast.pa_isstr = true; }
- | "wstring" -> { res with Ast.pa_iswstr = true; }
- | "isptr" -> { res with Ast.pa_isptr = true }
- | "isary" -> { res with Ast.pa_isary = true }
- | "readonly" -> { res with Ast.pa_rdonly = true }
- | "user_check" -> { res with Ast.pa_chkptr = false }
- | "in" ->
- let newdir = get_new_dir "in" Ast.PtrIn res.Ast.pa_direction
- in { res with Ast.pa_direction = newdir }
- | "out" ->
- let newdir = get_new_dir "out" Ast.PtrOut res.Ast.pa_direction
- in { res with Ast.pa_direction = newdir }
- | _ -> failwithf "unknown attribute: %s" key
- in
- let rec do_get_ptr_attr alist res_attr =
- match alist with
- [] -> res_attr
- | (k,v) :: xs -> do_get_ptr_attr xs (update_attr k v res_attr)
- in
- let has_str_attr (pattr: Ast.ptr_attr) =
- if pattr.Ast.pa_isstr && pattr.Ast.pa_iswstr
- then failwith "`string' and `wstring' are mutual exclusive"
- else (pattr.Ast.pa_isstr || pattr.Ast.pa_iswstr)
- in
- let check_invalid_ptr_size (pattr: Ast.ptr_attr) =
- let ps = pattr.Ast.pa_size in
- if ps <> Ast.empty_ptr_size && has_str_attr pattr
- then failwith "size attributes are mutual exclusive with (w)string attribute"
- else
- if (ps <> Ast.empty_ptr_size || has_str_attr pattr) &&
- pattr.Ast.pa_direction = Ast.PtrNoDirection
- then failwith "size/string attributes must be used with pointer direction"
- else pattr
- in
- let check_ptr_dir (pattr: Ast.ptr_attr) =
- if pattr.Ast.pa_direction <> Ast.PtrNoDirection && pattr.Ast.pa_chkptr = false
- then failwith "pointer direction and `user_check' are mutual exclusive"
- else
- if pattr.Ast.pa_direction = Ast.PtrNoDirection && pattr.Ast.pa_chkptr
- then failwith "pointer/array should have direction attribute or `user_check'"
- else
- if pattr.Ast.pa_direction = Ast.PtrOut && has_str_attr pattr
- then failwith "string/wstring should be used with an `in' attribute"
- else pattr
- in
- let check_invalid_ary_attr (pattr: Ast.ptr_attr) =
- if pattr.Ast.pa_size <> Ast.empty_ptr_size
- then failwith "Pointer size attributes cannot be used with foreign array"
- else
- if not pattr.Ast.pa_isptr
- then
- (* 'pa_chkptr' is default to true unless user specifies 'user_check' *)
- if pattr.Ast.pa_chkptr && pattr.Ast.pa_direction = Ast.PtrNoDirection
- then failwith "array must have direction attribute or `user_check'"
- else pattr
- else
- if has_str_attr pattr
- then failwith "`isary' cannot be used with `string/wstring' together"
- else failwith "`isary' cannot be used with `isptr' together"
- in
- let pattr = do_get_ptr_attr attr_list { Ast.pa_direction = Ast.PtrNoDirection;
- Ast.pa_size = Ast.empty_ptr_size;
- Ast.pa_isptr = false;
- Ast.pa_isary = false;
- Ast.pa_isstr = false;
- Ast.pa_iswstr = false;
- Ast.pa_rdonly = false;
- Ast.pa_chkptr = true;
- }
- in
- if pattr.Ast.pa_isary
- then check_invalid_ary_attr pattr
- else check_invalid_ptr_size pattr |> check_ptr_dir
- (* Untrusted functions can have these attributes:
- *
- * a. 3 mutual exclusive calling convention specifier:
- * 'stdcall', 'fastcall', 'cdecl'.
- *
- * b. 'dllimport' - to import a public symbol.
- *)
- let get_func_attr (attr_list: (string * Ast.attr_value) list) =
- let get_new_callconv (key: string) (cur: Ast.call_conv) (old: Ast.call_conv) =
- if old <> Ast.CC_NONE then
- failwithf "unexpected `%s', conflict with `%s'." key (Ast.get_call_conv_str old)
- else cur
- in
- let update_attr (key: string) (value: Ast.attr_value) (res: Ast.func_attr) =
- match key with
- | "stdcall" ->
- let callconv = get_new_callconv key Ast.CC_STDCALL res.Ast.fa_convention
- in { res with Ast.fa_convention = callconv}
- | "fastcall" ->
- let callconv = get_new_callconv key Ast.CC_FASTCALL res.Ast.fa_convention
- in { res with Ast.fa_convention = callconv}
- | "cdecl" ->
- let callconv = get_new_callconv key Ast.CC_CDECL res.Ast.fa_convention
- in { res with Ast.fa_convention = callconv}
- | "dllimport" ->
- if res.Ast.fa_dllimport then failwith "duplicated attribute: `dllimport'"
- else { res with Ast.fa_dllimport = true }
- | _ -> failwithf "invalid function attribute: %s" key
- in
- let rec do_get_func_attr alist res_attr =
- match alist with
- [] -> res_attr
- | (k,v) :: xs -> do_get_func_attr xs (update_attr k v res_attr)
- in do_get_func_attr attr_list { Ast.fa_dllimport = false;
- Ast.fa_convention= Ast.CC_NONE;
- }
- (* Some syntax checking against pointer attributes.
- * range: (Lexing.position * Lexing.position)
- *)
- let check_ptr_attr (fd: Ast.func_decl) range =
- let fname = fd.Ast.fname in
- let check_const (pattr: Ast.ptr_attr) (identifier: string) =
- let raise_err_direction (direction:string) =
- failwithf "`%s': `%s' is readonly - cannot be used with `%s'"
- fname identifier direction
- in
- if pattr.Ast.pa_rdonly
- then
- match pattr.Ast.pa_direction with
- Ast.PtrOut | Ast.PtrInOut -> raise_err_direction "out"
- | _ -> ()
- else ()
- in
- let check_void_ptr_size (pattr: Ast.ptr_attr) (identifier: string) =
- if pattr.Ast.pa_chkptr && (not (has_size pattr.Ast.pa_size))
- then failwithf "`%s': void pointer `%s' - buffer size unknown" fname identifier
- else ()
- in
- let check_string_ptr_size (atype: Ast.atype) (pattr: Ast.ptr_attr) (identifier: string) =
- if (pattr.Ast.pa_isstr)
- then
- match atype with
- Ast.Ptr(Ast.Char(_)) -> ()
- | _ -> failwithf "`%s': invalid 'string' attribute - `%s' is not char pointer." fname identifier
- else
- if (atype <> Ast.Ptr(Ast.WChar) && pattr.Ast.pa_iswstr)
- then failwithf "`%s': invalid 'wstring' attribute - `%s' is not wchar_t pointer." fname identifier
- else ()
- in
- let check_array_dims (atype: Ast.atype) (pattr: Ast.ptr_attr) (declr: Ast.declarator) =
- if Ast.is_array declr then
- if has_size pattr.Ast.pa_size then
- failwithf "`%s': invalid 'size' attribute - `%s' is explicitly declared array." fname declr.Ast.identifier
- else if has_count pattr.Ast.pa_size then
- failwithf "`%s': invalid 'count' attribute - `%s' is explicitly declared array." fname declr.Ast.identifier
- else if pattr.Ast.pa_isary then
- failwithf "`%s': invalid 'isary' attribute - `%s' is explicitly declared array." fname declr.Ast.identifier
- else ()
- in
- let check_pointer_array (atype: Ast.atype) (pattr: Ast.ptr_attr) (declr: Ast.declarator) =
- let is_ary = (Ast.is_array declr || pattr.Ast.pa_isary) in
- let is_ptr =
- match atype with
- Ast.Ptr _ -> true
- | _ -> pattr.Ast.pa_isptr
- in
- if is_ary && is_ptr then
- failwithf "`%s': Pointer array not allowed - `%s' is a pointer array." fname declr.Ast.identifier
- else ()
- in
- let checker (pd: Ast.pdecl) =
- let pt, declr = pd in
- let identifier = declr.Ast.identifier in
- match pt with
- Ast.PTVal _ -> ()
- | Ast.PTPtr(atype, pattr) ->
- if atype = Ast.Ptr(Ast.Void) then (* 'void' pointer, check there is a size or 'user_check' *)
- check_void_ptr_size pattr identifier
- else
- check_pointer_array atype pattr declr;
- check_const pattr identifier;
- check_string_ptr_size atype pattr identifier;
- check_array_dims atype pattr declr
- in
- List.iter checker fd.Ast.plist
- %}
- %token EOF
- %token TDot TComma TSemicolon TPtr TEqual
- %token TLParen TRParen
- %token TLBrace TRBrace
- %token TLBrack TRBrack
- %token Tpublic
- %token Tinclude
- %token Tconst
- %token <string>Tidentifier
- %token <int>Tnumber
- %token <string>Tstring
- %token Tchar Tshort Tunsigned Tint Tfloat Tdouble
- Tint8 Tint16 Tint32 Tint64
- Tuint8 Tuint16 Tuint32 Tuint64
- Tsizet Twchar Tvoid Tlong Tstruct Tunion Tenum
- %token Tenclave Tfrom Timport Ttrusted Tuntrusted Tallow Tpropagate_errno
- %start start_parsing
- %type <Ast.enclave> start_parsing
- /* Grammar follows */
- %%
- /* Type definitions
- * ------------------------------------------------------------------------
- */
- char_type: Tchar { Ast.Char Ast.Signed }
- | Tunsigned Tchar { Ast.Char Ast.Unsigned }
- ;
- /* Explicit shortness. */
- ex_shortness: Tshort { Ast.IShort }
- | Tlong { Ast.ILong }
- ;
- longlong: Tlong Tlong { Ast.LLong Ast.Signed }
- | Tunsigned Tlong Tlong { Ast.LLong Ast.Unsigned }
- shortness: /* empty */ { Ast.INone }
- | ex_shortness { $1 }
- ;
- int_type: shortness Tint {
- Ast.Int { Ast.ia_signedness = Ast.Signed; Ast.ia_shortness = $1 }
- }
- | Tunsigned shortness Tint {
- Ast.Int { Ast.ia_signedness = Ast.Unsigned; Ast.ia_shortness = $2 }
- }
- | Tunsigned shortness {
- Ast.Int { Ast.ia_signedness = Ast.Unsigned; Ast.ia_shortness = $2 }
- }
- | longlong { $1 }
- | ex_shortness {
- Ast.Int { Ast.ia_signedness = Ast.Signed; Ast.ia_shortness = $1 }
- }
- ;
- type_spec:
- char_type { $1 }
- | int_type { $1 }
- | Tfloat { Ast.Float }
- | Tdouble { Ast.Double }
- | Tlong Tdouble { Ast.LDouble }
- | Tint8 { Ast.Int8 }
- | Tint16 { Ast.Int16 }
- | Tint32 { Ast.Int32 }
- | Tint64 { Ast.Int64 }
- | Tuint8 { Ast.UInt8 }
- | Tuint16 { Ast.UInt16 }
- | Tuint32 { Ast.UInt32 }
- | Tuint64 { Ast.UInt64 }
- | Tsizet { Ast.SizeT }
- | Twchar { Ast.WChar }
- | Tvoid { Ast.Void }
- | struct_specifier { $1 }
- | union_specifier { $1 }
- | enum_specifier { $1 }
- | Tidentifier { Ast.Foreign($1) } /* User defined types in C header */
- ;
- pointer: TPtr { fun ii -> Ast.Ptr(ii) }
- | pointer TPtr { fun ii -> Ast.Ptr($1 ii) }
- ;
- empty_dimension: TLBrack TRBrack { failwith "Flexible array is not supported." }
- fixed_dimension: TLBrack Tnumber TRBrack { if $2 <> 0 then [$2]
- else failwith "Zero-length array is not supported." }
- fixed_size_array: fixed_dimension { $1 }
- | fixed_size_array fixed_dimension { $1 @ $2 }
- ;
- array_size: fixed_size_array { $1 }
- | empty_dimension { $1 }
- | empty_dimension fixed_size_array { $1 @ $2 }
- ;
- all_type: type_spec { $1 }
- | type_spec pointer { $2 $1 }
- ;
- declarator: Tidentifier { { Ast.identifier = $1; Ast.array_dims = []; } }
- | Tidentifier array_size { { Ast.identifier = $1; Ast.array_dims = $2; } }
- ;
- /* Available types as parameter.
- *
- * Instead of returning an value of 'Ast.parameter_type', we return
- * a lambda which wraps the actual type since so far there is no way
- * to tell whether the identifier is followed by array dimensions.
- */
- param_type: attr_block all_type {
- let attr = get_ptr_attr $1 in
- (*check the type is build in type or used defined type.*)
- let rec is_foreign s =
- match s with
- Ast.Ptr(a) -> is_foreign a
- | Ast.Foreign _ -> true
- | _ -> false
- in
- let is_bare_foreign s =
- match s with
- | Ast.Foreign _ -> true
- | _ -> false
- in
- (*'isptr', 'isary', only allowed for bare user defined type.*)
- (*'readonly' only allowed for user defined type.*)
- if attr.Ast.pa_isptr && not (is_bare_foreign $2) then
- failwithf "'isptr', attributes are only for user defined type, not for `%s'." (Ast.get_tystr $2)
- else if attr.Ast.pa_isary && not (is_bare_foreign $2) then
- failwithf "'isary', attributes are only for user defined type, not for `%s'." (Ast.get_tystr $2)
- else if attr.Ast.pa_rdonly && not (is_foreign $2) then
- failwithf "'readonly', attributes are only for user defined type, not for `%s'." (Ast.get_tystr $2)
- else if attr.Ast.pa_rdonly && not (attr.Ast.pa_isptr) then
- failwithf "'readonly' attribute is only used with 'isptr' attribute." else
- match $2 with
- Ast.Ptr _ -> fun x -> Ast.PTPtr($2, get_ptr_attr $1)
- | _ ->
- if $1 <> [] then
- let attr = get_ptr_attr $1 in
- match $2 with
- Ast.Foreign s ->
- if attr.Ast.pa_isptr || attr.Ast.pa_isary then fun x -> Ast.PTPtr($2, attr)
- else
- (* thinking about 'user_defined_type var[4]' *)
- fun is_ary ->
- if is_ary then Ast.PTPtr($2, attr)
- else failwithf "`%s' is considered plain type but decorated with pointer attributes" s
- | _ ->
- fun is_ary ->
- if is_ary then Ast.PTPtr($2, attr)
- else failwithf "unexpected pointer attributes for `%s'" (Ast.get_tystr $2)
- else
- fun is_ary ->
- if is_ary then Ast.PTPtr($2, get_ptr_attr [])
- else Ast.PTVal $2
- }
- | all_type {
- match $1 with
- Ast.Ptr _ -> fun x -> Ast.PTPtr($1, get_ptr_attr [])
- | _ ->
- fun is_ary ->
- if is_ary then Ast.PTPtr($1, get_ptr_attr [])
- else Ast.PTVal $1
- }
- | attr_block Tconst type_spec pointer {
- let attr = get_ptr_attr $1
- in fun x -> Ast.PTPtr($4 $3, { attr with Ast.pa_rdonly = true })
- }
- | Tconst type_spec pointer {
- let attr = get_ptr_attr []
- in fun x -> Ast.PTPtr($3 $2, { attr with Ast.pa_rdonly = true })
- }
- ;
- attr_block: TLBrack TRBrack { failwith "no attribute specified." }
- | TLBrack key_val_pairs TRBrack { $2 }
- ;
- key_val_pairs: key_val_pair { [$1] }
- | key_val_pairs TComma key_val_pair { $3 :: $1 }
- ;
- key_val_pair: Tidentifier TEqual Tidentifier { ($1, Ast.AString($3)) }
- | Tidentifier TEqual Tnumber { ($1, Ast.ANumber($3)) }
- | Tidentifier { ($1, Ast.AString("")) }
- ;
- struct_specifier: Tstruct Tidentifier { Ast.Struct($2) }
- union_specifier: Tunion Tidentifier { Ast.Union($2) }
- enum_specifier: Tenum Tidentifier { Ast.Enum($2) }
- struct_definition: struct_specifier TLBrace member_list TRBrace {
- let s = { Ast.sname = (match $1 with Ast.Struct s -> s | _ -> "");
- Ast.mlist = List.rev $3; }
- in Ast.StructDef(s)
- }
- union_definition: union_specifier TLBrace member_list TRBrace {
- let s = { Ast.sname = (match $1 with Ast.Union s -> s | _ -> "");
- Ast.mlist = List.rev $3; }
- in Ast.UnionDef(s)
- }
- /* enum can be anonymous. */
- enum_definition: Tenum TLBrace enum_body TRBrace {
- let e = { Ast.enname = ""; Ast.enbody = $3; }
- in Ast.EnumDef(e)
- }
- | enum_specifier TLBrace enum_body TRBrace {
- let e = { Ast.enname = (match $1 with Ast.Enum s -> s | _ -> "");
- Ast.enbody = $3; }
- in Ast.EnumDef(e)
- }
- ;
- enum_body: /* empty */ { [] }
- | enum_eles { List.rev $1 }
- ;
- enum_eles: enum_ele { [$1] }
- | enum_eles TComma enum_ele { $3 :: $1 }
- ;
- enum_ele: Tidentifier { ($1, Ast.EnumValNone) }
- | Tidentifier TEqual Tidentifier { ($1, Ast.EnumVal (Ast.AString $3)) }
- | Tidentifier TEqual Tnumber { ($1, Ast.EnumVal (Ast.ANumber $3)) }
- ;
- composite_defs: struct_definition { $1 }
- | union_definition { $1 }
- | enum_definition { $1 }
- ;
- member_list: member_def TSemicolon { [$1] }
- | member_list member_def TSemicolon { $2 :: $1 }
- ;
- member_def: all_type declarator { ($1, $2) }
- /* Importing declarations.
- * ------------------------------------------------------------------------
- */
- func_list: Tidentifier { [$1] }
- | func_list TComma Tidentifier { $3 :: $1 }
- ;
- module_path: Tstring { $1 }
- import_declaration: Tfrom module_path Timport func_list {
- { Ast.mname = $2; Ast.flist = List.rev $4; }
- }
- | Tfrom module_path Timport TPtr {
- { Ast.mname = $2; Ast.flist = ["*"]; }
- }
- ;
- include_declaration: Tinclude Tstring { $2 }
- include_declarations: include_declaration { [$1] }
- | include_declarations include_declaration { $2 :: $1 }
- ;
- /* Enclave function declarations.
- * ------------------------------------------------------------------------
- */
- enclave_functions: Ttrusted TLBrace trusted_block TRBrace TSemicolon {
- List.rev $3
- }
- | Tuntrusted TLBrace untrusted_block TRBrace TSemicolon {
- List.rev $3
- }
- ;
- trusted_block: trusted_functions { $1 }
- | include_declarations trusted_functions {
- trusted_headers := !trusted_headers @ List.rev $1; $2
- }
- ;
- untrusted_block: untrusted_functions { $1 }
- | include_declarations untrusted_functions {
- untrusted_headers := !untrusted_headers @ List.rev $1; $2
- }
- ;
- /* is_priv? Default to true. */
- access_modifier: /* nothing */ { true }
- | Tpublic { false }
- ;
- trusted_functions: /* nothing */ { [] }
- | trusted_functions access_modifier func_def TSemicolon {
- check_ptr_attr $3 (symbol_start_pos(), symbol_end_pos());
- Ast.Trusted { Ast.tf_fdecl = $3; Ast.tf_is_priv = $2 } :: $1
- }
- ;
- untrusted_functions: /* nothing */ { [] }
- | untrusted_functions untrusted_func_def TSemicolon { $2 :: $1 }
- ;
- func_def: all_type Tidentifier parameter_list {
- { Ast.fname = $2; Ast.rtype = $1; Ast.plist = List.rev $3 ; }
- }
- | all_type array_size Tidentifier parameter_list {
- failwithf "%s: returning an array is not supported - use pointer instead." $3
- }
- ;
- parameter_list: TLParen TRParen { [] }
- | TLParen Tvoid TRParen { [] } /* Make C programers comfortable */
- | TLParen parameter_defs TRParen { $2 }
- ;
- parameter_defs: parameter_def { [$1] }
- | parameter_defs TComma parameter_def { $3 :: $1 }
- ;
- parameter_def: param_type declarator {
- let pt = $1 (Ast.is_array $2) in
- let is_void =
- match pt with
- Ast.PTVal v -> v = Ast.Void
- | _ -> false
- in
- if is_void then
- failwithf "parameter `%s' has `void' type." $2.Ast.identifier
- else
- (pt, $2)
- }
- /* propagate_errno? Default to false. */
- propagate_errno: /* nothing */ { false }
- | Tpropagate_errno { true }
- ;
- untrusted_func_def: attr_block func_def allow_list propagate_errno {
- check_ptr_attr $2 (symbol_start_pos(), symbol_end_pos());
- let fattr = get_func_attr $1 in
- Ast.Untrusted { Ast.uf_fdecl = $2; Ast.uf_fattr = fattr; Ast.uf_allow_list = $3; Ast.uf_propagate_errno = $4 }
- }
- | func_def allow_list propagate_errno {
- check_ptr_attr $1 (symbol_start_pos(), symbol_end_pos());
- let fattr = get_func_attr [] in
- Ast.Untrusted { Ast.uf_fdecl = $1; Ast.uf_fattr = fattr; Ast.uf_allow_list = $2; Ast.uf_propagate_errno = $3 }
- }
- ;
- allow_list: /* nothing */ { [] }
- | Tallow TLParen TRParen { [] }
- | Tallow TLParen func_list TRParen { $3 }
- ;
- /* Enclave definition
- * ------------------------------------------------------------------------
- */
- expressions: /* nothing */ { [] }
- | expressions include_declaration { Ast.Include($2) :: $1 }
- | expressions import_declaration TSemicolon { Ast.Importing($2) :: $1 }
- | expressions composite_defs TSemicolon { Ast.Composite($2) :: $1 }
- | expressions enclave_functions { Ast.Interface($2) :: $1 }
- ;
- enclave_def: Tenclave TLBrace expressions TRBrace {
- { Ast.ename = "";
- Ast.eexpr = List.rev $3 }
- }
- ;
- /* The entry point of parser.
- * ------------------------------------------------------------------------
- */
- start_parsing: enclave_def TSemicolon EOF { $1 }
- %%
|