Parser.mly 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. /*
  2. * Copyright (C) 2011-2017 Intel Corporation. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in
  12. * the documentation and/or other materials provided with the
  13. * distribution.
  14. * * Neither the name of Intel Corporation nor the names of its
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. */
  31. %{
  32. open Util (* for failwithf *)
  33. (* Here we defined some helper routines to check attributes.
  34. *
  35. * An alternative approach is to code these rules in Lexer/Parser but
  36. * it has several drawbacks:
  37. *
  38. * 1. Bad extensibility;
  39. * 2. It grows the table size and down-graded the parsing time;
  40. * 3. It makes error reporting rigid this way.
  41. *)
  42. let get_string_from_attr (v: Ast.attr_value) (err_func: int -> string) =
  43. match v with
  44. Ast.AString s -> s
  45. | Ast.ANumber n -> err_func n
  46. (* Check whether 'size' or 'sizefunc' is specified. *)
  47. let has_size (sattr: Ast.ptr_size) =
  48. sattr.Ast.ps_size <> None || sattr.Ast.ps_sizefunc <> None
  49. (* Pointers can have the following attributes:
  50. *
  51. * 'size' - specifies the size of the pointer.
  52. * e.g. size = 4, size = val ('val' is a parameter);
  53. *
  54. * 'count' - indicates how many of items is managed by the pointer
  55. * e.g. count = 100, count = n ('n' is a parameter);
  56. *
  57. * 'sizefunc' - use a function to compute the size of the pointer.
  58. * e.g. sizefunc = get_ptr_size
  59. *
  60. * 'string' - indicate the pointer is managing a C string;
  61. * 'wstring' - indicate the pointer is managing a wide char string.
  62. *
  63. * 'isptr' - to specify that the foreign type is a pointer.
  64. * 'isary' - to specify that the foreign type is an array.
  65. * 'readonly' - to specify that the foreign type has a 'const' qualifier.
  66. *
  67. * 'user_check' - inhibit Edger8r from generating code to check the pointer.
  68. *
  69. * 'in' - the pointer is used as input
  70. * 'out' - the pointer is used as output
  71. *
  72. * Note that 'size' and 'sizefunc' are mutual exclusive (but they can
  73. * be used together with 'count'. 'string' and 'wstring' indicates 'isptr',
  74. * and they cannot use with only an 'out' attribute.
  75. *)
  76. let get_ptr_attr (attr_list: (string * Ast.attr_value) list) =
  77. let get_new_dir (cds: string) (cda: Ast.ptr_direction) (old: Ast.ptr_direction) =
  78. if old = Ast.PtrNoDirection then cda
  79. else if old = Ast.PtrInOut then failwithf "duplicated attribute: `%s'" cds
  80. else if old = cda then failwithf "duplicated attribute: `%s'" cds
  81. else Ast.PtrInOut
  82. in
  83. let update_attr (key: string) (value: Ast.attr_value) (res: Ast.ptr_attr) =
  84. match key with
  85. "size" ->
  86. { res with Ast.pa_size = { res.Ast.pa_size with Ast.ps_size = Some value }}
  87. | "count" ->
  88. { res with Ast.pa_size = { res.Ast.pa_size with Ast.ps_count = Some value }}
  89. | "sizefunc" ->
  90. let efn n = failwithf "invalid function name (%d) for `sizefunc'" n in
  91. let funcname = get_string_from_attr value efn
  92. in { res with Ast.pa_size =
  93. { res.Ast.pa_size with Ast.ps_sizefunc = Some funcname }}
  94. | "string" -> { res with Ast.pa_isptr = true; Ast.pa_isstr = true; }
  95. | "wstring" -> { res with Ast.pa_isptr = true; Ast.pa_iswstr = true; }
  96. | "isptr" -> { res with Ast.pa_isptr = true }
  97. | "isary" -> { res with Ast.pa_isary = true }
  98. | "readonly" -> { res with Ast.pa_rdonly = true }
  99. | "user_check" -> { res with Ast.pa_chkptr = false }
  100. | "in" ->
  101. let newdir = get_new_dir "in" Ast.PtrIn res.Ast.pa_direction
  102. in { res with Ast.pa_direction = newdir }
  103. | "out" ->
  104. let newdir = get_new_dir "out" Ast.PtrOut res.Ast.pa_direction
  105. in { res with Ast.pa_direction = newdir }
  106. | _ -> failwithf "unknown attribute: %s" key
  107. in
  108. let rec do_get_ptr_attr alist res_attr =
  109. match alist with
  110. [] -> res_attr
  111. | (k,v) :: xs -> do_get_ptr_attr xs (update_attr k v res_attr)
  112. in
  113. let has_str_attr (pattr: Ast.ptr_attr) =
  114. if pattr.Ast.pa_isstr && pattr.Ast.pa_iswstr
  115. then failwith "`string' and `wstring' are mutual exclusive"
  116. else (pattr.Ast.pa_isstr || pattr.Ast.pa_iswstr)
  117. in
  118. let check_invalid_ptr_size (pattr: Ast.ptr_attr) =
  119. let ps = pattr.Ast.pa_size in
  120. if ps.Ast.ps_size <> None && ps.Ast.ps_sizefunc <> None
  121. then failwith "`size' and `sizefunc' cannot be used at the same time"
  122. else
  123. if ps <> Ast.empty_ptr_size && has_str_attr pattr
  124. then failwith "size attributes are mutual exclusive with (w)string attribute"
  125. else
  126. if (ps <> Ast.empty_ptr_size || has_str_attr pattr) &&
  127. pattr.Ast.pa_direction = Ast.PtrNoDirection
  128. then failwith "size/string attributes must be used with pointer direction"
  129. else pattr
  130. in
  131. let check_ptr_dir (pattr: Ast.ptr_attr) =
  132. if pattr.Ast.pa_direction <> Ast.PtrNoDirection && pattr.Ast.pa_chkptr = false
  133. then failwith "pointer direction and `user_check' are mutual exclusive"
  134. else
  135. if pattr.Ast.pa_direction = Ast.PtrNoDirection && pattr.Ast.pa_chkptr
  136. then failwith "pointer/array should have direction attribute or `user_check'"
  137. else
  138. if pattr.Ast.pa_direction = Ast.PtrOut && (has_str_attr pattr || pattr.Ast.pa_size.Ast.ps_sizefunc <> None)
  139. then failwith "string/wstring/sizefunc should be used with an `in' attribute"
  140. else pattr
  141. in
  142. let check_invalid_ary_attr (pattr: Ast.ptr_attr) =
  143. if pattr.Ast.pa_size <> Ast.empty_ptr_size
  144. then failwith "Pointer size attributes cannot be used with foreign array"
  145. else
  146. if not pattr.Ast.pa_isptr
  147. then
  148. (* 'pa_chkptr' is default to true unless user specifies 'user_check' *)
  149. if pattr.Ast.pa_chkptr && pattr.Ast.pa_direction = Ast.PtrNoDirection
  150. then failwith "array must have direction attribute or `user_check'"
  151. else pattr
  152. else
  153. if has_str_attr pattr
  154. then failwith "`isary' cannot be used with `string/wstring' together"
  155. else failwith "`isary' cannot be used with `isptr' together"
  156. in
  157. let pattr = do_get_ptr_attr attr_list { Ast.pa_direction = Ast.PtrNoDirection;
  158. Ast.pa_size = Ast.empty_ptr_size;
  159. Ast.pa_isptr = false;
  160. Ast.pa_isary = false;
  161. Ast.pa_isstr = false;
  162. Ast.pa_iswstr = false;
  163. Ast.pa_rdonly = false;
  164. Ast.pa_chkptr = true;
  165. }
  166. in
  167. if pattr.Ast.pa_isary
  168. then check_invalid_ary_attr pattr
  169. else check_invalid_ptr_size pattr |> check_ptr_dir
  170. (* Untrusted functions can have these attributes:
  171. *
  172. * a. 3 mutual exclusive calling convention specifier:
  173. * 'stdcall', 'fastcall', 'cdecl'.
  174. *
  175. * b. 'dllimport' - to import a public symbol.
  176. *)
  177. let get_func_attr (attr_list: (string * Ast.attr_value) list) =
  178. let get_new_callconv (key: string) (cur: Ast.call_conv) (old: Ast.call_conv) =
  179. if old <> Ast.CC_NONE then
  180. failwithf "unexpected `%s', conflict with `%s'." key (Ast.get_call_conv_str old)
  181. else cur
  182. in
  183. let update_attr (key: string) (value: Ast.attr_value) (res: Ast.func_attr) =
  184. match key with
  185. | "stdcall" ->
  186. let callconv = get_new_callconv key Ast.CC_STDCALL res.Ast.fa_convention
  187. in { res with Ast.fa_convention = callconv}
  188. | "fastcall" ->
  189. let callconv = get_new_callconv key Ast.CC_FASTCALL res.Ast.fa_convention
  190. in { res with Ast.fa_convention = callconv}
  191. | "cdecl" ->
  192. let callconv = get_new_callconv key Ast.CC_CDECL res.Ast.fa_convention
  193. in { res with Ast.fa_convention = callconv}
  194. | "dllimport" ->
  195. if res.Ast.fa_dllimport then failwith "duplicated attribute: `dllimport'"
  196. else { res with Ast.fa_dllimport = true }
  197. | _ -> failwithf "invalid function attribute: %s" key
  198. in
  199. let rec do_get_func_attr alist res_attr =
  200. match alist with
  201. [] -> res_attr
  202. | (k,v) :: xs -> do_get_func_attr xs (update_attr k v res_attr)
  203. in do_get_func_attr attr_list { Ast.fa_dllimport = false;
  204. Ast.fa_convention= Ast.CC_NONE;
  205. }
  206. (* Some syntax checking against pointer attributes.
  207. * range: (Lexing.position * Lexing.position)
  208. *)
  209. let check_ptr_attr (fd: Ast.func_decl) range =
  210. let fname = fd.Ast.fname in
  211. let check_const (pattr: Ast.ptr_attr) (identifier: string) =
  212. let raise_err_direction (direction:string) =
  213. failwithf "`%s': `%s' is readonly - cannot be used with `%s'"
  214. fname identifier direction
  215. in
  216. if pattr.Ast.pa_rdonly
  217. then
  218. match pattr.Ast.pa_direction with
  219. Ast.PtrOut | Ast.PtrInOut -> raise_err_direction "out"
  220. | _ -> ()
  221. else ()
  222. in
  223. let check_void_ptr_size (pattr: Ast.ptr_attr) (identifier: string) =
  224. if pattr.Ast.pa_chkptr && (not (has_size pattr.Ast.pa_size))
  225. then failwithf "`%s': void pointer `%s' - buffer size unknown" fname identifier
  226. else ()
  227. in
  228. let checker (pd: Ast.pdecl) =
  229. let pt, declr = pd in
  230. let identifier = declr.Ast.identifier in
  231. match pt with
  232. Ast.PTVal _ -> ()
  233. | Ast.PTPtr(atype, pattr) ->
  234. if atype <> Ast.Ptr(Ast.Void) then check_const pattr identifier
  235. else (* 'void' pointer, check there is a size or 'user_check' *)
  236. check_void_ptr_size pattr identifier
  237. in
  238. List.iter checker fd.Ast.plist
  239. %}
  240. %token EOF
  241. %token TDot TComma TSemicolon TPtr TEqual
  242. %token TLParen TRParen
  243. %token TLBrace TRBrace
  244. %token TLBrack TRBrack
  245. %token Tpublic
  246. %token Tinclude
  247. %token Tconst
  248. %token <string>Tidentifier
  249. %token <int>Tnumber
  250. %token <string>Tstring
  251. %token Tchar Tshort Tunsigned Tint Tfloat Tdouble
  252. Tint8 Tint16 Tint32 Tint64
  253. Tuint8 Tuint16 Tuint32 Tuint64
  254. Tsizet Twchar Tvoid Tlong Tstruct Tunion Tenum
  255. %token Tenclave Tfrom Timport Ttrusted Tuntrusted Tallow Tpropagate_errno
  256. %start start_parsing
  257. %type <Ast.enclave> start_parsing
  258. /* Grammar follows */
  259. %%
  260. /* Type definitions
  261. * ------------------------------------------------------------------------
  262. */
  263. char_type: Tchar { Ast.Char Ast.Signed }
  264. | Tunsigned Tchar { Ast.Char Ast.Unsigned }
  265. ;
  266. /* Explicit shortness. */
  267. ex_shortness: Tshort { Ast.IShort }
  268. | Tlong { Ast.ILong }
  269. ;
  270. longlong: Tlong Tlong { Ast.LLong Ast.Signed }
  271. | Tunsigned Tlong Tlong { Ast.LLong Ast.Unsigned }
  272. shortness: /* empty */ { Ast.INone }
  273. | ex_shortness { $1 }
  274. ;
  275. int_type: shortness Tint {
  276. Ast.Int { Ast.ia_signedness = Ast.Signed; Ast.ia_shortness = $1 }
  277. }
  278. | Tunsigned shortness Tint {
  279. Ast.Int { Ast.ia_signedness = Ast.Unsigned; Ast.ia_shortness = $2 }
  280. }
  281. | Tunsigned shortness {
  282. Ast.Int { Ast.ia_signedness = Ast.Unsigned; Ast.ia_shortness = $2 }
  283. }
  284. | longlong { $1 }
  285. | ex_shortness {
  286. Ast.Int { Ast.ia_signedness = Ast.Signed; Ast.ia_shortness = $1 }
  287. }
  288. ;
  289. type_spec:
  290. char_type { $1 }
  291. | int_type { $1 }
  292. | Tfloat { Ast.Float }
  293. | Tdouble { Ast.Double }
  294. | Tlong Tdouble { Ast.LDouble }
  295. | Tint8 { Ast.Int8 }
  296. | Tint16 { Ast.Int16 }
  297. | Tint32 { Ast.Int32 }
  298. | Tint64 { Ast.Int64 }
  299. | Tuint8 { Ast.UInt8 }
  300. | Tuint16 { Ast.UInt16 }
  301. | Tuint32 { Ast.UInt32 }
  302. | Tuint64 { Ast.UInt64 }
  303. | Tsizet { Ast.SizeT }
  304. | Twchar { Ast.WChar }
  305. | Tvoid { Ast.Void }
  306. | struct_specifier { $1 }
  307. | union_specifier { $1 }
  308. | enum_specifier { $1 }
  309. | Tidentifier { Ast.Foreign($1) } /* User defined types in C header */
  310. ;
  311. pointer: TPtr { fun ii -> Ast.Ptr(ii) }
  312. | pointer TPtr { fun ii -> Ast.Ptr($1 ii) }
  313. ;
  314. empty_dimension: TLBrack TRBrack { failwith "Flexible array is not supported." }
  315. fixed_dimension: TLBrack Tnumber TRBrack { if $2 <> 0 then [$2]
  316. else failwith "Zero-length array is not supported." }
  317. fixed_size_array: fixed_dimension { $1 }
  318. | fixed_size_array fixed_dimension { $1 @ $2 }
  319. ;
  320. array_size: fixed_size_array { $1 }
  321. | empty_dimension { $1 }
  322. | empty_dimension fixed_size_array { $1 @ $2 }
  323. ;
  324. all_type: type_spec { $1 }
  325. | type_spec pointer { $2 $1 }
  326. ;
  327. declarator: Tidentifier { { Ast.identifier = $1; Ast.array_dims = []; } }
  328. | Tidentifier array_size { { Ast.identifier = $1; Ast.array_dims = $2; } }
  329. ;
  330. /* Available types as parameter.
  331. *
  332. * Instead of returning an value of 'Ast.parameter_type', we return
  333. * a lambda which wraps the actual type since so far there is no way
  334. * to tell whether the identifier is followed by array dimensions.
  335. */
  336. param_type: attr_block all_type {
  337. match $2 with
  338. Ast.Ptr _ -> fun x -> Ast.PTPtr($2, get_ptr_attr $1)
  339. | _ ->
  340. if $1 <> [] then
  341. let attr = get_ptr_attr $1 in
  342. match $2 with
  343. Ast.Foreign s ->
  344. if attr.Ast.pa_isptr || attr.Ast.pa_isary then fun x -> Ast.PTPtr($2, attr)
  345. else
  346. (* thinking about 'user_defined_type var[4]' *)
  347. fun is_ary ->
  348. if is_ary then Ast.PTPtr($2, attr)
  349. else failwithf "`%s' is considered plain type but decorated with pointer attributes" s
  350. | _ ->
  351. fun is_ary ->
  352. if is_ary then Ast.PTPtr($2, attr)
  353. else failwithf "unexpected pointer attributes for `%s'" (Ast.get_tystr $2)
  354. else
  355. fun is_ary ->
  356. if is_ary then Ast.PTPtr($2, get_ptr_attr [])
  357. else Ast.PTVal $2
  358. }
  359. | all_type {
  360. match $1 with
  361. Ast.Ptr _ -> fun x -> Ast.PTPtr($1, get_ptr_attr [])
  362. | _ ->
  363. fun is_ary ->
  364. if is_ary then Ast.PTPtr($1, get_ptr_attr [])
  365. else Ast.PTVal $1
  366. }
  367. | attr_block Tconst type_spec pointer {
  368. let attr = get_ptr_attr $1
  369. in fun x -> Ast.PTPtr($4 $3, { attr with Ast.pa_rdonly = true })
  370. }
  371. | Tconst type_spec pointer {
  372. let attr = get_ptr_attr []
  373. in fun x -> Ast.PTPtr($3 $2, { attr with Ast.pa_rdonly = true })
  374. }
  375. ;
  376. attr_block: TLBrack TRBrack { failwith "no attribute specified." }
  377. | TLBrack key_val_pairs TRBrack { $2 }
  378. ;
  379. key_val_pairs: key_val_pair { [$1] }
  380. | key_val_pairs TComma key_val_pair { $3 :: $1 }
  381. ;
  382. key_val_pair: Tidentifier TEqual Tidentifier { ($1, Ast.AString($3)) }
  383. | Tidentifier TEqual Tnumber { ($1, Ast.ANumber($3)) }
  384. | Tidentifier { ($1, Ast.AString("")) }
  385. ;
  386. struct_specifier: Tstruct Tidentifier { Ast.Struct($2) }
  387. union_specifier: Tunion Tidentifier { Ast.Union($2) }
  388. enum_specifier: Tenum Tidentifier { Ast.Enum($2) }
  389. struct_definition: struct_specifier TLBrace member_list TRBrace {
  390. let s = { Ast.sname = (match $1 with Ast.Struct s -> s | _ -> "");
  391. Ast.mlist = List.rev $3; }
  392. in Ast.StructDef(s)
  393. }
  394. union_definition: union_specifier TLBrace member_list TRBrace {
  395. let s = { Ast.sname = (match $1 with Ast.Union s -> s | _ -> "");
  396. Ast.mlist = List.rev $3; }
  397. in Ast.UnionDef(s)
  398. }
  399. /* enum can be anonymous. */
  400. enum_definition: Tenum TLBrace enum_body TRBrace {
  401. let e = { Ast.enname = ""; Ast.enbody = $3; }
  402. in Ast.EnumDef(e)
  403. }
  404. | enum_specifier TLBrace enum_body TRBrace {
  405. let e = { Ast.enname = (match $1 with Ast.Enum s -> s | _ -> "");
  406. Ast.enbody = $3; }
  407. in Ast.EnumDef(e)
  408. }
  409. ;
  410. enum_body: /* empty */ { [] }
  411. | enum_eles { List.rev $1 }
  412. ;
  413. enum_eles: enum_ele { [$1] }
  414. | enum_eles TComma enum_ele { $3 :: $1 }
  415. ;
  416. enum_ele: Tidentifier { ($1, Ast.EnumValNone) }
  417. | Tidentifier TEqual Tidentifier { ($1, Ast.EnumVal (Ast.AString $3)) }
  418. | Tidentifier TEqual Tnumber { ($1, Ast.EnumVal (Ast.ANumber $3)) }
  419. ;
  420. composite_defs: struct_definition { $1 }
  421. | union_definition { $1 }
  422. | enum_definition { $1 }
  423. ;
  424. member_list: member_def TSemicolon { [$1] }
  425. | member_list member_def TSemicolon { $2 :: $1 }
  426. ;
  427. member_def: all_type declarator { ($1, $2) }
  428. /* Importing declarations.
  429. * ------------------------------------------------------------------------
  430. */
  431. func_list: Tidentifier { [$1] }
  432. | func_list TComma Tidentifier { $3 :: $1 }
  433. ;
  434. module_path: Tstring { $1 }
  435. import_declaration: Tfrom module_path Timport func_list {
  436. { Ast.mname = $2; Ast.flist = List.rev $4; }
  437. }
  438. | Tfrom module_path Timport TPtr {
  439. { Ast.mname = $2; Ast.flist = ["*"]; }
  440. }
  441. ;
  442. include_declaration: Tinclude Tstring { $2 }
  443. include_declarations: include_declaration { [$1] }
  444. | include_declarations include_declaration { $2 :: $1 }
  445. ;
  446. /* Enclave function declarations.
  447. * ------------------------------------------------------------------------
  448. */
  449. enclave_functions: Ttrusted TLBrace trusted_block TRBrace TSemicolon {
  450. List.rev $3
  451. }
  452. | Tuntrusted TLBrace untrusted_block TRBrace TSemicolon {
  453. List.rev $3
  454. }
  455. ;
  456. trusted_block: trusted_functions { $1 }
  457. | include_declarations trusted_functions {
  458. trusted_headers := !trusted_headers @ List.rev $1; $2
  459. }
  460. ;
  461. untrusted_block: untrusted_functions { $1 }
  462. | include_declarations untrusted_functions {
  463. untrusted_headers := !untrusted_headers @ List.rev $1; $2
  464. }
  465. ;
  466. /* is_priv? Default to true. */
  467. access_modifier: /* nothing */ { true }
  468. | Tpublic { false }
  469. ;
  470. trusted_functions: /* nothing */ { [] }
  471. | trusted_functions access_modifier func_def TSemicolon {
  472. check_ptr_attr $3 (symbol_start_pos(), symbol_end_pos());
  473. Ast.Trusted { Ast.tf_fdecl = $3; Ast.tf_is_priv = $2 } :: $1
  474. }
  475. ;
  476. untrusted_functions: /* nothing */ { [] }
  477. | untrusted_functions untrusted_func_def TSemicolon { $2 :: $1 }
  478. ;
  479. func_def: all_type Tidentifier parameter_list {
  480. { Ast.fname = $2; Ast.rtype = $1; Ast.plist = List.rev $3 ; }
  481. }
  482. | all_type array_size Tidentifier parameter_list {
  483. failwithf "%s: returning an array is not supported - use pointer instead." $3
  484. }
  485. ;
  486. parameter_list: TLParen TRParen { [] }
  487. | TLParen Tvoid TRParen { [] } /* Make C programers comfortable */
  488. | TLParen parameter_defs TRParen { $2 }
  489. ;
  490. parameter_defs: parameter_def { [$1] }
  491. | parameter_defs TComma parameter_def { $3 :: $1 }
  492. ;
  493. parameter_def: param_type declarator {
  494. let pt = $1 (Ast.is_array $2) in
  495. let is_void =
  496. match pt with
  497. Ast.PTVal v -> v = Ast.Void
  498. | _ -> false
  499. in
  500. if is_void then
  501. failwithf "parameter `%s' has `void' type." $2.Ast.identifier
  502. else
  503. (pt, $2)
  504. }
  505. /* propagate_errno? Default to false. */
  506. propagate_errno: /* nothing */ { false }
  507. | Tpropagate_errno { true }
  508. ;
  509. untrusted_func_def: attr_block func_def allow_list propagate_errno {
  510. check_ptr_attr $2 (symbol_start_pos(), symbol_end_pos());
  511. let fattr = get_func_attr $1 in
  512. Ast.Untrusted { Ast.uf_fdecl = $2; Ast.uf_fattr = fattr; Ast.uf_allow_list = $3; Ast.uf_propagate_errno = $4 }
  513. }
  514. | func_def allow_list propagate_errno {
  515. check_ptr_attr $1 (symbol_start_pos(), symbol_end_pos());
  516. let fattr = get_func_attr [] in
  517. Ast.Untrusted { Ast.uf_fdecl = $1; Ast.uf_fattr = fattr; Ast.uf_allow_list = $2; Ast.uf_propagate_errno = $3 }
  518. }
  519. ;
  520. allow_list: /* nothing */ { [] }
  521. | Tallow TLParen TRParen { [] }
  522. | Tallow TLParen func_list TRParen { $3 }
  523. ;
  524. /* Enclave definition
  525. * ------------------------------------------------------------------------
  526. */
  527. expressions: /* nothing */ { [] }
  528. | expressions include_declaration { Ast.Include($2) :: $1 }
  529. | expressions import_declaration TSemicolon { Ast.Importing($2) :: $1 }
  530. | expressions composite_defs TSemicolon { Ast.Composite($2) :: $1 }
  531. | expressions enclave_functions { Ast.Interface($2) :: $1 }
  532. ;
  533. enclave_def: Tenclave TLBrace expressions TRBrace {
  534. { Ast.ename = "";
  535. Ast.eexpr = List.rev $3 }
  536. }
  537. ;
  538. /* The entry point of parser.
  539. * ------------------------------------------------------------------------
  540. */
  541. start_parsing: enclave_def TSemicolon EOF { $1 }
  542. %%