2 * Copyright 2010, INRIA, University of Copenhagen
3 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
4 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
5 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
6 * This file is part of Coccinelle.
8 * Coccinelle is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, according to version 2 of the License.
12 * Coccinelle is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
20 * The authors reserve the right to distribute this or future versions of
21 * Coccinelle under other licenses.
26 * Copyright 2010, INRIA, University of Copenhagen
27 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
28 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
29 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
30 * This file is part of Coccinelle.
32 * Coccinelle is free software: you can redistribute it and/or modify
33 * it under the terms of the GNU General Public License as published by
34 * the Free Software Foundation, according to version 2 of the License.
36 * Coccinelle is distributed in the hope that it will be useful,
37 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39 * GNU General Public License for more details.
41 * You should have received a copy of the GNU General Public License
42 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
44 * The authors reserve the right to distribute this or future versions of
45 * Coccinelle under other licenses.
51 (* Not clear how to allow function declarations to specify a return type
52 and how to allow both to be specified as static, because they are in
53 different rules. The rules seem to have to be combined, which would allow
54 functions to be declared as local variables *)
56 (* Not clear how to let a function have a parameter of type void. At the
57 moment, void is allowed to be the type of a variable, which is wrong, and a
58 parameter needs both a type and an identifier *)
59 module Ast0 = Ast0_cocci
60 module Ast = Ast_cocci
66 %token TIdentifier TExpression TStatement TFunction TLocal TType TParameter
67 %token TIdExpression TInitialiser TDeclaration TField
68 %token Tlist TFresh TConstant TError TWords TWhy0 TPlus0 TBang0
69 %token TPure TContext TGenerated
70 %token TTypedef TDeclarer TIterator TName TPosition TPosAny
71 %token TUsing TDisable TExtends TDepends TOn TEver TNever TExists TForall
72 %token TScript TInitialize TFinalize TNothing TVirtual
73 %token<string> TRuleName
75 %token<Data.clt> Tchar Tshort Tint Tdouble Tfloat Tlong
76 %token<Data.clt> Tsize_t Tssize_t Tptrdiff_t
77 %token<Data.clt> Tvoid Tstruct Tunion Tenum
78 %token<Data.clt> Tunsigned Tsigned
80 %token<Data.clt> Tstatic Tauto Tregister Textern Tinline Ttypedef
81 %token<Data.clt> Tconst Tvolatile
82 %token<string * Data.clt> Tattr
84 %token <Data.clt> TIf TElse TWhile TFor TDo TSwitch TCase TDefault TReturn
85 %token <Data.clt> TBreak TContinue TGoto TSizeof TFunDecl
86 %token <string * Data.clt> TIdent TTypeId TDeclarerId TIteratorId
87 %token <Ast_cocci.added_string * Data.clt> TPragma
89 %token <Parse_aux.idinfo> TMetaId TMetaFunc TMetaLocalFunc
90 %token <Parse_aux.idinfo> TMetaIterator TMetaDeclarer
91 %token <Parse_aux.expinfo> TMetaErr
92 %token <Parse_aux.info> TMetaParam TMetaStm TMetaStmList TMetaType
93 %token <Parse_aux.info> TMetaInit TMetaDecl TMetaField
94 %token <Parse_aux.list_info> TMetaParamList TMetaExpList
95 %token <Parse_aux.typed_expinfo> TMetaExp TMetaIdExp TMetaLocalIdExp TMetaConst
96 %token <Parse_aux.pos_info> TMetaPos
98 %token TArob TArobArob TPArob
99 %token <string> TScriptData
101 %token <Data.clt> TEllipsis TOEllipsis TCEllipsis TPOEllipsis TPCEllipsis
102 %token <Data.clt> TWhen TWhenTrue TWhenFalse TAny TStrict TLineEnd
104 %token <Data.clt> TWhy TDotDot TBang TOPar TOPar0
105 %token <Data.clt> TMid0 TCPar TCPar0
107 %token <string> TPathIsoFile
108 %token <string * Data.clt> TIncludeL TIncludeNL
109 %token <Data.clt * token> TDefine
110 %token <Data.clt * token * int * int> TDefineParam
111 %token <string * Data.clt> TMinusFile TPlusFile
113 %token <Data.clt> TInc TDec
115 %token <string * Data.clt> TString TChar TFloat TInt
117 %token <Data.clt> TOrLog
118 %token <Data.clt> TAndLog
119 %token <Data.clt> TOr
120 %token <Data.clt> TXor
121 %token <Data.clt> TAnd
122 %token <Data.clt> TEqEq TNotEq TTildeEq TTildeExclEq TSub
123 %token <Ast_cocci.logicalOp * Data.clt> TLogOp /* TInf TSup TInfEq TSupEq */
124 %token <Ast_cocci.arithOp * Data.clt> TShLOp TShROp /* TShl TShr */
125 %token <Ast_cocci.arithOp * Data.clt> TDmOp /* TDiv TMod */
126 %token <Data.clt> TPlus TMinus
127 %token <Data.clt> TMul TTilde
129 %token <Data.clt> TOBrace TCBrace TOInit
130 %token <Data.clt> TOCro TCCro
132 %token <Data.clt> TPtrOp
134 %token TMPtVirg TCppConcatOp
135 %token <Data.clt> TEq TDot TComma TPtVirg
136 %token <Ast_cocci.assignOp * Data.clt> TAssign
138 %token TIso TRightIso TIsoExpression TIsoStatement TIsoDeclaration TIsoType
139 %token TIsoTopLevel TIsoArgExpression TIsoTestExpression TIsoToTestExpression
145 /* operator precedence */
155 %left TLogOp /* TInf TSup TInfEq TSupEq */
156 %left TShLOp TShROp /* TShl TShr */
158 %left TMul TDmOp /* TDiv TMod */
164 %type <Ast0_cocci.rule> minus_main
166 %start minus_exp_main
167 %type <Ast0_cocci.rule> minus_exp_main
170 %type <Ast0_cocci.rule> plus_main
173 %type <Ast0_cocci.rule> plus_exp_main
176 %type <Data.incl_iso list> include_main
179 %type <Ast_cocci.rulename>
183 %type <Ast_cocci.rulename>
187 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> meta_main
189 %start <(string option (*string*) * string option (*ast*)) * (Ast_cocci.meta_name * Ast_cocci.metavar) option> script_meta_main
192 %type <Ast0_cocci.anything list list> iso_main
195 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> iso_meta_main
198 %type <unit> never_used
203 minus_main: minus_body EOF { $1 } | m=minus_body TArobArob { m }
204 | m=minus_body TArob { m }
205 plus_main: plus_body EOF { $1 } | p=plus_body TArobArob { p }
206 | p=plus_body TArob { p }
207 minus_exp_main: minus_exp_body EOF { $1 } | m=minus_exp_body TArobArob { m }
208 | m=minus_exp_body TArob { m }
209 plus_exp_main: plus_exp_body EOF { $1 } | p=plus_exp_body TArobArob { p }
210 | p=plus_exp_body TArob { p }
211 meta_main: m=metadec { m (!Ast0.rule_name) }
212 iso_meta_main: m=metadec { m "" }
214 /*****************************************************************************
217 *****************************************************************************/
221 | TContext { Ast0.Context }
222 | TPure TContext { Ast0.PureContext }
223 | TContext TPure { Ast0.PureContext }
224 | /* empty */ { Ast0.Impure }
227 nm=pure_ident TArob { P.make_iso_rule_name_result (P.id2name nm) }
230 nm=ioption(pure_ident) extends d=depends i=loption(choose_iso)
231 a=loption(disable) e=exists ee=is_expression TArob
232 { P.make_cocci_rule_name_result nm d i a e ee }
233 | TGenerated extends d=depends i=loption(choose_iso)
234 a=loption(disable) e=exists ee=is_expression TArob
235 /* these rules have no name as a cheap way to ensure that no normal
236 rule inherits their metavariables or depends on them */
237 { P.make_generated_rule_name_result None d i a e ee }
238 | TScript TDotDot lang=pure_ident nm=ioption(pure_ident) d=depends TArob
239 { P.make_script_rule_name_result lang nm d }
240 | TInitialize TDotDot lang=pure_ident d=depends TArob
241 { P.make_initial_script_rule_name_result lang d }
242 | TFinalize TDotDot lang=pure_ident d=depends TArob
243 { P.make_final_script_rule_name_result lang d }
247 | TExtends parent=TRuleName
248 { !Data.install_bindings (parent) }
251 /* empty */ { Ast.NoDep }
252 | TDepends TOn parents=dep { parents }
256 | dep TAndLog dep { Ast.AndDep($1, $3) }
257 | dep TOrLog dep { Ast.OrDep ($1, $3) }
260 TRuleName { Ast.Dep $1 }
261 | TBang TRuleName { Ast.AntiDep $2 }
262 | TEver TRuleName { Ast.EverDep $2 }
263 | TNever TRuleName { Ast.NeverDep $2 }
264 | TOPar dep TCPar { $2 }
267 TUsing separated_nonempty_list(TComma,TString) { List.map P.id2name $2 }
270 TDisable separated_nonempty_list(TComma,pure_ident) { List.map P.id2name $2 }
273 TExists { Ast.Exists }
274 | TForall { Ast.Forall }
275 | { Ast.Undetermined }
277 is_expression: // for more flexible parsing of top level expressions
279 | TExpression { true }
282 list(incl) TArob { $1 }
283 | list(incl) TArobArob { $1 }
286 TIncludeL { let (x,_) = $1 in Data.Include(x) }
287 | TUsing TString { Data.Iso(Common.Left(P.id2name $2)) }
288 | TUsing TPathIsoFile { Data.Iso(Common.Right $2) }
289 | TVirtual comma_list(pure_ident)
290 { let names = List.map P.id2name $2 in
291 (* ensure that the names of virtual and real rules don't overlap *)
293 (function name -> Hashtbl.add Data.all_metadecls name [])
299 kindfn=metakind ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
300 { P.create_metadec ar ispure kindfn ids }
301 | kindfn=metakind_fresh ids=comma_list(pure_ident_or_meta_ident_with_seed)
303 { P.create_fresh_metadec kindfn ids }
304 | ar=arity ispure=pure
305 kindfn=metakind_atomic_maybe_virt
307 comma_list(pure_ident_or_meta_ident_with_idconstraint_virt(re_or_not_eqid))
309 { let (normal,virt) = Common.partition_either (fun x -> x) ids in
310 let (idfn,virtfn) = kindfn in
312 (P.create_metadec_with_constraints ar ispure idfn normal cr) @
313 (P.create_metadec_virt ar ispure virtfn virt cr) }
314 | ar=arity ispure=pure
315 kindfn=metakind_atomic
316 ids=comma_list(pure_ident_or_meta_ident_with_idconstraint(re_or_not_eqid))
318 { P.create_metadec_with_constraints ar ispure kindfn ids }
319 | ar=arity ispure=pure
320 kindfn=metakind_atomic_expi
321 ids=comma_list(pure_ident_or_meta_ident_with_econstraint(re_or_not_eqe_or_sub))
323 { P.create_metadec_with_constraints ar ispure kindfn ids }
324 | ar=arity ispure=pure
325 kindfn=metakind_atomic_expe
326 ids=comma_list(pure_ident_or_meta_ident_with_econstraint(not_ceq_or_sub))
328 { P.create_metadec_with_constraints ar ispure kindfn ids }
329 | ar=arity TPosition a=option(TPosAny)
330 ids=comma_list(pure_ident_or_meta_ident_with_x_eq(not_pos)) TMPtVirg
331 (* pb: position variables can't be inherited from normal rules, and then
332 there is no way to inherit from a generated rule, so there is no point
333 to have a position variable *)
334 { (if !Data.in_generating
335 then failwith "position variables not allowed in a generated rule file");
336 let kindfn arity name pure check_meta constraints =
337 let tok = check_meta(Ast.MetaPosDecl(arity,name)) in
338 let any = match a with None -> Ast.PER | Some _ -> Ast.ALL in
339 !Data.add_pos_meta name constraints any; tok in
340 P.create_metadec_with_constraints ar false kindfn ids }
341 | ar=arity ispure=pure
342 TParameter Tlist TOCro len=list_len TCCro
343 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
344 { P.create_len_metadec ar ispure
345 (fun lenname arity name pure check_meta ->
346 let tok = check_meta(Ast.MetaParamListDecl(arity,name,lenname)) in
347 !Data.add_paramlist_meta name lenname pure; tok)
349 | ar=arity ispure=pure
350 TExpression Tlist TOCro len=list_len TCCro
351 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
352 { P.create_len_metadec ar ispure
353 (fun lenname arity name pure check_meta ->
354 let tok = check_meta(Ast.MetaExpListDecl(arity,name,lenname)) in
355 !Data.add_explist_meta name lenname pure; tok)
359 pure_ident_or_meta_ident { Common.Left $1 }
360 | TInt { let (x,clt) = $1 in Common.Right (int_of_string x) }
362 %inline metakind_fresh:
364 { (fun name check_meta seed ->
365 let tok = check_meta(Ast.MetaFreshIdDecl(name,seed)) in
366 !Data.add_fresh_id_meta name; tok) }
368 /* metavariable kinds with no constraints, etc */
371 { (fun arity name pure check_meta ->
372 let tok = check_meta(Ast.MetaParamDecl(arity,name)) in
373 !Data.add_param_meta name pure; tok) }
375 { (fun arity name pure check_meta ->
376 let len = Ast.AnyLen in
377 let tok = check_meta(Ast.MetaParamListDecl(arity,name,len)) in
378 !Data.add_paramlist_meta name len pure; tok) }
380 { (fun arity name pure check_meta ->
381 let len = Ast.AnyLen in
382 let tok = check_meta(Ast.MetaExpListDecl(arity,name,len)) in
383 !Data.add_explist_meta name len pure; tok) }
385 { (fun arity name pure check_meta ->
386 let tok = check_meta(Ast.MetaTypeDecl(arity,name)) in
387 !Data.add_type_meta name pure; tok) }
389 { (fun arity name pure check_meta ->
390 let tok = check_meta(Ast.MetaInitDecl(arity,name)) in
391 !Data.add_init_meta name pure; tok) }
393 { (fun arity name pure check_meta ->
394 let tok = check_meta(Ast.MetaStmDecl(arity,name)) in
395 !Data.add_stm_meta name pure; tok) }
397 { (fun arity name pure check_meta ->
398 let tok = check_meta(Ast.MetaDeclDecl(arity,name)) in
399 !Data.add_decl_meta name pure; tok) }
401 { (fun arity name pure check_meta ->
402 let tok = check_meta(Ast.MetaFieldDecl(arity,name)) in
403 !Data.add_field_meta name pure; tok) }
405 { (fun arity name pure check_meta ->
406 let tok = check_meta(Ast.MetaStmListDecl(arity,name)) in
407 !Data.add_stmlist_meta name pure; tok) }
409 { (fun arity (_,name) pure check_meta ->
410 if arity = Ast.NONE && pure = Ast0.Impure
411 then (!Data.add_type_name name; [])
412 else raise (Semantic_cocci.Semantic "bad typedef")) }
414 { (fun arity (_,name) pure check_meta ->
415 if arity = Ast.NONE && pure = Ast0.Impure
416 then (!Data.add_declarer_name name; [])
417 else raise (Semantic_cocci.Semantic "bad declarer")) }
419 { (fun arity (_,name) pure check_meta ->
420 if arity = Ast.NONE && pure = Ast0.Impure
421 then (!Data.add_iterator_name name; [])
422 else raise (Semantic_cocci.Semantic "bad iterator")) }
424 %inline metakind_atomic_maybe_virt:
427 let idfn arity name pure check_meta constraints =
428 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
429 !Data.add_id_meta name constraints pure; tok in
430 let virtfn arity name pure check_meta virtual_env =
432 let vl = List.assoc name virtual_env in
433 !Data.add_virt_id_meta_found name vl; []
435 let name = ("virtual",name) in
436 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
437 !Data.add_virt_id_meta_not_found name pure; tok in
440 %inline metakind_atomic:
442 { (fun arity name pure check_meta constraints ->
443 let tok = check_meta(Ast.MetaFuncDecl(arity,name)) in
444 !Data.add_func_meta name constraints pure; tok) }
446 { (fun arity name pure check_meta constraints ->
447 let tok = check_meta(Ast.MetaLocalFuncDecl(arity,name)) in
448 !Data.add_local_func_meta name constraints pure;
451 { (fun arity name pure check_meta constraints ->
452 let tok = check_meta(Ast.MetaDeclarerDecl(arity,name)) in
453 !Data.add_declarer_meta name constraints pure; tok) }
455 { (fun arity name pure check_meta constraints ->
456 let tok = check_meta(Ast.MetaIteratorDecl(arity,name)) in
457 !Data.add_iterator_meta name constraints pure; tok) }
459 %inline metakind_atomic_expi:
461 { (fun arity name pure check_meta constraints ->
462 let tok = check_meta(Ast.MetaErrDecl(arity,name)) in
463 !Data.add_err_meta name constraints pure; tok) }
464 | l=option(TLocal) TIdExpression ty=ioption(meta_exp_type)
465 { (fun arity name pure check_meta constraints ->
468 !Data.add_idexp_meta ty name constraints pure;
469 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
471 !Data.add_local_idexp_meta ty name constraints pure;
472 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
473 | l=option(TLocal) TIdExpression m=nonempty_list(TMul)
474 { (fun arity name pure check_meta constraints ->
475 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
478 !Data.add_idexp_meta ty name constraints pure;
479 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
481 !Data.add_local_idexp_meta ty name constraints pure;
482 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
483 | TExpression ty=expression_type
484 { (fun arity name pure check_meta constraints ->
485 let ty = Some [ty] in
486 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
487 !Data.add_exp_meta ty name constraints pure; tok) }
488 | TConstant ty=ioption(meta_exp_type)
489 { (fun arity name pure check_meta constraints ->
490 let tok = check_meta(Ast.MetaConstDecl(arity,name,ty)) in
491 !Data.add_const_meta ty name constraints pure; tok) }
494 m=nonempty_list(TMul) { P.ty_pointerify Type_cocci.Unknown m }
496 { P.ty_pointerify (Type_cocci.EnumName Type_cocci.NoName) m }
497 | Tstruct m=list(TMul)
499 (Type_cocci.StructUnionName (Type_cocci.Struct,Type_cocci.NoName)) m }
500 | Tunion m=list(TMul)
502 (Type_cocci.StructUnionName (Type_cocci.Union,Type_cocci.NoName)) m }
504 %inline metakind_atomic_expe:
506 { (fun arity name pure check_meta constraints ->
507 let tok = check_meta(Ast.MetaExpDecl(arity,name,None)) in
508 !Data.add_exp_meta None name constraints pure; tok) }
509 | vl=meta_exp_type // no error if use $1 but doesn't type check
510 { (fun arity name pure check_meta constraints ->
512 (match constraints with
513 Ast0.NotExpCstrt constraints ->
516 match Ast0.unwrap c with
521 Type_cocci.BaseType(Type_cocci.IntType) -> true
522 | Type_cocci.BaseType(Type_cocci.ShortType) -> true
523 | Type_cocci.BaseType(Type_cocci.LongType) -> true
527 failwith "metavariable with int constraint must be an int"
531 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
532 !Data.add_exp_meta ty name constraints pure; tok)
537 { [Ast0_cocci.ast0_type_to_type t] }
538 | t=typedef_ctype TOCro TCCro
539 { [Type_cocci.Array (Ast0_cocci.ast0_type_to_type t)] }
540 | TOBrace t=comma_list(ctype) TCBrace m=list(TMul)
542 (function x -> P.ty_pointerify (Ast0_cocci.ast0_type_to_type x) m)
545 arity: TBang0 { Ast.UNIQUE }
547 | TPlus0 { Ast.MULTI }
548 | /* empty */ { Ast.NONE }
550 /* ---------------------------------------------------------------------- */
555 { Ast0.wrap(Ast0.BaseType(Ast.CharType,[P.clt2mcode "char" ty])) }
557 { Ast0.wrap(Ast0.BaseType(Ast.ShortType,[P.clt2mcode "short" ty])) }
559 { Ast0.wrap(Ast0.BaseType(Ast.IntType,[P.clt2mcode "int" ty])) }
561 { let (nm,pure,clt) = p in
562 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
563 | r=TRuleName TDot p=TIdent
564 { let nm = (r,P.id2name p) in
565 (* this is only possible when we are in a metavar decl. Otherwise,
566 it will be represented already as a MetaType *)
567 let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in
568 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p),
569 Ast0.Impure (*will be ignored*))) }
571 { Ast0.wrap(Ast0.BaseType(Ast.LongType,[P.clt2mcode "long" ty])) }
572 | ty1=Tlong ty2=Tlong
576 [P.clt2mcode "long" ty1;P.clt2mcode "long" ty2])) }
581 { Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" ty])) }
583 { Ast0.wrap(Ast0.BaseType(Ast.DoubleType,[P.clt2mcode "double" ty])) }
585 { Ast0.wrap(Ast0.BaseType(Ast.FloatType,[P.clt2mcode "float" ty])) }
587 { Ast0.wrap(Ast0.BaseType(Ast.SizeType,[P.clt2mcode "size_t" ty])) }
589 { Ast0.wrap(Ast0.BaseType(Ast.SSizeType,[P.clt2mcode "ssize_t" ty])) }
591 { Ast0.wrap(Ast0.BaseType(Ast.PtrDiffType,[P.clt2mcode "ptrdiff_t" ty])) }
593 { Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, Some i)) }
594 | s=Tenum i=ioption(ident) l=TOBrace ids=enum_decl_list r=TCBrace
595 { (if i = None && !Data.in_iso
596 then failwith "enums must be named in the iso file");
597 Ast0.wrap(Ast0.EnumDef(Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, i)),
598 P.clt2mcode "{" l, ids, P.clt2mcode "}" r)) }
599 | s=struct_or_union i=ident
600 { Ast0.wrap(Ast0.StructUnionName(s, Some i)) }
601 | s=struct_or_union i=ioption(ident)
602 l=TOBrace d=struct_decl_list r=TCBrace
603 { (if i = None && !Data.in_iso
604 then failwith "structures must be named in the iso file");
605 Ast0.wrap(Ast0.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)),
607 d, P.clt2mcode "}" r)) }
608 | s=TMetaType l=TOBrace d=struct_decl_list r=TCBrace
609 { let (nm,pure,clt) = s in
610 let ty = Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) in
611 Ast0.wrap(Ast0.StructUnionDef(ty,P.clt2mcode "{" l,d,P.clt2mcode "}" r)) }
613 { Ast0.wrap(Ast0.TypeName(P.id2mcode p)) }
617 r=Tsigned ty=signable_types
618 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,Some ty)) }
619 | r=Tunsigned ty=signable_types
620 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,Some ty)) }
621 | ty=signable_types { ty }
622 | ty=non_signable_types { ty }
625 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
626 { P.pointerify (P.make_cv cv ty) m }
628 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,None)) }
630 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,None)) }
631 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
632 { let (mids,code) = t in
634 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
636 /* signed, unsigned alone not allowed */
638 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
639 { P.pointerify (P.make_cv cv ty) m }
640 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
641 { let (mids,code) = t in
643 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
645 /* ---------------------------------------------------------------------- */
648 s=Tstruct { P.clt2mcode Ast.Struct s }
649 | u=Tunion { P.clt2mcode Ast.Union u }
653 | struct_decl_one { [$1] }
656 | TMetaField { P.meta_field $1 }
657 | t=ctype d=d_ident pv=TPtVirg
659 Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv)) }
660 | t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
661 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar pv=TPtVirg
665 (Ast0.FunctionPointer
666 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
667 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
668 Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv)) }
669 | cv=ioption(const_vol) i=pure_ident d=d_ident pv=TPtVirg
671 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
672 Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv)) }
675 struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) }
677 struct_decl_list_start:
679 | struct_decl struct_decl_list_start { $1@$2 }
680 | d=edots_when(TEllipsis,struct_decl_one) r=continue_struct_decl_list
681 { (P.mkddots_one "..." d)::r }
683 continue_struct_decl_list:
685 | struct_decl struct_decl_list_start { $1@$2 }
689 /* ---------------------------------------------------------------------- */
690 /* very restricted what kinds of expressions can appear in an enum decl */
693 | ident { Ast0.wrap(Ast0.Ident($1)) }
695 { let id = Ast0.wrap(Ast0.Ident($1)) in
698 (id,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,
702 ident { Ast0.wrap(Ast0.Ident($1)) }
704 { let (x,clt) = $1 in
705 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
707 { let (nm,constraints,pure,ty,clt) = $1 in
709 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
711 { let (nm,constraints,pure,ty,clt) = $1 in
713 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
715 { let (nm,constraints,pure,ty,clt) = $1 in
717 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
720 nonempty_list_start(enum_decl_one,edots_when(TEllipsis,enum_decl_one))
721 { Ast0.wrap(Ast0.DOTS($1 P.mkedots (fun c -> Ast0.EComma c))) }
723 /*****************************************************************************/
725 /* have to inline everything to avoid conflicts? switch to proper
726 declarations, statements, and expressions for the subterms */
730 b=loption(minus_start)
731 /*ew=loption(error_words)*/
732 { match f@b(*@ew*) with
733 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
734 | code -> Top_level.top_level code }
738 b=loption(plus_start)
739 /*ew=loption(error_words)*/
740 { Top_level.top_level (f@b(*@ew*)) }
745 /*ew=loption(error_words)*/
746 { match f@[b](*@ew*) with
747 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
748 | code -> Top_level.top_level code }
753 /*ew=loption(error_words)*/
754 { Top_level.top_level (f@[b](*@ew*)) }
759 (Ast0.FILEINFO(P.id2mcode $1,
765 (Ast0.Include(P.clt2mcode "#include"
766 (P.drop_pos (P.drop_aft (P.id2clt $1))),
767 let (arity,ln,lln,offset,col,strbef,straft,pos) =
770 (arity,ln,lln,offset,0,strbef,straft,pos) in
772 (Ast.Local (Parse_aux.str2inc (P.id2name $1)))
776 (Ast0.Include(P.clt2mcode "#include"
777 (P.drop_pos (P.drop_aft (P.id2clt $1))),
778 let (arity,ln,lln,offset,col,strbef,straft,pos) =
781 (arity,ln,lln,offset,0,strbef,straft,pos) in
783 (Ast.NonLocal (Parse_aux.str2inc (P.id2name $1)))
785 | d=defineop TLineEnd
786 { d (Ast0.wrap(Ast0.DOTS([]))) }
787 | d=defineop t=ctype TLineEnd
788 { let ty = Ast0.wrap(Ast0.TopExp(Ast0.wrap(Ast0.TypeExp(t)))) in
789 d (Ast0.wrap(Ast0.DOTS([ty]))) }
790 | defineop b=toplevel_seq_start(toplevel_after_dots) TLineEnd
794 (match Ast0.unwrap e with
796 [Ast0.rewrap e (Ast0.TopExp(Ast0.set_arg_exp (e1)))]
799 $1 (Ast0.wrap(Ast0.DOTS(body))) }
803 { let (clt,ident) = $1 in
807 (P.clt2mcode "#define" clt,
809 TMetaId((nm,constraints,pure,clt)) ->
810 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
812 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
815 (Semantic_cocci.Semantic
816 "unexpected name for a #define")),
817 Ast0.wrap Ast0.NoParams,
819 | TDefineParam define_param_list_option TCPar
820 { let (clt,ident,parenoff,parencol) = $1 in
821 (* clt is the start of the #define itself *)
822 let (arity,line,lline,offset,col,strbef,straft,pos) = clt in
825 (arity,line,lline,parenoff,parencol,[],[],Ast0.NoMetaPos) in
829 (P.clt2mcode "#define" clt,
831 TMetaId((nm,constraints,pure,clt)) ->
832 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
834 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
837 (Semantic_cocci.Semantic
838 "unexpected name for a #define")),
839 Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" $3)),body)) }
841 /* ---------------------------------------------------------------------- */
843 dparam: ident { Ast0.wrap(Ast0.DParam $1) }
845 define_param_list_option:
846 empty_list_start(dparam,TEllipsis)
850 (fun _ d -> Ast0.wrap(Ast0.DPdots(P.clt2mcode "," d)))
851 (fun c -> Ast0.DPComma c))) }
853 /*****************************************************************************/
856 s=ioption(storage) t=ctype
857 id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
862 (Ast0.FunctionType(Some t,
863 P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
864 id, P.clt2mcode ";" pt)) }
868 TFunDecl i=func_ident lp=TOPar d=decl_list(decl) rp=TCPar
869 lb=TOBrace b=fun_start rb=TCBrace
870 { P.verify_parameter_declarations (Ast0.undots d);
871 Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()),
873 P.clt2mcode "(" lp, d,
875 P.clt2mcode "{" lb, b,
876 P.clt2mcode "}" rb)) }
883 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
884 raise (Semantic_cocci.Semantic "duplicate storage")
885 with Not_found -> (Ast0.FStorage($1))::$2 }
886 | t=ctype r=fninfo_nt { (Ast0.FType(t))::r }
889 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
890 raise (Semantic_cocci.Semantic "duplicate inline")
891 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
894 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
895 raise (Semantic_cocci.Semantic "multiple attributes")
896 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
903 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
904 raise (Semantic_cocci.Semantic "duplicate storage")
905 with Not_found -> (Ast0.FStorage($1))::$2 }
908 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
909 raise (Semantic_cocci.Semantic "duplicate inline")
910 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
913 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
914 raise (Semantic_cocci.Semantic "duplicate init")
915 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
918 s=Tstatic { P.clt2mcode Ast.Static s }
919 | s=Tauto { P.clt2mcode Ast.Auto s }
920 | s=Tregister { P.clt2mcode Ast.Register s }
921 | s=Textern { P.clt2mcode Ast.Extern s }
923 decl: t=ctype i=ident
924 { Ast0.wrap(Ast0.Param(t, Some i)) }
925 | t=ctype { (*verify in FunDecl*) Ast0.wrap(Ast0.Param(t, None)) }
926 | t=ctype lp=TOPar s=TMul i=ident rp=TCPar
927 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
930 (Ast0.FunctionPointer
931 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
932 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
933 Ast0.wrap(Ast0.Param(fnptr, Some i)) }
935 { let (nm,pure,clt) = $1 in
936 Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
940 | t=ctype lp=TOPar s=TMul rp=TCPar
941 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
944 (Ast0.FunctionPointer
945 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
946 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
947 Ast0.wrap(Ast0.Param(fnptr, None)) }
950 Tconst { P.clt2mcode Ast.Const $1 }
951 | Tvolatile { P.clt2mcode Ast.Volatile $1 }
953 /*****************************************************************************/
956 includes { $1 } /* shouldn't be allowed to be a single_statement... */
961 | TIf TOPar eexpr TCPar single_statement %prec TIf
962 { P.ifthen $1 $2 $3 $4 $5 }
963 | TIf TOPar eexpr TCPar single_statement TElse single_statement
964 { P.ifthenelse $1 $2 $3 $4 $5 $6 $7 }
965 | TFor TOPar option(eexpr) TPtVirg option(eexpr) TPtVirg
966 option(eexpr) TCPar single_statement
967 { P.forloop $1 $2 $3 $4 $5 $6 $7 $8 $9 }
968 | TWhile TOPar eexpr TCPar single_statement
969 { P.whileloop $1 $2 $3 $4 $5 }
970 | TDo single_statement TWhile TOPar eexpr TCPar TPtVirg
971 { P.doloop $1 $2 $3 $4 $5 $6 $7 }
972 | iter_ident TOPar eexpr_list_option TCPar single_statement
973 { P.iterator $1 $2 $3 $4 $5 }
974 | TSwitch TOPar eexpr TCPar TOBrace list(decl_var) list(case_line) TCBrace
975 { P.switch $1 $2 $3 $4 $5 (List.concat $6) $7 $8 }
976 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
977 | TReturn TPtVirg { P.ret $1 $2 }
978 | TBreak TPtVirg { P.break $1 $2 }
979 | TContinue TPtVirg { P.cont $1 $2 }
980 | ident TDotDot { P.label $1 $2 }
981 | TGoto ident TPtVirg { P.goto $1 $2 $3 }
982 | TOBrace fun_start TCBrace
986 TEllipsis w=list(whenppdecs)
987 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." $1, List.concat w)) }
988 | TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
989 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." $1, b,
990 P.clt2mcode "...>" c, List.concat w, false)) }
991 | TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
992 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." $1, b,
993 P.clt2mcode "...+>" c, List.concat w, true)) }
995 %inline stm_dots_ell:
996 a=TEllipsis w=list(whenppdecs)
997 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." a, List.concat w)) }
999 %inline stm_dots_nest:
1000 a=TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
1001 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." a, b,
1002 P.clt2mcode "...>" c, List.concat w, false)) }
1003 | a=TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
1004 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." a, b,
1005 P.clt2mcode "...+>" c, List.concat w, true)) }
1007 whenppdecs: w=whens(when_start,rule_elem_statement,any_strict)
1010 /* a statement that fits into a single rule_elem. should nests be included?
1011 what about statement metavariables? */
1012 rule_elem_statement:
1014 { Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),$1)) }
1015 | expr TPtVirg { P.exp_stm $1 $2 }
1016 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
1017 | TReturn TPtVirg { P.ret $1 $2 }
1018 | TBreak TPtVirg { P.break $1 $2 }
1019 | TContinue TPtVirg { P.cont $1 $2 }
1020 | TOPar0 midzero_list(rule_elem_statement,rule_elem_statement) TCPar0
1021 { let (mids,code) = $2 in
1023 (Ast0.Disj(P.clt2mcode "(" $1,
1024 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
1025 mids, P.clt2mcode ")" $3)) }
1027 /* a statement on its own */
1030 | TOPar0 midzero_list(statement,statement) TCPar0
1031 /* degenerate case, elements are single statements and thus don't
1033 { let (mids,code) = $2 in
1035 (Ast0.Disj(P.clt2mcode "(" $1,
1036 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
1037 mids, P.clt2mcode ")" $3)) }
1040 TDefault TDotDot fun_start
1042 (Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) }
1043 | TCase eexpr TDotDot fun_start
1044 { Ast0.wrap(Ast0.Case(P.clt2mcode "case" $1,$2,P.clt2mcode ":" $3,$4)) }
1045 /* | lp=TOPar0 t=midzero_list(case_line,case_line) rp=TCPar0
1046 { let (mids,code) = ([],[t]) in
1048 (Ast0.DisjCase(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) } */
1050 /* In the following, an identifier as a type is not fully supported. Indeed,
1051 the language is ambiguous: what is foo * bar; */
1052 /* The AST DisjDecl cannot be generated because it would be ambiguous with
1053 a disjunction on a statement with a declaration in each branch */
1056 { [Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv))] }
1057 | TMetaDecl { [P.meta_decl $1] }
1058 | s=ioption(storage) t=ctype d=comma_list(d_ident) pv=TPtVirg
1060 (function (id,fn) ->
1061 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)))
1063 | f=funproto { [f] }
1064 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
1066 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
1067 /* type is a typedef name */
1068 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
1069 d=comma_list(d_ident) pv=TPtVirg
1071 (function (id,fn) ->
1073 P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1074 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
1076 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
1077 e=initialize pv=TPtVirg
1078 { let (id,fn) = d in
1079 !Data.add_type_name (P.id2name i);
1080 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1081 [Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1082 P.clt2mcode ";" pv))] }
1083 /* function pointer type */
1084 | s=ioption(storage)
1085 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1086 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1088 { let (id,fn) = d in
1091 (Ast0.FunctionPointer
1092 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1093 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1094 [Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv))] }
1095 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1096 { [Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
1097 P.clt2mcode ")" $4,P.clt2mcode ";" $5))] }
1098 | s=ioption(storage)
1099 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1100 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1101 q=TEq e=initialize pv=TPtVirg
1102 { let (id,fn) = d in
1105 (Ast0.FunctionPointer
1106 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1107 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1108 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
1109 | s=Ttypedef t=typedef_ctype id=comma_list(typedef_ident) pv=TPtVirg
1110 { let s = P.clt2mcode "typedef" s in
1113 Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv)))
1118 { Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv)) }
1119 | TMetaDecl { P.meta_decl $1 }
1120 | s=ioption(storage) t=ctype d=d_ident pv=TPtVirg
1121 { let (id,fn) = d in
1122 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1124 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
1125 { let (id,fn) = d in
1126 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)) }
1127 /* type is a typedef name */
1128 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
1129 d=d_ident pv=TPtVirg
1130 { let (id,fn) = d in
1131 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1132 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) }
1133 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
1134 e=initialize pv=TPtVirg
1135 { let (id,fn) = d in
1136 !Data.add_type_name (P.id2name i);
1137 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1138 Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1139 P.clt2mcode ";" pv)) }
1140 /* function pointer type */
1141 | s=ioption(storage)
1142 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1143 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1145 { let (id,fn) = d in
1148 (Ast0.FunctionPointer
1149 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1150 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1151 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1152 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1153 { Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
1154 P.clt2mcode ")" $4,P.clt2mcode ";" $5)) }
1155 | s=ioption(storage)
1156 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1157 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1158 q=TEq e=initialize pv=TPtVirg
1159 { let (id,fn) = d in
1162 (Ast0.FunctionPointer
1163 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1164 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1165 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))}
1169 ident list(array_dec)
1173 (function (l,i,r) ->
1176 (Ast0.Array(rest,P.clt2mcode "[" l,i,P.clt2mcode "]" r)))
1179 array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
1183 { Ast0.wrap(Ast0.InitExpr($1)) }
1184 | TOBrace initialize_list TCBrace
1185 { if P.struct_initializer $2
1187 let il = P.drop_dot_commas $2 in
1188 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
1190 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
1192 {let (nm,pure,clt) = $1 in
1193 Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) }
1196 /*arithexpr and not eexpr because can have ambiguity with comma*/
1197 /*dots and nests probably not allowed at top level, haven't looked into why*/
1198 arith_expr(eexpr,invalid) { Ast0.wrap(Ast0.InitExpr($1)) }
1199 | TOBrace initialize_list TCBrace
1200 { if P.struct_initializer $2
1202 let il = P.drop_dot_commas $2 in
1203 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
1205 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
1206 /* gccext:, labeled elements */
1207 | list(designator) TEq initialize2 /*can we have another of these on the rhs?*/
1208 { Ast0.wrap(Ast0.InitGccExt($1,P.clt2mcode "=" $2,$3)) }
1209 | ident TDotDot initialize2
1210 { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
1214 { Ast0.DesignatorField (P.clt2mcode "." $1,$2) }
1216 { Ast0.DesignatorIndex (P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3) }
1217 | TOCro eexpr TEllipsis eexpr TCCro
1218 { Ast0.DesignatorRange (P.clt2mcode "[" $1,$2,P.clt2mcode "..." $3,
1219 $4,P.clt2mcode "]" $5) }
1222 empty_list_start(initialize2,edots_when(TEllipsis,initialize))
1223 { Ast0.wrap(Ast0.DOTS($1 P.mkidots (fun c -> Ast0.IComma c))) }
1225 /* a statement that is part of a list */
1228 { let (nm,pure,clt) = $1 in
1229 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1234 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1236 | statement { [$1] }
1237 /* this doesn't allow expressions at top level, because the parser doesn't
1238 know whether there is one. If there is one, this is not sequencible.
1239 If there is not one, then it is. It seems complicated to get around
1240 this at the parser level. We would have to have a check afterwards to
1241 allow this. One case where this would be useful is for a when. Now
1242 we allow a sequence of whens, so one can be on only statements and
1243 one can be on only expressions. */
1244 | TOPar0 t=midzero_list(fun_start,fun_start) TCPar0
1245 { let (mids,code) = t in
1248 match Ast0.unwrap x with Ast0.DOTS([]) -> true | _ -> false)
1252 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, code, mids,
1253 P.clt2mcode ")" $3))] }
1255 /* a statement that is part of a list */
1256 decl_statement_expr:
1258 { let (nm,pure,clt) = $1 in
1259 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1264 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1266 | statement { [$1] }
1267 /* this doesn't allow expressions at top level, because the parser doesn't
1268 know whether there is one. If there is one, this is not sequencible.
1269 If there is not one, then it is. It seems complicated to get around
1270 this at the parser level. We would have to have a check afterwards to
1271 allow this. One case where this would be useful is for a when. Now
1272 we allow a sequence of whens, so one can be on only statements and
1273 one can be on only expressions. */
1274 | TOPar0 t=midzero_list(fun_after_stm,fun_after_dots_or) TCPar0
1275 { let (mids,code) = t in
1276 if List.for_all (function [] -> true | _ -> false) code
1280 List.map (function x -> Ast0.wrap(Ast0.DOTS x)) code in
1281 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, dot_code, mids,
1282 P.clt2mcode ")" $3))] }
1284 /*****************************************************************************/
1286 /* The following cannot contain <... ...> at the top level. This can only
1287 be allowed as an expression when the expression is delimited on both sides
1288 by expression-specific markers. In that case, the rule eexpr is used, which
1289 allows <... ...> anywhere. Hopefully, this will not be too much of a problem
1291 expr: basic_expr(expr,invalid) { $1 }
1292 /* allows ... and nests */
1293 eexpr: basic_expr(eexpr,dot_expressions) { $1 }
1294 /* allows nests but not .... */
1295 dexpr: basic_expr(eexpr,nest_expressions) { $1 }
1298 eexpr { Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))) }
1301 TInvalid { raise (Semantic_cocci.Semantic "not matchable") }
1304 TEllipsis { Ast0.wrap(Ast0.Edots(P.clt2mcode "..." $1,None)) }
1305 | nest_expressions { $1 }
1307 /* not clear what whencode would mean, so just drop it */
1309 TOEllipsis e=expr_dots(TEllipsis) c=TCEllipsis
1310 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." $1,
1311 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1312 P.clt2mcode "...>" c, None, false)) }
1313 | TPOEllipsis e=expr_dots(TEllipsis) c=TPCEllipsis
1314 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
1315 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1316 P.clt2mcode "...+>" c, None, true)) }
1318 //whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
1320 basic_expr(recurser,primary_extra):
1321 assign_expr(recurser,primary_extra) { $1 }
1324 cond_expr(r,pe) { $1 }
1325 | unary_expr(r,pe) TAssign assign_expr_bis
1326 { let (op,clt) = $2 in
1327 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1328 Ast0.set_arg_exp $3,false)) }
1329 | unary_expr(r,pe) TEq assign_expr_bis
1332 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1335 cond_expr(eexpr,dot_expressions) { $1 }
1336 | unary_expr(eexpr,dot_expressions) TAssign assign_expr_bis
1337 { let (op,clt) = $2 in
1338 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1339 Ast0.set_arg_exp $3,false)) }
1340 | unary_expr(eexpr,dot_expressions) TEq assign_expr_bis
1343 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1346 arith_expr(r,pe) { $1 }
1347 | l=arith_expr(r,pe) w=TWhy t=option(eexpr) dd=TDotDot r=cond_expr(r,pe)
1348 { Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
1349 P.clt2mcode ":" dd, r)) }
1352 cast_expr(r,pe) { $1 }
1353 | arith_expr(r,pe) TMul arith_expr(r,pe)
1354 { P.arith_op Ast.Mul $1 $2 $3 }
1355 | arith_expr(r,pe) TDmOp arith_expr(r,pe)
1356 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1357 | arith_expr(r,pe) TPlus arith_expr(r,pe)
1358 { P.arith_op Ast.Plus $1 $2 $3 }
1359 | arith_expr(r,pe) TMinus arith_expr(r,pe)
1360 { P.arith_op Ast.Minus $1 $2 $3 }
1361 | arith_expr(r,pe) TShLOp arith_expr(r,pe)
1362 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1363 | arith_expr(r,pe) TShROp arith_expr(r,pe)
1364 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1365 | arith_expr(r,pe) TLogOp arith_expr(r,pe)
1366 { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
1367 | arith_expr(r,pe) TEqEq arith_expr(r,pe)
1368 { P.logic_op Ast.Eq $1 $2 $3 }
1369 | arith_expr(r,pe) TNotEq arith_expr(r,pe)
1370 { P.logic_op Ast.NotEq $1 $2 $3 }
1371 | arith_expr(r,pe) TAnd arith_expr(r,pe)
1372 { P.arith_op Ast.And $1 $2 $3 }
1373 | arith_expr(r,pe) TOr arith_expr(r,pe)
1374 { P.arith_op Ast.Or $1 $2 $3 }
1375 | arith_expr(r,pe) TXor arith_expr(r,pe)
1376 { P.arith_op Ast.Xor $1 $2 $3 }
1377 | arith_expr(r,pe) TAndLog arith_expr(r,pe)
1378 { P.logic_op Ast.AndLog $1 $2 $3 }
1379 | arith_expr(r,pe) TOrLog arith_expr(r,pe)
1380 { P.logic_op Ast.OrLog $1 $2 $3 }
1383 unary_expr(r,pe) { $1 }
1384 | lp=TOPar t=ctype rp=TCPar e=cast_expr(r,pe)
1385 { Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
1386 P.clt2mcode ")" rp, e)) }
1389 postfix_expr(r,pe) { $1 }
1390 | TInc unary_expr(r,pe)
1391 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
1392 | TDec unary_expr(r,pe)
1393 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
1394 | unary_op cast_expr(r,pe)
1395 { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
1396 | TBang unary_expr(r,pe)
1397 { let mcode = P.clt2mcode Ast.Not $1 in
1398 Ast0.wrap(Ast0.Unary($2, mcode)) }
1399 | TSizeof unary_expr(r,pe)
1400 { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
1401 | s=TSizeof lp=TOPar t=ctype rp=TCPar
1402 { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
1403 P.clt2mcode "(" lp,t,
1404 P.clt2mcode ")" rp)) }
1406 unary_op: TAnd { P.clt2mcode Ast.GetRef $1 }
1407 | TMul { P.clt2mcode Ast.DeRef $1 }
1408 | TPlus { P.clt2mcode Ast.UnPlus $1 }
1409 | TMinus { P.clt2mcode Ast.UnMinus $1 }
1410 | TTilde { P.clt2mcode Ast.Tilde $1 }
1413 primary_expr(r,pe) { $1 }
1414 | postfix_expr(r,pe) TOCro eexpr TCCro
1415 { Ast0.wrap(Ast0.ArrayAccess ($1,P.clt2mcode "[" $2,$3,
1416 P.clt2mcode "]" $4)) }
1417 | postfix_expr(r,pe) TDot ident
1418 { Ast0.wrap(Ast0.RecordAccess($1, P.clt2mcode "." $2, $3)) }
1419 | postfix_expr(r,pe) TPtrOp ident
1420 { Ast0.wrap(Ast0.RecordPtAccess($1, P.clt2mcode "->" $2,
1422 | postfix_expr(r,pe) TInc
1423 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Inc $2)) }
1424 | postfix_expr(r,pe) TDec
1425 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Dec $2)) }
1426 | postfix_expr(r,pe) TOPar eexpr_list_option TCPar
1427 { Ast0.wrap(Ast0.FunCall($1,P.clt2mcode "(" $2,
1429 P.clt2mcode ")" $4)) }
1431 primary_expr(recurser,primary_extra):
1432 func_ident { Ast0.wrap(Ast0.Ident($1)) }
1434 { let (x,clt) = $1 in
1435 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1437 { let (x,clt) = $1 in
1438 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) }
1440 { let (x,clt) = $1 in
1441 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) }
1443 { let (x,clt) = $1 in
1444 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) }
1446 { let (nm,constraints,pure,ty,clt) = $1 in
1448 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
1450 { let (nm,constraints,pure,clt) = $1 in
1451 Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) }
1453 { let (nm,constraints,pure,ty,clt) = $1 in
1455 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
1457 { let (nm,constraints,pure,ty,clt) = $1 in
1459 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
1461 { let (nm,constraints,pure,ty,clt) = $1 in
1463 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) }
1465 { Ast0.wrap(Ast0.Paren(P.clt2mcode "(" $1,$2,
1466 P.clt2mcode ")" $3)) }
1467 | TOPar0 midzero_list(recurser,eexpr) TCPar0
1468 { let (mids,code) = $2 in
1469 Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" $1,
1471 P.clt2mcode ")" $3)) }
1472 | primary_extra { $1 }
1475 r=no_dot_start_end(dexpr,edots_when(dotter,eexpr)) { r }
1478 no_dot_start_end(grammar,dotter):
1479 g=grammar dg=list(pair(dotter,grammar))
1480 { function dot_builder ->
1481 g :: (List.concat(List.map (function (d,g) -> [dot_builder d;g]) dg)) }
1483 /*****************************************************************************/
1489 | TIdentifier { "identifier" }
1490 | TExpression { "expression" }
1491 | TStatement { "statement" }
1492 | TFunction { "function" }
1493 | TLocal { "local" }
1495 | TParameter { "parameter" }
1496 | TIdExpression { "idexpression" }
1497 | TInitialiser { "initialiser" }
1499 | TFresh { "fresh" }
1500 | TConstant { "constant" }
1501 | TError { "error" }
1502 | TWords { "words" }
1504 | TContext { "context" }
1505 | TGenerated { "generated" }
1506 | TTypedef { "typedef" }
1507 | TDeclarer { "declarer" }
1508 | TIterator { "iterator" }
1510 | TPosition { "position" }
1513 TRuleName TDot pure_ident { (Some $1,P.id2name $3) }
1514 | TRuleName TDot pure_ident_kwd { (Some $1,$3) }
1516 pure_ident_or_meta_ident:
1517 pure_ident { (None,P.id2name $1) }
1518 | pure_ident_kwd { (None,$1) }
1521 pure_ident_or_meta_ident_with_seed:
1522 pure_ident_or_meta_ident { ($1,Ast.NoVal) }
1523 | pure_ident_or_meta_ident TEq
1524 separated_nonempty_list(TCppConcatOp,seed_elem)
1526 [Ast.SeedString s] -> ($1,Ast.StringSeed s)
1527 | _ -> ($1,Ast.ListSeed $3) }
1530 TString { let (x,_) = $1 in Ast.SeedString x }
1531 | TMetaId { let (x,_,_,_) = $1 in Ast.SeedId x }
1532 | TRuleName TDot pure_ident
1533 { let nm = ($1,P.id2name $3) in
1534 P.check_meta(Ast.MetaIdDecl(Ast.NONE,nm));
1537 pure_ident_or_meta_ident_with_x_eq(x_eq):
1538 i=pure_ident_or_meta_ident l=loption(x_eq)
1543 pure_ident_or_meta_ident_with_econstraint(x_eq):
1544 i=pure_ident_or_meta_ident optc=option(x_eq)
1547 None -> (i, Ast0.NoConstraint)
1551 pure_ident_or_meta_ident_with_idconstraint_virt(constraint_type):
1552 i=pure_ident_or_meta_ident c=option(constraint_type)
1556 None -> (i, Ast.IdNoConstraint)
1557 | Some constraint_ -> (i,constraint_))
1559 | TVirtual TDot pure_ident { Common.Right (P.id2name $3) }
1561 pure_ident_or_meta_ident_with_idconstraint(constraint_type):
1562 i=pure_ident_or_meta_ident c=option(constraint_type)
1565 None -> (i, Ast.IdNoConstraint)
1566 | Some constraint_ -> (i,constraint_)
1570 re=regexp_eqid {Ast.IdRegExpConstraint re}
1576 then failwith "constraints not allowed in iso file");
1577 (if !Data.in_generating
1578 then failwith "constraints not allowed in a generated rule file");
1579 let (s,_) = re in Ast.IdRegExp (s,Str.regexp s)
1581 | TTildeExclEq re=TString
1583 then failwith "constraints not allowed in iso file");
1584 (if !Data.in_generating
1585 then failwith "constraints not allowed in a generated rule file");
1586 let (s,_) = re in Ast.IdNotRegExp (s,Str.regexp s)
1590 TNotEq i=pure_ident_or_meta_ident
1592 then failwith "constraints not allowed in iso file");
1593 (if !Data.in_generating
1594 (* pb: constraints not stored with metavars; too lazy to search for
1595 them in the pattern *)
1596 then failwith "constraints not allowed in a generated rule file");
1600 P.check_inherited_constraint i
1601 (function mv -> Ast.MetaIdDecl(Ast.NONE,mv)) in
1602 Ast.IdNegIdSet([],[i])
1603 | (None,i) -> Ast.IdNegIdSet([i],[])) }
1604 | TNotEq TOBrace l=comma_list(pure_ident_or_meta_ident) TCBrace
1606 then failwith "constraints not allowed in iso file");
1607 (if !Data.in_generating
1608 then failwith "constraints not allowed in a generated rule file");
1611 (function (str,meta) ->
1613 (Some rn,id) as i ->
1615 P.check_inherited_constraint i
1616 (function mv -> Ast.MetaIdDecl(Ast.NONE,mv)) in
1618 | (None,i) -> (i::str,meta))
1620 Ast.IdNegIdSet(str,meta)
1623 re_or_not_eqe_or_sub:
1624 re=regexp_eqid {Ast0.NotIdCstrt re}
1625 | ne=not_eqe {Ast0.NotExpCstrt ne}
1626 | s=sub {Ast0.SubExpCstrt s}
1629 ceq=not_ceq {Ast0.NotExpCstrt ceq}
1630 | s=sub {Ast0.SubExpCstrt s}
1635 then failwith "constraints not allowed in iso file");
1636 (if !Data.in_generating
1637 then failwith "constraints not allowed in a generated rule file");
1638 [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))]
1640 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1642 then failwith "constraints not allowed in iso file");
1643 (if !Data.in_generating
1644 then failwith "constraints not allowed in a generated rule file");
1647 Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
1652 TNotEq i=ident_or_const
1654 then failwith "constraints not allowed in iso file");
1655 (if !Data.in_generating
1656 then failwith "constraints not allowed in a generated rule file");
1658 | TNotEq TOBrace l=comma_list(ident_or_const) TCBrace
1660 then failwith "constraints not allowed in iso file");
1661 (if !Data.in_generating
1662 then failwith "constraints not allowed in a generated rule file");
1666 (* has to be inherited because not clear how to check subterm constraints
1667 in the functorized CTL engine, so need the variable to be bound
1668 already when bind the subterm constrained metavariable *)
1671 then failwith "constraints not allowed in iso file");
1672 (if !Data.in_generating
1673 then failwith "constraints not allowed in a generated rule file");
1675 P.check_inherited_constraint i
1676 (function mv -> Ast.MetaExpDecl(Ast.NONE,mv,None)) in
1678 | TSub TOBrace l=comma_list(meta_ident) TCBrace
1680 then failwith "constraints not allowed in iso file");
1681 (if !Data.in_generating
1682 then failwith "constraints not allowed in a generated rule file");
1685 P.check_inherited_constraint i
1686 (function mv -> Ast.MetaExpDecl(Ast.NONE,mv,None)))
1690 i=pure_ident { Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))) }
1692 { let (x,clt) = $1 in
1693 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1698 then failwith "constraints not allowed in iso file");
1699 (if !Data.in_generating
1700 then failwith "constraints not allowed in a generated rule file");
1702 P.check_inherited_constraint i
1703 (function mv -> Ast.MetaPosDecl(Ast.NONE,mv)) in
1705 | TNotEq TOBrace l=comma_list(meta_ident) TCBrace
1707 then failwith "constraints not allowed in iso file");
1708 (if !Data.in_generating
1709 then failwith "constraints not allowed in a generated rule file");
1712 P.check_inherited_constraint i
1713 (function mv -> Ast.MetaPosDecl(Ast.NONE,mv)))
1716 func_ident: pure_ident
1717 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1719 { let (nm,constraints,pure,clt) = $1 in
1720 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1722 { let (nm,constraints,pure,clt) = $1 in
1723 Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
1725 { let (nm,constraints,pure,clt) = $1 in
1727 (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
1730 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1732 { let (nm,constraints,pure,clt) = $1 in
1733 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1737 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1739 { let (nm,constraints,pure,clt) = $1 in
1740 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1744 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1746 { let (nm,constraints,pure,clt) = $1 in
1747 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1751 { Ast0.wrap(Ast0.TypeName(P.id2mcode $1)) }
1753 { let (nm,pure,clt) = $1 in
1754 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
1756 /*****************************************************************************/
1759 empty_list_start(one_dec(decl),TEllipsis)
1763 (fun _ d -> Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." d)))
1764 (fun c -> Ast0.PComma c))) }
1769 { let (nm,lenname,pure,clt) = $1 in
1770 let nm = P.clt2mcode nm clt in
1773 Ast.AnyLen -> Ast0.AnyListLen
1774 | Ast.MetaLen nm -> Ast0.MetaListLen(P.clt2mcode nm clt)
1775 | Ast.CstLen n -> Ast0.CstListLen n in
1776 Ast0.wrap(Ast0.MetaParamList(nm,lenname,pure)) }
1778 /* ---------------------------------------------------------------------- */
1779 /* comma list parser, used for fn params, fn args, enums, initlists,
1782 /* enums: enum_decl, edots_when(TEllipsis,enum_decl_one)
1783 fun s d -> P.mkedots "..." d
1784 fun c -> Ast0.EComma c
1787 empty_list_start(elem,dotter):
1788 /* empty */ { fun build_dots build_comma -> [] }
1789 | nonempty_list_start(elem,dotter) { $1 }
1791 nonempty_list_start(elem,dotter): /* dots allowed */
1792 elem { fun build_dots build_comma -> [$1] }
1794 { fun build_dots build_comma ->
1795 $1::[Ast0.wrap(build_comma(P.clt2mcode "," $2))] }
1796 | elem TComma nonempty_list_start(elem,dotter)
1797 { fun build_dots build_comma ->
1798 $1::(Ast0.wrap(build_comma(P.clt2mcode "," $2)))::
1799 ($3 build_dots build_comma) }
1800 | TNothing nonempty_list_start(elem,dotter) { $2 }
1801 | d=dotter { fun build_dots build_comma -> [(build_dots "..." d)] }
1803 { fun build_dots build_comma ->
1804 [(build_dots "..." d);Ast0.wrap(build_comma(P.clt2mcode "," $2))] }
1805 | d=dotter TComma r=continue_list(elem,dotter)
1806 { fun build_dots build_comma ->
1807 (build_dots "..." d)::
1808 (Ast0.wrap(build_comma(P.clt2mcode "," $2)))::
1809 (r build_dots build_comma) }
1811 continue_list(elem,dotter): /* dots not allowed */
1812 elem { fun build_dots build_comma -> [$1] }
1814 { fun build_dots build_comma ->
1815 $1::[Ast0.wrap(build_comma(P.clt2mcode "," $2))] }
1816 | elem TComma nonempty_list_start(elem,dotter)
1817 { fun build_dots build_comma ->
1818 $1::(Ast0.wrap(build_comma(P.clt2mcode "," $2)))::
1819 ($3 build_dots build_comma) }
1820 | TNothing nonempty_list_start(elem,dotter) { $2 }
1822 /* ---------------------------------------------------------------------- */
1824 /* error words make it complicated to be able to use error as a metavariable
1825 name or a type in a metavariable list; for that we would like to allow TError
1826 as an ident, but that makes conflicts with this rule. To add back error words,
1827 need to find some appropriate delimiter for it, but it has not been used much
1830 TError TWords TEq TOCro cl=comma_list(dexpr) TCCro
1831 { [Ast0.wrap(Ast0.ERRORWORDS(cl))] }
1834 /* ---------------------------------------------------------------------- */
1835 /* sequences of statements and expressions */
1837 /* There are number of cases that must be considered:
1840 Dots and nests allowed at the beginning or end
1841 Expressions allowed at the beginning or end
1842 One function allowed, by itself
1844 Dots and nests allowed at the beginning or end
1845 Expressions not allowed at the beginning or end
1846 Functions not allowed
1847 3. The body of a nest:
1848 Dots and nests not allowed at the beginning or end
1849 Expressions allowed at the beginning or end
1850 Functions not allowed
1852 Dots and nests not allowed at the beginning but allowed at the end
1853 Expressions allowed at the beginning or end
1854 Functions not allowed
1856 These are implemented by the rules minus_toplevel_sequence,
1857 plus_toplevel_sequence, function_body_sequence, nest_body_sequence, and
1860 /* ------------------------------------------------------------------------ */
1861 /* Minus top level */
1863 /* doesn't allow only ... */
1865 fundecl { [Ast0.wrap(Ast0.DECL($1))] }
1866 | ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1867 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1868 | toplevel_seq_startne(toplevel_after_dots_init)
1869 { List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1 }
1871 toplevel_seq_startne(after_dots_init):
1872 a=stm_dots_ell b=after_dots_init { a::b }
1873 | a=stm_dots_nest b=after_dots_init { a::b }
1874 | a=stm_dots_nest { [a] }
1875 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1876 | decl_statement_expr toplevel_after_stm { $1@$2 }
1878 toplevel_seq_start(after_dots_init):
1879 stm_dots after_dots_init { $1::$2 }
1880 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1881 | decl_statement_expr toplevel_after_stm { $1@$2 }
1883 toplevel_after_dots_init:
1884 TNothing toplevel_after_exp {$2}
1885 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1886 | decl_statement_expr toplevel_after_stm {$1@$2}
1890 | stm_dots toplevel_after_dots {$1::$2}
1892 toplevel_after_dots:
1894 | TNothing toplevel_after_exp {$2}
1895 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1896 | decl_statement_expr toplevel_after_stm {$1@$2}
1900 | stm_dots toplevel_after_dots {$1::$2}
1901 | decl_statement toplevel_after_stm {$1@$2}
1904 TOInit initialize_list TCBrace
1905 { if P.struct_initializer $2
1907 let il = P.drop_dot_commas $2 in
1908 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
1910 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
1912 /* ------------------------------------------------------------------------ */
1913 /* Plus top level */
1915 /* does allow only ... also allows multiple top-level functions */
1917 ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1918 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1919 | stm_dots plus_after_dots
1920 { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1921 | expr plus_after_exp
1922 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1923 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1924 | decl_statement_expr plus_after_stm
1925 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1929 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1933 | TNothing plus_after_exp {$2}
1934 | expr plus_after_exp
1935 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1936 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1937 | decl_statement_expr plus_after_stm
1938 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1942 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1943 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1944 | decl_statement plus_after_stm
1945 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1947 /* ------------------------------------------------------------------------ */
1951 fun_after_stm { Ast0.wrap(Ast0.DOTS($1)) }
1955 | stm_dots fun_after_dots {$1::$2}
1956 | decl_statement fun_after_stm {$1@$2}
1960 | TNothing fun_after_exp {$2}
1961 | expr fun_after_exp {Ast0.wrap(Ast0.Exp($1))::$2}
1962 | decl_statement_expr fun_after_stm {$1@$2}
1965 stm_dots fun_after_dots {$1::$2}
1967 /* hack to allow mixing statements and expressions in an or */
1970 | TNothing fun_after_exp_or {$2}
1971 | expr fun_after_exp_or {Ast0.wrap(Ast0.Exp($1))::$2}
1972 | decl_statement_expr fun_after_stm {$1@$2}
1976 | stm_dots fun_after_dots {$1::$2}
1978 /* ------------------------------------------------------------------------ */
1982 nest_after_dots { Ast0.wrap(Ast0.DOTS($1)) }
1985 decl_statement_expr nest_after_stm {$1@$2}
1986 | TNothing nest_after_exp {$2}
1987 | expr nest_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1991 | stm_dots nest_after_dots {$1::$2}
1992 | decl_statement nest_after_stm {$1@$2}
1996 | stm_dots nest_after_dots {$1::$2}
1998 /* ------------------------------------------------------------------------ */
2002 expr toplevel_after_exp
2003 { Ast0.wrap(Ast0.DOTS((Ast0.wrap(Ast0.Exp($1)))::$2)) }
2004 | decl_statement toplevel_after_stm
2005 { Ast0.wrap(Ast0.DOTS($1@$2)) }
2007 /* ---------------------------------------------------------------------- */
2009 /* arg expr. may contain a type or a explist metavariable */
2011 dexpr { Ast0.set_arg_exp $1 }
2013 { let (nm,lenname,pure,clt) = $1 in
2014 let nm = P.clt2mcode nm clt in
2017 Ast.AnyLen -> Ast0.AnyListLen
2018 | Ast.MetaLen nm -> Ast0.MetaListLen(P.clt2mcode nm clt)
2019 | Ast.CstLen n -> Ast0.CstListLen n in
2020 Ast0.wrap(Ast0.MetaExprList(nm,lenname,pure)) }
2022 { Ast0.set_arg_exp(Ast0.wrap(Ast0.TypeExp($1))) }
2025 empty_list_start(aexpr,TEllipsis)
2029 (fun _ d -> Ast0.wrap(Ast0.Edots(P.clt2mcode "..." d,None)))
2030 (fun c -> Ast0.EComma c))) }
2032 /****************************************************************************/
2034 // non-empty lists - drop separator
2036 separated_nonempty_list(TComma,elem) { $1 }
2038 midzero_list(elem,aft):
2039 a=elem b=list(mzl(aft))
2040 { let (mids,code) = List.split b in (mids,(a::code)) }
2043 a=TMid0 b=elem { (P.clt2mcode "|" a, b) }
2045 edots_when(dotter,when_grammar):
2046 d=dotter { (d,None) }
2047 | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
2049 whens(when_grammar,simple_when_grammar,any_strict):
2050 TWhen TNotEq w=when_grammar TLineEnd { [Ast0.WhenNot w] }
2051 | TWhen TEq w=simple_when_grammar TLineEnd { [Ast0.WhenAlways w] }
2052 | TWhen comma_list(any_strict) TLineEnd
2053 { List.map (function x -> Ast0.WhenModifier(x)) $2 }
2054 | TWhenTrue TNotEq e = eexpr TLineEnd { [Ast0.WhenNotTrue e] }
2055 | TWhenFalse TNotEq e = eexpr TLineEnd { [Ast0.WhenNotFalse e] }
2058 TAny { Ast.WhenAny }
2059 | TStrict { Ast.WhenStrict }
2060 | TForall { Ast.WhenForall }
2061 | TExists { Ast.WhenExists }
2063 /*****************************************************************************
2066 *****************************************************************************/
2069 TIsoExpression e1=eexpr el=list(iso(eexpr)) EOF
2070 { let fn x = Ast0.ExprTag x in P.iso_adjust fn fn e1 el }
2071 | TIsoArgExpression e1=eexpr el=list(iso(eexpr)) EOF
2072 { let fn x = Ast0.ArgExprTag x in P.iso_adjust fn fn e1 el }
2073 | TIsoTestExpression e1=eexpr el=list(iso(eexpr)) EOF
2074 { let fn x = Ast0.TestExprTag x in P.iso_adjust fn fn e1 el }
2075 | TIsoToTestExpression e1=eexpr el=list(iso(eexpr)) EOF
2076 { let ffn x = Ast0.ExprTag x in
2077 let fn x = Ast0.TestExprTag x in
2078 P.iso_adjust ffn fn e1 el }
2079 | TIsoStatement s1=single_statement sl=list(iso(single_statement)) EOF
2080 { let fn x = Ast0.StmtTag x in P.iso_adjust fn fn s1 sl }
2081 | TIsoType t1=ctype tl=list(iso(ctype)) EOF
2082 { let fn x = Ast0.TypeCTag x in P.iso_adjust fn fn t1 tl }
2083 | TIsoTopLevel e1=nest_start el=list(iso(nest_start)) EOF
2084 { let fn x = Ast0.DotsStmtTag x in P.iso_adjust fn fn e1 el }
2085 | TIsoDeclaration d1=decl_var dl=list(iso(decl_var)) EOF
2086 { let check_one = function
2090 (Semantic_cocci.Semantic
2091 "only one variable per declaration in an isomorphism rule") in
2092 let d1 = check_one d1 in
2096 Common.Left x -> Common.Left(check_one x)
2097 | Common.Right x -> Common.Right(check_one x))
2099 let fn x = Ast0.DeclTag x in P.iso_adjust fn fn d1 dl }
2102 TIso t=term { Common.Left t }
2103 | TRightIso t=term { Common.Right t }
2105 /*****************************************************************************
2108 *****************************************************************************/
2110 never_used: TPragma { () }
2111 | TPArob TMetaPos { () }
2112 | TScriptData { () }
2115 py=pure_ident TMPtVirg
2116 { ((Some (P.id2name py), None), None) }
2117 | py=pure_ident script_name_decl TMPtVirg
2118 { ((Some (P.id2name py), None), Some $2) }
2119 | TOPar TUnderscore TComma ast=pure_ident TCPar script_name_decl TMPtVirg
2120 { ((None, Some (P.id2name ast)), Some $6) }
2121 | TOPar str=pure_ident TComma TUnderscore TCPar script_name_decl TMPtVirg
2122 { ((Some (P.id2name str), None), Some $6) }
2123 | TOPar str=pure_ident TComma ast=pure_ident TCPar script_name_decl TMPtVirg
2124 { ((Some (P.id2name str), Some (P.id2name ast)), Some $6) }
2127 TShLOp TRuleName TDot cocci=pure_ident
2128 { let nm = P.id2name cocci in
2129 let mv = Parse_aux.lookup $2 nm in
2131 | TShLOp TVirtual TDot cocci=pure_ident
2132 { let nm = P.id2name cocci in
2133 let name = ("virtual", nm) in
2134 let mv = Ast.MetaIdDecl(Ast.NONE,name) in