2 * Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
3 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
4 * This file is part of Coccinelle.
6 * Coccinelle is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, according to version 2 of the License.
10 * Coccinelle is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
18 * The authors reserve the right to distribute this or future versions of
19 * Coccinelle under other licenses.
25 (* Not clear how to allow function declarations to specify a return type
26 and how to allow both to be specified as static, because they are in
27 different rules. The rules seem to have to be combined, which would allow
28 functions to be declared as local variables *)
30 (* Not clear how to let a function have a parameter of type void. At the
31 moment, void is allowed to be the type of a variable, which is wrong, and a
32 parameter needs both a type and an identifier *)
33 module Ast0 = Ast0_cocci
34 module Ast = Ast_cocci
40 %token TIdentifier TExpression TStatement TFunction TLocal TType TParameter
42 %token Tlist TFresh TConstant TError TWords TWhy0 TPlus0 TBang0
44 %token TTypedef TDeclarer TIterator TName TPosition TPosAny
45 %token TUsing TDisable TExtends TDepends TOn TEver TNever TExists TForall TScript
46 %token TReverse TNothing
47 %token<string> TRuleName
49 %token<Data.clt> Tchar Tshort Tint Tdouble Tfloat Tlong
50 %token<Data.clt> Tvoid Tstruct Tunion
51 %token<Data.clt> Tunsigned Tsigned
53 %token<Data.clt> Tstatic Tauto Tregister Textern Tinline Ttypedef
54 %token<Data.clt> Tconst Tvolatile
55 %token<string * Data.clt> Tattr
57 %token <Data.clt> TIf TElse TWhile TFor TDo TSwitch TCase TDefault TReturn
58 %token <Data.clt> TBreak TContinue TGoto TSizeof TFunDecl
59 %token <string * Data.clt> TIdent TTypeId TDeclarerId TIteratorId
61 %token <Parse_aux.idinfo> TMetaId TMetaFunc TMetaLocalFunc
62 %token <Parse_aux.idinfo> TMetaIterator TMetaDeclarer
63 %token <Parse_aux.expinfo> TMetaErr
64 %token <Parse_aux.info> TMetaParam TMetaStm TMetaStmList TMetaType
65 %token <Parse_aux.list_info> TMetaParamList TMetaExpList
66 %token <Parse_aux.typed_info> TMetaExp TMetaIdExp TMetaLocalIdExp TMetaConst
67 %token <Parse_aux.pos_info> TMetaPos
69 %token TArob TArobArob TPArob
70 %token <string> TScriptData
72 %token <Data.clt> TEllipsis TOEllipsis TCEllipsis TPOEllipsis TPCEllipsis
73 %token <Data.clt> TWhen TWhenTrue TWhenFalse TAny TStrict TLineEnd
75 %token <Data.clt> TWhy TDotDot TBang TOPar TOPar0
76 %token <Data.clt> TMid0 TCPar TCPar0
78 %token <string> TPragma TPathIsoFile
79 %token <string * Data.clt> TIncludeL TIncludeNL
80 %token <Data.clt * token> TDefine
81 %token <Data.clt * token * int> TDefineParam
82 %token <string * Data.clt> TMinusFile TPlusFile
84 %token <Data.clt> TInc TDec
86 %token <string * Data.clt> TString TChar TFloat TInt
88 %token <Data.clt> TOrLog
89 %token <Data.clt> TAndLog
91 %token <Data.clt> TXor
92 %token <Data.clt> TAnd
93 %token <Data.clt> TEqEq TNotEq
94 %token <Ast_cocci.logicalOp * Data.clt> TLogOp /* TInf TSup TInfEq TSupEq */
95 %token <Ast_cocci.arithOp * Data.clt> TShOp /* TShl TShr */
96 %token <Ast_cocci.arithOp * Data.clt> TDmOp /* TDiv TMod */
97 %token <Data.clt> TPlus TMinus
98 %token <Data.clt> TMul TTilde
100 %token <Data.clt> TOBrace TCBrace TOInit
101 %token <Data.clt> TOCro TCCro
103 %token <Data.clt> TPtrOp
106 %token <Data.clt> TEq TDot TComma TPtVirg
107 %token <Ast_cocci.assignOp * Data.clt> TAssign
109 %token TIso TRightIso TIsoExpression TIsoStatement TIsoDeclaration TIsoType
110 %token TIsoTopLevel TIsoArgExpression TIsoTestExpression
114 /* operator precedence */
124 %left TLogOp /* TInf TSup TInfEq TSupEq */
125 %left TShOp /* TShl TShr */
127 %left TMul TDmOp /* TDiv TMod */
133 %type <Ast0_cocci.rule> minus_main
135 %start minus_exp_main
136 %type <Ast0_cocci.rule> minus_exp_main
139 %type <Ast0_cocci.rule> plus_main
142 %type <Ast0_cocci.rule> plus_exp_main
145 %type <(string,string) Common.either list> include_main
148 %type <Ast_cocci.rulename>
152 %type <Ast_cocci.rulename>
156 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> meta_main
158 %start <string * (string * string)> script_meta_main
161 %type <Ast0_cocci.anything list list> iso_main
164 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> iso_meta_main
167 %type <unit> never_used
172 minus_main: minus_body EOF { $1 } | m=minus_body TArobArob { m }
173 | m=minus_body TArob { m }
174 plus_main: plus_body EOF { $1 } | p=plus_body TArobArob { p }
175 | p=plus_body TArob { p }
176 minus_exp_main: minus_exp_body EOF { $1 } | m=minus_exp_body TArobArob { m }
177 | m=minus_exp_body TArob { m }
178 plus_exp_main: plus_exp_body EOF { $1 } | p=plus_exp_body TArobArob { p }
179 | p=plus_exp_body TArob { p }
180 meta_main: m=metadec { m (!Ast0.rule_name) }
181 iso_meta_main: m=metadec { m "" }
183 /*****************************************************************************
186 *****************************************************************************/
190 | TContext { Ast0.Context }
191 | TPure TContext { Ast0.PureContext }
192 | TContext TPure { Ast0.PureContext }
193 | /* empty */ { Ast0.Impure }
196 nm=pure_ident TArob { P.make_iso_rule_name_result (P.id2name nm) }
199 nm=ioption(pure_ident) extends d=depends i=loption(choose_iso)
200 a=loption(disable) e=exists ee=is_expression TArob
201 { P.make_cocci_rule_name_result nm d i a e ee }
202 | TScript TDotDot lang=pure_ident d=depends TArob
203 { P.make_script_rule_name_result lang d }
207 | TExtends parent=TRuleName
208 { !Data.install_bindings (parent) }
211 /* empty */ { Ast.NoDep }
212 | TDepends TOn parents=dep { parents }
216 | dep TAndLog dep { Ast.AndDep($1, $3) }
217 | dep TOrLog dep { Ast.OrDep ($1, $3) }
220 TRuleName { Ast.Dep $1 }
221 | TBang TRuleName { Ast.AntiDep $2 }
222 | TEver TRuleName { Ast.EverDep $2 }
223 | TNever TRuleName { Ast.NeverDep $2 }
224 | TOPar dep TCPar { $2 }
227 TUsing separated_nonempty_list(TComma,TString) { List.map P.id2name $2 }
230 TDisable separated_nonempty_list(TComma,pure_ident) { List.map P.id2name $2 }
233 TExists { Ast.Exists }
234 | TForall { Ast.Forall }
235 | TReverse TForall { Ast.ReverseForall }
236 | { Ast.Undetermined }
238 is_expression: // for more flexible parsing of top level expressions
240 | TExpression { true }
243 list(incl) TArob { $1 }
244 | list(incl) TArobArob { $1 }
247 TUsing TString { Common.Left(P.id2name $2) }
248 | TUsing TPathIsoFile { Common.Right $2 }
252 kindfn=metakind ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
253 { P.create_metadec ar ispure kindfn ids }
254 | ar=arity ispure=pure
255 kindfn=metakind_atomic
256 ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_eq)) TMPtVirg
257 { P.create_metadec_ne ar ispure kindfn ids }
258 | ar=arity ispure=pure
259 kindfn=metakind_atomic_expi
260 ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_eqe)) TMPtVirg
261 { P.create_metadec_ne ar ispure kindfn ids }
262 | ar=arity ispure=pure
263 kindfn=metakind_atomic_expe
264 ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_ceq)) TMPtVirg
265 { P.create_metadec_ne ar ispure kindfn ids }
266 | ar=arity TPosition a=option(TPosAny)
267 ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_pos)) TMPtVirg
268 { let kindfn arity name pure check_meta constraints =
269 let tok = check_meta(Ast.MetaPosDecl(arity,name)) in
270 let any = match a with None -> Ast.PER | Some _ -> Ast.ALL in
271 !Data.add_pos_meta name constraints any; tok in
272 P.create_metadec_ne ar false kindfn ids }
273 | ar=arity ispure=pure
274 TParameter Tlist TOCro id=pure_ident_or_meta_ident TCCro
275 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
276 { P.create_len_metadec ar ispure
277 (fun lenname arity name pure check_meta ->
279 check_meta(Ast.MetaParamListDecl(arity,name,Some lenname)) in
280 !Data.add_paramlist_meta name (Some lenname) pure; tok)
282 | ar=arity ispure=pure
283 TExpression Tlist TOCro id=pure_ident_or_meta_ident TCCro
284 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
285 { P.create_len_metadec ar ispure
286 (fun lenname arity name pure check_meta ->
288 check_meta(Ast.MetaExpListDecl(arity,name,Some lenname)) in
289 !Data.add_explist_meta name (Some lenname) pure; tok)
294 { (fun arity name pure check_meta ->
295 let tok = check_meta(Ast.MetaFreshIdDecl(arity,name)) in
296 !Data.add_id_meta name [] pure; tok) }
298 { (fun arity name pure check_meta ->
299 let tok = check_meta(Ast.MetaParamDecl(arity,name)) in
300 !Data.add_param_meta name pure; tok) }
302 { (fun arity name pure check_meta ->
303 let tok = check_meta(Ast.MetaParamListDecl(arity,name,None)) in
304 !Data.add_paramlist_meta name None pure; tok) }
306 { (fun arity name pure check_meta ->
307 let tok = check_meta(Ast.MetaExpListDecl(arity,name,None)) in
308 !Data.add_explist_meta name None pure; tok) }
310 { (fun arity name pure check_meta ->
311 let tok = check_meta(Ast.MetaTypeDecl(arity,name)) in
312 !Data.add_type_meta name pure; tok) }
314 { (fun arity name pure check_meta ->
315 let tok = check_meta(Ast.MetaStmDecl(arity,name)) in
316 !Data.add_stm_meta name pure; tok) }
318 { (fun arity name pure check_meta ->
319 let tok = check_meta(Ast.MetaStmListDecl(arity,name)) in
320 !Data.add_stmlist_meta name pure; tok) }
322 { (fun arity (_,name) pure check_meta ->
323 if arity = Ast.NONE && pure = Ast0.Impure
324 then (!Data.add_type_name name; [])
325 else raise (Semantic_cocci.Semantic "bad typedef")) }
327 { (fun arity (_,name) pure check_meta ->
328 if arity = Ast.NONE && pure = Ast0.Impure
329 then (!Data.add_declarer_name name; [])
330 else raise (Semantic_cocci.Semantic "bad declarer")) }
332 { (fun arity (_,name) pure check_meta ->
333 if arity = Ast.NONE && pure = Ast0.Impure
334 then (!Data.add_iterator_name name; [])
335 else raise (Semantic_cocci.Semantic "bad iterator")) }
338 %inline metakind_atomic:
340 { (fun arity name pure check_meta constraints ->
341 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
342 !Data.add_id_meta name constraints pure; tok) }
344 { (fun arity name pure check_meta constraints ->
345 let tok = check_meta(Ast.MetaFuncDecl(arity,name)) in
346 !Data.add_func_meta name constraints pure; tok) }
348 { (fun arity name pure check_meta constraints ->
349 let tok = check_meta(Ast.MetaLocalFuncDecl(arity,name)) in
350 !Data.add_local_func_meta name constraints pure;
353 { (fun arity name pure check_meta constraints ->
354 let tok = check_meta(Ast.MetaDeclarerDecl(arity,name)) in
355 !Data.add_declarer_meta name constraints pure; tok) }
357 { (fun arity name pure check_meta constraints ->
358 let tok = check_meta(Ast.MetaIteratorDecl(arity,name)) in
359 !Data.add_iterator_meta name constraints pure; tok) }
361 %inline metakind_atomic_expi:
363 { (fun arity name pure check_meta constraints ->
364 let tok = check_meta(Ast.MetaErrDecl(arity,name)) in
365 !Data.add_err_meta name constraints pure; tok) }
366 | l=option(TLocal) TIdExpression ty=ioption(meta_exp_type)
367 { (fun arity name pure check_meta constraints ->
370 !Data.add_idexp_meta ty name constraints pure;
371 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
373 !Data.add_local_idexp_meta ty name constraints pure;
374 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
375 | l=option(TLocal) TIdExpression m=nonempty_list(TMul)
376 { (fun arity name pure check_meta constraints ->
377 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
380 !Data.add_idexp_meta ty name constraints pure;
381 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
383 !Data.add_local_idexp_meta ty name constraints pure;
384 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
385 | TExpression m=nonempty_list(TMul)
386 { (fun arity name pure check_meta constraints ->
387 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
388 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
389 !Data.add_exp_meta ty name constraints pure; tok) }
390 | vl=meta_exp_type TOCro TCCro
391 { (fun arity name pure check_meta constraints ->
392 let ty = Some (List.map (function x -> Type_cocci.Array x) vl) in
393 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
394 !Data.add_exp_meta ty name constraints pure; tok) }
395 | TConstant ty=ioption(meta_exp_type)
396 { (fun arity name pure check_meta constraints ->
397 let tok = check_meta(Ast.MetaConstDecl(arity,name,ty)) in
398 !Data.add_const_meta ty name constraints pure; tok) }
400 %inline metakind_atomic_expe:
402 { (fun arity name pure check_meta constraints ->
403 let tok = check_meta(Ast.MetaExpDecl(arity,name,None)) in
404 !Data.add_exp_meta None name constraints pure; tok) }
405 | vl=meta_exp_type // no error if use $1 but doesn't type check
406 { (fun arity name pure check_meta constraints ->
410 match Ast0.unwrap c with
415 Type_cocci.BaseType(Type_cocci.IntType,_) -> true
416 | Type_cocci.BaseType(Type_cocci.ShortType,_) -> true
417 | Type_cocci.BaseType(Type_cocci.LongType,_) -> true
420 then failwith "metavariable with int constraint must be an int"
423 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
424 !Data.add_exp_meta ty name constraints pure; tok) }
429 { [Ast0_cocci.ast0_type_to_type t] }
430 | TOBrace t=comma_list(ctype) TCBrace m=list(TMul)
432 (function x -> P.ty_pointerify (Ast0_cocci.ast0_type_to_type x) m)
435 arity: TBang0 { Ast.UNIQUE }
437 | TPlus0 { Ast.MULTI }
438 | /* empty */ { Ast.NONE }
442 { Ast0.wrap(Ast0.ImplicitInt(q)) }
443 | q=ioption(ctype_qualif) ty=Tchar
444 { Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.CharType ty, q)) }
445 | q=ioption(ctype_qualif) ty=Tshort
446 { Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.ShortType ty, q)) }
447 | q=ioption(ctype_qualif) ty=Tint
448 { Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.IntType ty, q)) }
450 { Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.DoubleType t, None)) }
452 { Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.FloatType t, None)) }
453 | q=ioption(ctype_qualif) ty=Tlong
454 { Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.LongType ty, q)) }
455 | s=struct_or_union i=ident
456 { Ast0.wrap(Ast0.StructUnionName(s, Some i)) }
457 | s=struct_or_union i=ioption(ident)
458 l=TOBrace d=struct_decl_list r=TCBrace
459 { (if i = None && !Data.in_iso
460 then failwith "structures must be named in the iso file");
461 Ast0.wrap(Ast0.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)),
463 d, P.clt2mcode "}" r)) }
464 | s=TMetaType l=TOBrace d=struct_decl_list r=TCBrace
465 { let (nm,pure,clt) = s in
467 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) in
469 (Ast0.StructUnionDef(ty,P.clt2mcode "{" l,d,P.clt2mcode "}" r)) }
470 | r=TRuleName TDot p=TIdent
471 { let nm = (r,P.id2name p) in
472 (* this is only possible when we are in a metavar decl. Otherwise,
473 it will be represented already as a MetaType *)
474 let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in
475 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p),
476 Ast0.Impure (*will be ignored*))) }
478 { Ast0.wrap(Ast0.TypeName(P.id2mcode p)) }
480 { let (nm,pure,clt) = p in
481 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
484 s=Tstruct { P.clt2mcode Ast.Struct s }
485 | u=Tunion { P.clt2mcode Ast.Union u }
489 | t=ctype d=d_ident pv=TPtVirg
491 [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
492 | t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
493 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar pv=TPtVirg
497 (Ast0.FunctionPointer
498 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
499 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
500 [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
501 | cv=ioption(const_vol) i=pure_ident d=d_ident pv=TPtVirg
503 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
504 [Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv))] }
507 struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) }
509 struct_decl_list_start:
511 | struct_decl struct_decl_list_start { $1@$2 }
512 | d=edots_when(TEllipsis,struct_decl) r=continue_struct_decl_list
513 { (P.mkddots "..." d)::r }
515 continue_struct_decl_list:
517 | struct_decl struct_decl_list_start { $1@$2 }
521 cv=ioption(const_vol) ty=generic_ctype m=list(TMul)
522 { P.pointerify (P.make_cv cv ty) m }
523 | cv=ioption(const_vol) t=Tvoid m=nonempty_list(TMul)
525 Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.VoidType t, None)) in
526 P.pointerify (P.make_cv cv ty) m }
527 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
529 { let (mids,code) = t in
531 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
534 fn_ctype: // allows metavariables
535 ty=generic_ctype m=list(TMul) { P.pointerify ty m }
536 | t=Tvoid m=list(TMul)
538 (Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.VoidType t, None)))
542 Tunsigned { P.clt2mcode Ast.Unsigned $1 }
543 | Tsigned { P.clt2mcode Ast.Signed $1 }
545 /*****************************************************************************/
547 /* have to inline everything to avoid conflicts? switch to proper
548 declarations, statements, and expressions for the subterms */
552 b=loption(minus_start)
553 ew=loption(error_words)
555 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
556 | code -> Top_level.top_level code }
560 b=loption(plus_start)
561 ew=loption(error_words)
562 { Top_level.top_level (f@b@ew) }
567 ew=loption(error_words)
568 { match f@[b]@ew with
569 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
570 | code -> Top_level.top_level code }
575 ew=loption(error_words)
576 { Top_level.top_level (f@[b]@ew) }
581 (Ast0.FILEINFO(P.id2mcode $1,
587 (Ast0.Include(P.clt2mcode "#include" (P.drop_aft (P.id2clt $1)),
588 let (arity,ln,lln,offset,col,strbef,straft,pos) =
591 (arity,ln,lln,offset,0,strbef,straft,pos) in
593 (Ast.Local (Parse_aux.str2inc (P.id2name $1)))
597 (Ast0.Include(P.clt2mcode "#include" (P.drop_aft (P.id2clt $1)),
598 let (arity,ln,lln,offset,col,strbef,straft,pos) =
601 (arity,ln,lln,offset,0,strbef,straft,pos) in
603 (Ast.NonLocal (Parse_aux.str2inc (P.id2name $1)))
605 | d=defineop t=ctype TLineEnd
606 { let ty = Ast0.wrap(Ast0.TopExp(Ast0.wrap(Ast0.TypeExp(t)))) in
607 d (Ast0.wrap(Ast0.DOTS([ty]))) }
608 | defineop b=toplevel_seq_start(toplevel_after_dots) TLineEnd
612 (match Ast0.unwrap e with
614 [Ast0.rewrap e (Ast0.TopExp(Ast0.set_arg_exp (e1)))]
617 $1 (Ast0.wrap(Ast0.DOTS(body))) }
621 { let (clt,ident) = $1 in
625 (P.clt2mcode "#define" clt,
627 TMetaId((nm,constraints,pure,clt)) ->
628 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
630 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
633 (Semantic_cocci.Semantic
634 "unexpected name for a #define")),
635 Ast0.wrap Ast0.NoParams,
637 | TDefineParam define_param_list_option TCPar
638 { let (clt,ident,parenoff) = $1 in
639 let (arity,line,lline,offset,col,strbef,straft,pos) = clt in
641 P.clt2mcode "(" (arity,line,lline,parenoff,0,[],[],Ast0.NoMetaPos) in
645 (P.clt2mcode "#define" clt,
647 TMetaId((nm,constraints,pure,clt)) ->
648 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
650 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
653 (Semantic_cocci.Semantic
654 "unexpected name for a #define")),
655 Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" $3)),body)) }
657 /* ---------------------------------------------------------------------- */
659 define_param_list: define_param_list_start
661 match Ast0.unwrap x with Ast0.DPcircles(_) -> true | _ -> false in
662 if List.exists circle $1
663 then Ast0.wrap(Ast0.CIRCLES($1))
664 else Ast0.wrap(Ast0.DOTS($1)) }
666 define_param_list_start:
667 ident { [Ast0.wrap(Ast0.DParam $1)] }
668 | ident TComma define_param_list_start
669 { Ast0.wrap(Ast0.DParam $1)::
670 Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $2))::$3 }
671 | d=TEllipsis r=list(dp_comma_args(TEllipsis))
672 { (P.mkdpdots "..." d)::
673 (List.concat (List.map (function x -> x (P.mkdpdots "...")) r)) }
675 dp_comma_args(dotter):
677 { function dot_builder ->
678 [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," c)); dot_builder d] }
680 { function dot_builder ->
681 [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $1));
682 Ast0.wrap(Ast0.DParam $2)] }
684 define_param_list_option: define_param_list { $1 }
685 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
687 /*****************************************************************************/
690 s=ioption(storage) t=ctype
691 id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
696 (Ast0.FunctionType(Some t,
697 P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
698 id, P.clt2mcode ";" pt)) }
699 | s=ioption(storage) t=Tvoid
700 id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
701 { let t = Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.VoidType t, None)) in
706 (Ast0.FunctionType(Some t,
707 P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
708 id, P.clt2mcode ";" pt)) }
713 TFunDecl i=func_ident lp=TOPar d=decl_list(decl) rp=TCPar
714 lb=TOBrace b=fun_start rb=TCBrace
715 { Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()),
717 P.clt2mcode "(" lp, d,
719 P.clt2mcode "{" lb, b,
720 P.clt2mcode "}" rb)) }
727 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
728 raise (Semantic_cocci.Semantic "duplicate storage")
729 with Not_found -> (Ast0.FStorage($1))::$2 }
730 | t=fn_ctype r=fninfo_nt { (Ast0.FType(t))::r }
733 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
734 raise (Semantic_cocci.Semantic "duplicate inline")
735 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
738 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
739 raise (Semantic_cocci.Semantic "multiple attributes")
740 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
747 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
748 raise (Semantic_cocci.Semantic "duplicate storage")
749 with Not_found -> (Ast0.FStorage($1))::$2 }
752 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
753 raise (Semantic_cocci.Semantic "duplicate inline")
754 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
757 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
758 raise (Semantic_cocci.Semantic "duplicate init")
759 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
762 s=Tstatic { P.clt2mcode Ast.Static s }
763 | s=Tauto { P.clt2mcode Ast.Auto s }
764 | s=Tregister { P.clt2mcode Ast.Register s }
765 | s=Textern { P.clt2mcode Ast.Extern s }
767 decl: t=ctype i=ident
768 { Ast0.wrap(Ast0.Param(t, Some i)) }
769 | t=fn_ctype lp=TOPar s=TMul i=ident rp=TCPar
770 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
773 (Ast0.FunctionPointer
774 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
775 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
776 Ast0.wrap(Ast0.Param(fnptr, Some i)) }
778 { let ty = Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.VoidType t, None)) in
779 Ast0.wrap(Ast0.VoidParam(ty)) }
781 { let (nm,pure,clt) = $1 in
782 Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
786 | t=ctype { Ast0.wrap(Ast0.Param(t, None)) }
787 | t=fn_ctype lp=TOPar s=TMul rp=TCPar
788 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
791 (Ast0.FunctionPointer
792 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
793 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
794 Ast0.wrap(Ast0.Param(fnptr, None)) }
797 Tconst { P.clt2mcode Ast.Const $1 }
798 | Tvolatile { P.clt2mcode Ast.Volatile $1 }
800 /*****************************************************************************/
803 includes { $1 } /* shouldn't be allowed to be a single_statement... */
808 | TIf TOPar eexpr TCPar single_statement %prec TIf
809 { P.ifthen $1 $2 $3 $4 $5 }
810 | TIf TOPar eexpr TCPar single_statement TElse single_statement
811 { P.ifthenelse $1 $2 $3 $4 $5 $6 $7 }
812 | TFor TOPar option(eexpr) TPtVirg option(eexpr) TPtVirg
813 option(eexpr) TCPar single_statement
814 { P.forloop $1 $2 $3 $4 $5 $6 $7 $8 $9 }
815 | TWhile TOPar eexpr TCPar single_statement
816 { P.whileloop $1 $2 $3 $4 $5 }
817 | TDo single_statement TWhile TOPar eexpr TCPar TPtVirg
818 { P.doloop $1 $2 $3 $4 $5 $6 $7 }
819 | iter_ident TOPar eexpr_list_option TCPar single_statement
820 { P.iterator $1 $2 $3 $4 $5 }
821 | TSwitch TOPar eexpr TCPar TOBrace list(case_line) TCBrace
822 { P.switch $1 $2 $3 $4 $5 $6 $7 }
823 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
824 | TReturn TPtVirg { P.ret $1 $2 }
825 | TBreak TPtVirg { P.break $1 $2 }
826 | TContinue TPtVirg { P.cont $1 $2 }
827 | ident TDotDot { P.label $1 $2 }
828 | TGoto ident TPtVirg { P.goto $1 $2 $3 }
829 | TOBrace fun_start TCBrace
833 TEllipsis w=list(whenppdecs)
834 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." $1, List.concat w)) }
835 | TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
836 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." $1, b,
837 P.clt2mcode "...>" c, List.concat w, false)) }
838 | TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
839 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." $1, b,
840 P.clt2mcode "...+>" c, List.concat w, true)) }
842 whenppdecs: w=whens(when_start,rule_elem_statement)
845 /* a statement that fits into a single rule_elem. should nests be included?
846 what about statement metavariables? */
849 { Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),$1)) }
850 | expr TPtVirg { P.exp_stm $1 $2 }
851 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
852 | TReturn TPtVirg { P.ret $1 $2 }
853 | TBreak TPtVirg { P.break $1 $2 }
854 | TContinue TPtVirg { P.cont $1 $2 }
855 | TOPar0 midzero_list(rule_elem_statement,rule_elem_statement) TCPar0
856 { let (mids,code) = $2 in
858 (Ast0.Disj(P.clt2mcode "(" $1,
859 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
860 mids, P.clt2mcode ")" $3)) }
862 /* a statement on its own */
865 | TOPar0 midzero_list(statement,statement) TCPar0
866 /* degenerate case, elements are single statements and thus don't
868 { let (mids,code) = $2 in
870 (Ast0.Disj(P.clt2mcode "(" $1,
871 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
872 mids, P.clt2mcode ")" $3)) }
875 TDefault TDotDot fun_start
876 { Ast0.wrap(Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) }
877 | TCase eexpr TDotDot fun_start
878 { Ast0.wrap(Ast0.Case(P.clt2mcode "case" $1,$2,P.clt2mcode ":" $3,$4)) }
880 /* In the following, an identifier as a type is not fully supported. Indeed,
881 the language is ambiguous: what is foo * bar; */
882 /* The AST DisjDecl cannot be generated because it would be ambiguous with
883 a disjunction on a statement with a declaration in each branch */
886 { [Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv))] }
887 | s=ioption(storage) t=ctype d=comma_list(d_ident) pv=TPtVirg
890 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)))
893 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
895 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
896 /* type is a typedef name */
897 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
898 d=comma_list(d_ident) pv=TPtVirg
902 P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
903 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
905 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
906 e=initialize pv=TPtVirg
908 !Data.add_type_name (P.id2name i);
909 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
910 [Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
911 P.clt2mcode ";" pv))] }
912 /* function pointer type */
914 t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
915 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
920 (Ast0.FunctionPointer
921 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
922 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
923 [Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv))] }
924 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
925 { [Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
926 P.clt2mcode ")" $4,P.clt2mcode ";" $5))] }
928 t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
929 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
930 q=TEq e=initialize pv=TPtVirg
934 (Ast0.FunctionPointer
935 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
936 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
937 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
938 | s=Ttypedef t=ctype id=typedef_ident pv=TPtVirg
939 { let s = P.clt2mcode "typedef" s in
940 [Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv))] }
944 { Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv)) }
945 | s=ioption(storage) t=ctype d=d_ident pv=TPtVirg
947 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
949 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
951 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)) }
952 /* type is a typedef name */
953 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
956 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
957 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) }
958 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
959 e=initialize pv=TPtVirg
961 !Data.add_type_name (P.id2name i);
962 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
963 Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
964 P.clt2mcode ";" pv)) }
965 /* function pointer type */
967 t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
968 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
973 (Ast0.FunctionPointer
974 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
975 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
976 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
977 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
978 { Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
979 P.clt2mcode ")" $4,P.clt2mcode ";" $5)) }
981 t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
982 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
983 q=TEq e=initialize pv=TPtVirg
987 (Ast0.FunctionPointer
988 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
989 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
990 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))}
994 ident list(array_dec)
1001 (Ast0.Array(rest,P.clt2mcode "[" l,i,P.clt2mcode "]" r)))
1004 array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
1008 { Ast0.wrap(Ast0.InitExpr($1)) }
1009 | TOBrace initialize_list TCBrace
1010 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1013 (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
1014 P.clt2mcode "}" $2)) }
1017 /*arithexpr and not eexpr because can have ambiguity with comma*/
1018 /*dots and nests probably not allowed at top level, haven't looked into why*/
1019 arith_expr(eexpr,invalid) { Ast0.wrap(Ast0.InitExpr($1)) }
1020 | TOBrace initialize_list TCBrace
1021 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1024 (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
1025 P.clt2mcode "}" $2)) }
1026 /* gccext:, labeled elements */
1027 | TDot ident TEq initialize2
1028 { Ast0.wrap(Ast0.InitGccDotName(P.clt2mcode "." $1,$2,P.clt2mcode "=" $3,$4)) }
1029 | ident TDotDot initialize2
1030 { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
1031 | TOCro eexpr TCCro TEq initialize2
1032 { Ast0.wrap(Ast0.InitGccIndex(P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3,
1033 P.clt2mcode "=" $4,$5)) }
1034 | TOCro eexpr TEllipsis eexpr TCCro TEq initialize2
1035 { Ast0.wrap(Ast0.InitGccRange(P.clt2mcode "[" $1,$2,P.clt2mcode "..." $3,
1036 $4,P.clt2mcode "]" $5,P.clt2mcode "=" $6,$7)) }
1039 initialize_list_start { Ast0.wrap(Ast0.DOTS($1)) }
1041 initialize_list_start:
1042 initialize2 TComma { [$1;Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))] }
1043 | initialize2 TComma initialize_list_start
1044 { $1::Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))::$3 }
1045 | d=edots_when(TEllipsis,initialize)
1046 r=comma_initializers(edots_when(TEllipsis,initialize))
1047 { (P.mkidots "..." d)::
1048 (List.concat(List.map (function x -> x (P.mkidots "...")) r)) }
1050 comma_initializers(dotter):
1052 | d=dotter r=comma_initializers2(dotter)
1053 { (function dot_builder -> [dot_builder d])::r }
1054 | i=initialize2 c=TComma r=comma_initializers(dotter)
1055 { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
1058 comma_initializers2(dotter):
1060 | i=initialize2 c=TComma r=comma_initializers(dotter)
1061 { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
1064 /* a statement that is part of a list */
1067 { let (nm,pure,clt) = $1 in
1068 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1073 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1075 | statement { [$1] }
1076 /* this doesn't allow expressions at top level, because the parser doesn't
1077 know whether there is one. If there is one, this is not sequencible.
1078 If there is not one, then it is. It seems complicated to get around
1079 this at the parser level. We would have to have a check afterwards to
1080 allow this. One case where this would be useful is for a when. Now
1081 we allow a sequence of whens, so one can be on only statements and
1082 one can be on only expressions. */
1083 | TOPar0 t=midzero_list(fun_start,fun_start) TCPar0
1084 { let (mids,code) = t in
1087 match Ast0.unwrap x with Ast0.DOTS([]) -> true | _ -> false)
1091 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, code, mids,
1092 P.clt2mcode ")" $3))] }
1094 /* a statement that is part of a list */
1095 decl_statement_expr:
1097 { let (nm,pure,clt) = $1 in
1098 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1103 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1105 | statement { [$1] }
1106 /* this doesn't allow expressions at top level, because the parser doesn't
1107 know whether there is one. If there is one, this is not sequencible.
1108 If there is not one, then it is. It seems complicated to get around
1109 this at the parser level. We would have to have a check afterwards to
1110 allow this. One case where this would be useful is for a when. Now
1111 we allow a sequence of whens, so one can be on only statements and
1112 one can be on only expressions. */
1113 | TOPar0 t=midzero_list(fun_after_stm,fun_after_dots_or) TCPar0
1114 { let (mids,code) = t in
1115 if List.for_all (function [] -> true | _ -> false) code
1119 List.map (function x -> Ast0.wrap(Ast0.DOTS x)) code in
1120 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, dot_code, mids,
1121 P.clt2mcode ")" $3))] }
1123 /*****************************************************************************/
1125 /* The following cannot contain <... ...> at the top level. This can only
1126 be allowed as an expression when the expression is delimited on both sides
1127 by expression-specific markers. In that case, the rule eexpr is used, which
1128 allows <... ...> anywhere. Hopefully, this will not be too much of a problem
1130 expr: basic_expr(expr,invalid) { $1 }
1131 /* allows ... and nests */
1132 eexpr: basic_expr(eexpr,dot_expressions) { $1 }
1133 /* allows nests but not .... */
1134 dexpr: basic_expr(eexpr,nest_expressions) { $1 }
1137 eexpr { Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))) }
1140 TInvalid { raise (Semantic_cocci.Semantic "not matchable") }
1143 TEllipsis { Ast0.wrap(Ast0.Edots(P.clt2mcode "..." $1,None)) }
1144 | nest_expressions { $1 }
1146 /* not clear what whencode would mean, so just drop it */
1148 TOEllipsis e=expr_dots(TEllipsis) c=TCEllipsis
1149 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." $1,
1150 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1151 P.clt2mcode "...>" c, None, false)) }
1152 | TPOEllipsis e=expr_dots(TEllipsis) c=TPCEllipsis
1153 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
1154 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1155 P.clt2mcode "...+>" c, None, true)) }
1157 //whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
1159 basic_expr(recurser,primary_extra):
1160 assign_expr(recurser,primary_extra) { $1 }
1163 cond_expr(r,pe) { $1 }
1164 | unary_expr(r,pe) TAssign assign_expr_bis
1165 { let (op,clt) = $2 in
1166 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1167 Ast0.set_arg_exp $3,false)) }
1168 | unary_expr(r,pe) TEq assign_expr_bis
1171 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1174 cond_expr(eexpr,dot_expressions) { $1 }
1175 | unary_expr(eexpr,dot_expressions) TAssign assign_expr_bis
1176 { let (op,clt) = $2 in
1177 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1178 Ast0.set_arg_exp $3,false)) }
1179 | unary_expr(eexpr,dot_expressions) TEq assign_expr_bis
1182 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1185 arith_expr(r,pe) { $1 }
1186 | l=arith_expr(r,pe) w=TWhy t=option(eexpr) dd=TDotDot r=cond_expr(r,pe)
1187 { Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
1188 P.clt2mcode ":" dd, r)) }
1191 cast_expr(r,pe) { $1 }
1192 | arith_expr(r,pe) TMul arith_expr(r,pe)
1193 { P.arith_op Ast.Mul $1 $2 $3 }
1194 | arith_expr(r,pe) TDmOp arith_expr(r,pe)
1195 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1196 | arith_expr(r,pe) TPlus arith_expr(r,pe)
1197 { P.arith_op Ast.Plus $1 $2 $3 }
1198 | arith_expr(r,pe) TMinus arith_expr(r,pe)
1199 { P.arith_op Ast.Minus $1 $2 $3 }
1200 | arith_expr(r,pe) TShOp arith_expr(r,pe)
1201 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1202 | arith_expr(r,pe) TLogOp arith_expr(r,pe)
1203 { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
1204 | arith_expr(r,pe) TEqEq arith_expr(r,pe)
1205 { P.logic_op Ast.Eq $1 $2 $3 }
1206 | arith_expr(r,pe) TNotEq arith_expr(r,pe)
1207 { P.logic_op Ast.NotEq $1 $2 $3 }
1208 | arith_expr(r,pe) TAnd arith_expr(r,pe)
1209 { P.arith_op Ast.And $1 $2 $3 }
1210 | arith_expr(r,pe) TOr arith_expr(r,pe)
1211 { P.arith_op Ast.Or $1 $2 $3 }
1212 | arith_expr(r,pe) TXor arith_expr(r,pe)
1213 { P.arith_op Ast.Xor $1 $2 $3 }
1214 | arith_expr(r,pe) TAndLog arith_expr(r,pe)
1215 { P.logic_op Ast.AndLog $1 $2 $3 }
1216 | arith_expr(r,pe) TOrLog arith_expr(r,pe)
1217 { P.logic_op Ast.OrLog $1 $2 $3 }
1220 unary_expr(r,pe) { $1 }
1221 | lp=TOPar t=ctype rp=TCPar e=cast_expr(r,pe)
1222 { Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
1223 P.clt2mcode ")" rp, e)) }
1226 postfix_expr(r,pe) { $1 }
1227 | TInc unary_expr(r,pe)
1228 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
1229 | TDec unary_expr(r,pe)
1230 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
1231 | unary_op unary_expr(r,pe)
1232 { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
1233 | TBang unary_expr(r,pe)
1234 { let mcode = P.clt2mcode Ast.Not $1 in
1235 Ast0.wrap(Ast0.Unary($2, mcode)) }
1236 | TSizeof unary_expr(r,pe)
1237 { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
1238 | s=TSizeof lp=TOPar t=ctype rp=TCPar
1239 { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
1240 P.clt2mcode "(" lp,t,
1241 P.clt2mcode ")" rp)) }
1243 unary_op: TAnd { P.clt2mcode Ast.GetRef $1 }
1244 | TMul { P.clt2mcode Ast.DeRef $1 }
1245 | TPlus { P.clt2mcode Ast.UnPlus $1 }
1246 | TMinus { P.clt2mcode Ast.UnMinus $1 }
1247 | TTilde { P.clt2mcode Ast.Tilde $1 }
1250 primary_expr(r,pe) { $1 }
1251 | postfix_expr(r,pe) TOCro eexpr TCCro
1252 { Ast0.wrap(Ast0.ArrayAccess ($1,P.clt2mcode "[" $2,$3,
1253 P.clt2mcode "]" $4)) }
1254 | postfix_expr(r,pe) TDot ident
1255 { Ast0.wrap(Ast0.RecordAccess($1, P.clt2mcode "." $2, $3)) }
1256 | postfix_expr(r,pe) TPtrOp ident
1257 { Ast0.wrap(Ast0.RecordPtAccess($1, P.clt2mcode "->" $2,
1259 | postfix_expr(r,pe) TInc
1260 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Inc $2)) }
1261 | postfix_expr(r,pe) TDec
1262 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Dec $2)) }
1263 | postfix_expr(r,pe) TOPar eexpr_list_option TCPar
1264 { Ast0.wrap(Ast0.FunCall($1,P.clt2mcode "(" $2,
1266 P.clt2mcode ")" $4)) }
1268 primary_expr(recurser,primary_extra):
1269 func_ident { Ast0.wrap(Ast0.Ident($1)) }
1271 { let (x,clt) = $1 in
1272 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1274 { let (x,clt) = $1 in
1275 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) }
1277 { let (x,clt) = $1 in
1278 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) }
1280 { let (x,clt) = $1 in
1281 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) }
1283 { let (nm,constraints,pure,ty,clt) = $1 in
1285 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
1287 { let (nm,constraints,pure,clt) = $1 in
1288 Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) }
1290 { let (nm,constraints,pure,ty,clt) = $1 in
1292 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
1294 { let (nm,constraints,pure,ty,clt) = $1 in
1296 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
1298 { let (nm,constraints,pure,ty,clt) = $1 in
1300 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) }
1302 { Ast0.wrap(Ast0.Paren(P.clt2mcode "(" $1,$2,
1303 P.clt2mcode ")" $3)) }
1304 | TOPar0 midzero_list(recurser,eexpr) TCPar0
1305 { let (mids,code) = $2 in
1306 Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" $1,
1308 P.clt2mcode ")" $3)) }
1309 | primary_extra { $1 }
1312 r=no_dot_start_end(dexpr,edots_when(dotter,eexpr)) { r }
1315 no_dot_start_end(grammar,dotter):
1316 g=grammar dg=list(pair(dotter,grammar))
1317 { function dot_builder ->
1318 g :: (List.concat(List.map (function (d,g) -> [dot_builder d;g]) dg)) }
1320 /*****************************************************************************/
1326 TRuleName TDot pure_ident { (Some $1,P.id2name $3) }
1328 pure_ident_or_meta_ident:
1329 pure_ident { (None,P.id2name $1) }
1331 | Tlist { (None,"list") }
1332 | TError { (None,"error") }
1333 | TType { (None,"type") }
1335 pure_ident_or_meta_ident_with_not_eq(not_eq):
1336 i=pure_ident_or_meta_ident l=loption(not_eq) { (i,l) }
1341 then failwith "constraints not allowed in iso file");
1342 [Ast0.wrap(Ast0.Id(P.id2mcode i))] }
1343 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1345 then failwith "constraints not allowed in iso file");
1346 List.map (function i -> Ast0.wrap(Ast0.Id(P.id2mcode i))) l }
1351 then failwith "constraints not allowed in iso file");
1352 [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))] }
1353 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1355 then failwith "constraints not allowed in iso file");
1358 Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
1362 TNotEq i=ident_or_const
1364 then failwith "constraints not allowed in iso file");
1366 | TNotEq TOBrace l=comma_list(ident_or_const) TCBrace
1368 then failwith "constraints not allowed in iso file");
1372 i=pure_ident { Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))) }
1374 { let (x,clt) = $1 in
1375 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1380 then failwith "constraints not allowed in iso file");
1382 (None,_) -> failwith "constraint must be an inherited variable"
1383 | (Some rule,name) ->
1384 let i = (rule,name) in
1385 P.check_meta(Ast.MetaPosDecl(Ast.NONE,i));
1387 | TNotEq TOBrace l=comma_list(meta_ident) TCBrace
1389 then failwith "constraints not allowed in iso file");
1393 failwith "constraint must be an inherited variable"
1394 | (Some rule,name) ->
1395 let i = (rule,name) in
1396 P.check_meta(Ast.MetaPosDecl(Ast.NONE,i));
1400 func_ident: pure_ident
1401 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1403 { let (nm,constraints,pure,clt) = $1 in
1404 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1406 { let (nm,constraints,pure,clt) = $1 in
1407 Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
1409 { let (nm,constraints,pure,clt) = $1 in
1411 (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
1414 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1416 { let (nm,constraints,pure,clt) = $1 in
1417 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1421 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1423 { let (nm,constraints,pure,clt) = $1 in
1424 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1428 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1430 { let (nm,constraints,pure,clt) = $1 in
1431 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1435 { Ast0.wrap(Ast0.TypeName(P.id2mcode $1)) }
1437 { let (nm,pure,clt) = $1 in
1438 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
1440 /*****************************************************************************/
1443 decl_list_start(decl)
1445 match Ast0.unwrap x with Ast0.Pcircles(_) -> true | _ -> false in
1446 if List.exists circle $1
1447 then Ast0.wrap(Ast0.CIRCLES($1))
1448 else Ast0.wrap(Ast0.DOTS($1)) }
1450 decl_list_start(decl):
1451 one_dec(decl) { [$1] }
1452 | one_dec(decl) TComma decl_list_start(decl)
1453 { $1::Ast0.wrap(Ast0.PComma(P.clt2mcode "," $2))::$3 }
1454 | TEllipsis list(comma_decls(TEllipsis,decl))
1455 { Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." $1))::
1456 (List.concat(List.map (function x -> x (P.mkpdots "...")) $2)) }
1461 { let (nm,lenname,pure,clt) = $1 in
1462 let nm = P.clt2mcode nm clt in
1465 Some nm -> Some(P.clt2mcode nm clt)
1467 Ast0.wrap(Ast0.MetaParamList(nm,lenname,pure)) }
1469 comma_decls(dotter,decl):
1471 { function dot_builder ->
1472 [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1));
1474 | TComma one_dec(decl)
1475 { function dot_builder ->
1476 [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1)); $2] }
1478 /* ---------------------------------------------------------------------- */
1481 TError TWords TEq TOCro cl=comma_list(dexpr) TCCro
1482 { [Ast0.wrap(Ast0.ERRORWORDS(cl))] }
1484 /* ---------------------------------------------------------------------- */
1485 /* sequences of statements and expressions */
1487 /* There are number of cases that must be considered:
1490 Dots and nests allowed at the beginning or end
1491 Expressions allowed at the beginning or end
1492 One function allowed, by itself
1494 Dots and nests allowed at the beginning or end
1495 Expressions not allowed at the beginning or end
1496 Functions not allowed
1497 3. The body of a nest:
1498 Dots and nests not allowed at the beginning or end
1499 Expressions allowed at the beginning or end
1500 Functions not allowed
1502 Dots and nests not allowed at the beginning but allowed at the end
1503 Expressions allowed at the beginning or end
1504 Functions not allowed
1506 These are implemented by the rules minus_toplevel_sequence,
1507 plus_toplevel_sequence, function_body_sequence, nest_body_sequence, and
1510 /* ------------------------------------------------------------------------ */
1511 /* Minus top level */
1513 /* doesn't allow only ... */
1515 fundecl { [Ast0.wrap(Ast0.DECL($1))] }
1516 | ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1517 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1518 | toplevel_seq_start(toplevel_after_dots_init)
1519 { List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1 }
1521 toplevel_seq_start(after_dots_init):
1522 stm_dots after_dots_init { $1::$2 }
1523 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1524 | decl_statement_expr toplevel_after_stm { $1@$2 }
1526 toplevel_after_dots_init:
1527 TNothing toplevel_after_exp {$2}
1528 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1529 | decl_statement_expr toplevel_after_stm {$1@$2}
1533 | stm_dots toplevel_after_dots {$1::$2}
1535 toplevel_after_dots:
1537 | TNothing toplevel_after_exp {$2}
1538 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1539 | decl_statement_expr toplevel_after_stm {$1@$2}
1543 | stm_dots toplevel_after_dots {$1::$2}
1544 | decl_statement toplevel_after_stm {$1@$2}
1547 TOInit initialize_list TCBrace
1548 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1550 /* ------------------------------------------------------------------------ */
1551 /* Plus top level */
1553 /* does allow only ... also allows multiple top-level functions */
1555 ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1556 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1557 | stm_dots plus_after_dots
1558 { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1559 | expr plus_after_exp
1560 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1561 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1562 | decl_statement_expr plus_after_stm
1563 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1567 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1571 | TNothing plus_after_exp {$2}
1572 | expr plus_after_exp
1573 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1574 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1575 | decl_statement_expr plus_after_stm
1576 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1580 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1581 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1582 | decl_statement plus_after_stm
1583 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1585 /* ------------------------------------------------------------------------ */
1589 fun_after_stm { Ast0.wrap(Ast0.DOTS($1)) }
1593 | stm_dots fun_after_dots {$1::$2}
1594 | decl_statement fun_after_stm {$1@$2}
1598 | TNothing fun_after_exp {$2}
1599 | expr fun_after_exp {Ast0.wrap(Ast0.Exp($1))::$2}
1600 | decl_statement_expr fun_after_stm {$1@$2}
1603 stm_dots fun_after_dots {$1::$2}
1605 /* hack to allow mixing statements and expressions in an or */
1608 | TNothing fun_after_exp_or {$2}
1609 | expr fun_after_exp_or {Ast0.wrap(Ast0.Exp($1))::$2}
1610 | decl_statement_expr fun_after_stm {$1@$2}
1614 | stm_dots fun_after_dots {$1::$2}
1616 /* ------------------------------------------------------------------------ */
1620 nest_after_dots { Ast0.wrap(Ast0.DOTS($1)) }
1623 decl_statement_expr nest_after_stm {$1@$2}
1624 | TNothing nest_after_exp {$2}
1625 | expr nest_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1629 | stm_dots nest_after_dots {$1::$2}
1630 | decl_statement nest_after_stm {$1@$2}
1634 | stm_dots nest_after_dots {$1::$2}
1636 /* ------------------------------------------------------------------------ */
1640 expr toplevel_after_exp
1641 { Ast0.wrap(Ast0.DOTS((Ast0.wrap(Ast0.Exp($1)))::$2)) }
1642 | decl_statement toplevel_after_stm
1643 { Ast0.wrap(Ast0.DOTS($1@$2)) }
1645 /* ---------------------------------------------------------------------- */
1650 match Ast0.unwrap x with Ast0.Ecircles(_) -> true | _ -> false in
1652 match Ast0.unwrap x with Ast0.Estars(_) -> true | _ -> false in
1653 if List.exists circle $1
1654 then Ast0.wrap(Ast0.CIRCLES($1))
1656 if List.exists star $1
1657 then Ast0.wrap(Ast0.STARS($1))
1658 else Ast0.wrap(Ast0.DOTS($1)) }
1660 /* arg expr. may contain a type or a explist metavariable */
1663 { Ast0.set_arg_exp $1 }
1665 { let (nm,lenname,pure,clt) = $1 in
1666 let nm = P.clt2mcode nm clt in
1669 Some nm -> Some(P.clt2mcode nm clt)
1671 Ast0.wrap(Ast0.MetaExprList(nm,lenname,pure)) }
1673 { Ast0.set_arg_exp(Ast0.wrap(Ast0.TypeExp($1))) }
1677 | aexpr TComma eexpr_list_start
1678 { $1::Ast0.wrap(Ast0.EComma(P.clt2mcode "," $2))::$3 }
1682 { function dot_builder ->
1683 [Ast0.wrap(Ast0.EComma(P.clt2mcode "," c)); dot_builder d] }
1685 { function dot_builder ->
1686 [Ast0.wrap(Ast0.EComma(P.clt2mcode "," $1)); $2] }
1688 eexpr_list_option: eexpr_list { $1 }
1689 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
1691 /****************************************************************************/
1693 // non-empty lists - drop separator
1695 separated_nonempty_list(TComma,elem) { $1 }
1697 midzero_list(elem,aft):
1698 a=elem b=list(mzl(aft))
1699 { let (mids,code) = List.split b in (mids,(a::code)) }
1702 a=TMid0 b=elem { (P.clt2mcode "|" a, b) }
1704 edots_when(dotter,when_grammar):
1705 d=dotter { (d,None) }
1706 | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
1708 whens(when_grammar,simple_when_grammar):
1709 TWhen TNotEq w=when_grammar TLineEnd { [Ast0.WhenNot w] }
1710 | TWhen TEq w=simple_when_grammar TLineEnd { [Ast0.WhenAlways w] }
1711 | TWhen comma_list(any_strict) TLineEnd
1712 { List.map (function x -> Ast0.WhenModifier(x)) $2 }
1713 | TWhenTrue TNotEq e = eexpr TLineEnd { [Ast0.WhenNotTrue e] }
1714 | TWhenFalse TNotEq e = eexpr TLineEnd { [Ast0.WhenNotFalse e] }
1717 TAny { Ast.WhenAny }
1718 | TStrict { Ast.WhenStrict }
1719 | TForall { Ast.WhenForall }
1720 | TExists { Ast.WhenExists }
1722 /*****************************************************************************
1725 *****************************************************************************/
1728 TIsoExpression e1=dexpr el=list(iso(dexpr)) EOF
1729 { P.iso_adjust (function x -> Ast0.ExprTag x) e1 el }
1730 | TIsoArgExpression e1=dexpr el=list(iso(dexpr)) EOF
1731 { P.iso_adjust (function x -> Ast0.ArgExprTag x) e1 el }
1732 | TIsoTestExpression e1=dexpr el=list(iso(dexpr)) EOF
1733 { P.iso_adjust (function x -> Ast0.TestExprTag x) e1 el }
1734 | TIsoStatement s1=single_statement sl=list(iso(single_statement)) EOF
1735 { P.iso_adjust (function x -> Ast0.StmtTag x) s1 sl }
1736 | TIsoType t1=ctype tl=list(iso(ctype)) EOF
1737 { P.iso_adjust (function x -> Ast0.TypeCTag x) t1 tl }
1738 | TIsoTopLevel e1=nest_start el=list(iso(nest_start)) EOF
1739 { P.iso_adjust (function x -> Ast0.DotsStmtTag x) e1 el }
1740 | TIsoDeclaration d1=decl_var dl=list(iso(decl_var)) EOF
1741 { let check_one = function
1745 (Semantic_cocci.Semantic
1746 "only one variable per declaration in an isomorphism rule") in
1747 let d1 = check_one d1 in
1751 Common.Left x -> Common.Left(check_one x)
1752 | Common.Right x -> Common.Right(check_one x))
1754 P.iso_adjust (function x -> Ast0.DeclTag x) d1 dl }
1757 TIso t=term { Common.Left t }
1758 | TRightIso t=term { Common.Right t }
1760 /*****************************************************************************
1763 *****************************************************************************/
1765 never_used: TPragma { () }
1766 | TPArob TMetaPos { () }
1767 | TScriptData { () }
1769 script_meta_main: py=pure_ident TShOp TRuleName TDot cocci=pure_ident TMPtVirg
1770 { (P.id2name py, ($3, P.id2name cocci)) }