8172b306ce414f46e014cf1695742860e7811216
[bpt/coccinelle.git] / parsing_cocci / .#parser_cocci_menhir.mly.1.166
1 /*
2 * Copyright 2005-2009, 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.
5 *
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.
9 *
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.
14 *
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/>.
17 *
18 * The authors reserve the right to distribute this or future versions of
19 * Coccinelle under other licenses.
20 */
21
22
23 %{
24
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 *)
29
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
35 module P = Parse_aux
36 %}
37
38 %token EOF
39
40 %token TIdentifier TExpression TStatement TFunction TLocal TType TParameter
41 %token TIdExpression
42 %token Tlist TFresh TConstant TError TWords TWhy0 TPlus0 TBang0
43 %token TPure TContext TGenerated
44 %token TTypedef TDeclarer TIterator TName TPosition TPosAny
45 %token TUsing TDisable TExtends TDepends TOn TEver TNever TExists TForall
46 %token TScript TReverse TNothing
47 %token<string> TRuleName
48
49 %token<Data.clt> Tchar Tshort Tint Tdouble Tfloat Tlong
50 %token<Data.clt> Tvoid Tstruct Tunion Tenum
51 %token<Data.clt> Tunsigned Tsigned
52
53 %token<Data.clt> Tstatic Tauto Tregister Textern Tinline Ttypedef
54 %token<Data.clt> Tconst Tvolatile
55 %token<string * Data.clt> Tattr
56
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
60
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
68
69 %token TArob TArobArob TPArob
70 %token <string> TScriptData
71
72 %token <Data.clt> TEllipsis TOEllipsis TCEllipsis TPOEllipsis TPCEllipsis
73 %token <Data.clt> TWhen TWhenTrue TWhenFalse TAny TStrict TLineEnd
74
75 %token <Data.clt> TWhy TDotDot TBang TOPar TOPar0
76 %token <Data.clt> TMid0 TCPar TCPar0
77
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
83
84 %token <Data.clt> TInc TDec
85
86 %token <string * Data.clt> TString TChar TFloat TInt
87
88 %token <Data.clt> TOrLog
89 %token <Data.clt> TAndLog
90 %token <Data.clt> TOr
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
99
100 %token <Data.clt> TOBrace TCBrace TOInit
101 %token <Data.clt> TOCro TCCro
102
103 %token <Data.clt> TPtrOp
104
105 %token TMPtVirg
106 %token <Data.clt> TEq TDot TComma TPtVirg
107 %token <Ast_cocci.assignOp * Data.clt> TAssign
108
109 %token TIso TRightIso TIsoExpression TIsoStatement TIsoDeclaration TIsoType
110 %token TIsoTopLevel TIsoArgExpression TIsoTestExpression
111
112 %token TInvalid
113
114 /* operator precedence */
115 %nonassoc TIf
116 %nonassoc TElse
117
118 %left TOrLog
119 %left TAndLog
120 %left TOr
121 %left TXor
122 %left TAnd
123 %left TEqEq TNotEq
124 %left TLogOp /* TInf TSup TInfEq TSupEq */
125 %left TShOp /* TShl TShr */
126 %left TPlus TMinus
127 %left TMul TDmOp /* TDiv TMod */
128
129 %start reinit
130 %type <unit> reinit
131
132 %start minus_main
133 %type <Ast0_cocci.rule> minus_main
134
135 %start minus_exp_main
136 %type <Ast0_cocci.rule> minus_exp_main
137
138 %start plus_main
139 %type <Ast0_cocci.rule> plus_main
140
141 %start plus_exp_main
142 %type <Ast0_cocci.rule> plus_exp_main
143
144 %start include_main
145 %type <(string,string) Common.either list> include_main
146
147 %start iso_rule_name
148 %type <Ast_cocci.rulename>
149 iso_rule_name
150
151 %start rule_name
152 %type <Ast_cocci.rulename>
153 rule_name
154
155 %start meta_main
156 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> meta_main
157
158 %start <string * (string * string)> script_meta_main
159
160 %start iso_main
161 %type <Ast0_cocci.anything list list> iso_main
162
163 %start iso_meta_main
164 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> iso_meta_main
165
166 %start never_used
167 %type <unit> never_used
168
169 %%
170
171 reinit: { }
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 "" }
182
183 /*****************************************************************************
184 *
185 *
186 *****************************************************************************/
187
188 pure:
189 TPure { Ast0.Pure }
190 | TContext { Ast0.Context }
191 | TPure TContext { Ast0.PureContext }
192 | TContext TPure { Ast0.PureContext }
193 | /* empty */ { Ast0.Impure }
194
195 iso_rule_name:
196 nm=pure_ident TArob { P.make_iso_rule_name_result (P.id2name nm) }
197
198 rule_name:
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 | TGenerated extends d=depends i=loption(choose_iso)
203 a=loption(disable) e=exists ee=is_expression TArob
204 /* these rules have no name as a cheap way to ensure that no normal
205 rule inherits their metavariables or depends on them */
206 { P.make_generated_rule_name_result None d i a e ee }
207 | TScript TDotDot lang=pure_ident d=depends TArob
208 { P.make_script_rule_name_result lang d }
209
210 extends:
211 /* empty */ { () }
212 | TExtends parent=TRuleName
213 { !Data.install_bindings (parent) }
214
215 depends:
216 /* empty */ { Ast.NoDep }
217 | TDepends TOn parents=dep { parents }
218
219 dep:
220 pnrule { $1 }
221 | dep TAndLog dep { Ast.AndDep($1, $3) }
222 | dep TOrLog dep { Ast.OrDep ($1, $3) }
223
224 pnrule:
225 TRuleName { Ast.Dep $1 }
226 | TBang TRuleName { Ast.AntiDep $2 }
227 | TEver TRuleName { Ast.EverDep $2 }
228 | TNever TRuleName { Ast.NeverDep $2 }
229 | TOPar dep TCPar { $2 }
230
231 choose_iso:
232 TUsing separated_nonempty_list(TComma,TString) { List.map P.id2name $2 }
233
234 disable:
235 TDisable separated_nonempty_list(TComma,pure_ident) { List.map P.id2name $2 }
236
237 exists:
238 TExists { Ast.Exists }
239 | TForall { Ast.Forall }
240 | TReverse TForall { Ast.ReverseForall }
241 | { Ast.Undetermined }
242
243 is_expression: // for more flexible parsing of top level expressions
244 { false }
245 | TExpression { true }
246
247 include_main:
248 list(incl) TArob { $1 }
249 | list(incl) TArobArob { $1 }
250
251 incl:
252 TUsing TString { Common.Left(P.id2name $2) }
253 | TUsing TPathIsoFile { Common.Right $2 }
254
255 metadec:
256 ar=arity ispure=pure
257 kindfn=metakind ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
258 { P.create_metadec ar ispure kindfn ids }
259 | ar=arity ispure=pure
260 kindfn=metakind_atomic
261 ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_eq)) TMPtVirg
262 { P.create_metadec_ne ar ispure kindfn ids }
263 | ar=arity ispure=pure
264 kindfn=metakind_atomic_expi
265 ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_eqe)) TMPtVirg
266 { P.create_metadec_ne ar ispure kindfn ids }
267 | ar=arity ispure=pure
268 kindfn=metakind_atomic_expe
269 ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_ceq)) TMPtVirg
270 { P.create_metadec_ne ar ispure kindfn ids }
271 | ar=arity TPosition a=option(TPosAny)
272 ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_pos)) TMPtVirg
273 (* pb: position variables can't be inherited from normal rules, and then
274 there is no way to inherit from a generated rule, so there is no point
275 to have a position variable *)
276 { (if !Data.in_generating
277 then failwith "position variables not allowed in a generated rule file");
278 let kindfn arity name pure check_meta constraints =
279 let tok = check_meta(Ast.MetaPosDecl(arity,name)) in
280 let any = match a with None -> Ast.PER | Some _ -> Ast.ALL in
281 !Data.add_pos_meta name constraints any; tok in
282 P.create_metadec_ne ar false kindfn ids }
283 | ar=arity ispure=pure
284 TParameter Tlist TOCro id=pure_ident_or_meta_ident TCCro
285 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
286 { P.create_len_metadec ar ispure
287 (fun lenname arity name pure check_meta ->
288 let tok =
289 check_meta(Ast.MetaParamListDecl(arity,name,Some lenname)) in
290 !Data.add_paramlist_meta name (Some lenname) pure; tok)
291 id ids }
292 | ar=arity ispure=pure
293 TExpression Tlist TOCro id=pure_ident_or_meta_ident TCCro
294 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
295 { P.create_len_metadec ar ispure
296 (fun lenname arity name pure check_meta ->
297 let tok =
298 check_meta(Ast.MetaExpListDecl(arity,name,Some lenname)) in
299 !Data.add_explist_meta name (Some lenname) pure; tok)
300 id ids }
301
302 %inline metakind:
303 TFresh TIdentifier
304 { (fun arity name pure check_meta ->
305 let tok = check_meta(Ast.MetaFreshIdDecl(arity,name)) in
306 !Data.add_id_meta name [] pure; tok) }
307 | TParameter
308 { (fun arity name pure check_meta ->
309 let tok = check_meta(Ast.MetaParamDecl(arity,name)) in
310 !Data.add_param_meta name pure; tok) }
311 | TParameter Tlist
312 { (fun arity name pure check_meta ->
313 let tok = check_meta(Ast.MetaParamListDecl(arity,name,None)) in
314 !Data.add_paramlist_meta name None pure; tok) }
315 | TExpression Tlist
316 { (fun arity name pure check_meta ->
317 let tok = check_meta(Ast.MetaExpListDecl(arity,name,None)) in
318 !Data.add_explist_meta name None pure; tok) }
319 | TType
320 { (fun arity name pure check_meta ->
321 let tok = check_meta(Ast.MetaTypeDecl(arity,name)) in
322 !Data.add_type_meta name pure; tok) }
323 | TStatement
324 { (fun arity name pure check_meta ->
325 let tok = check_meta(Ast.MetaStmDecl(arity,name)) in
326 !Data.add_stm_meta name pure; tok) }
327 | TStatement Tlist
328 { (fun arity name pure check_meta ->
329 let tok = check_meta(Ast.MetaStmListDecl(arity,name)) in
330 !Data.add_stmlist_meta name pure; tok) }
331 | TTypedef
332 { (fun arity (_,name) pure check_meta ->
333 if arity = Ast.NONE && pure = Ast0.Impure
334 then (!Data.add_type_name name; [])
335 else raise (Semantic_cocci.Semantic "bad typedef")) }
336 | TDeclarer TName
337 { (fun arity (_,name) pure check_meta ->
338 if arity = Ast.NONE && pure = Ast0.Impure
339 then (!Data.add_declarer_name name; [])
340 else raise (Semantic_cocci.Semantic "bad declarer")) }
341 | TIterator TName
342 { (fun arity (_,name) pure check_meta ->
343 if arity = Ast.NONE && pure = Ast0.Impure
344 then (!Data.add_iterator_name name; [])
345 else raise (Semantic_cocci.Semantic "bad iterator")) }
346
347
348 %inline metakind_atomic:
349 TIdentifier
350 { (fun arity name pure check_meta constraints ->
351 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
352 !Data.add_id_meta name constraints pure; tok) }
353 | TFunction
354 { (fun arity name pure check_meta constraints ->
355 let tok = check_meta(Ast.MetaFuncDecl(arity,name)) in
356 !Data.add_func_meta name constraints pure; tok) }
357 | TLocal TFunction
358 { (fun arity name pure check_meta constraints ->
359 let tok = check_meta(Ast.MetaLocalFuncDecl(arity,name)) in
360 !Data.add_local_func_meta name constraints pure;
361 tok) }
362 | TDeclarer
363 { (fun arity name pure check_meta constraints ->
364 let tok = check_meta(Ast.MetaDeclarerDecl(arity,name)) in
365 !Data.add_declarer_meta name constraints pure; tok) }
366 | TIterator
367 { (fun arity name pure check_meta constraints ->
368 let tok = check_meta(Ast.MetaIteratorDecl(arity,name)) in
369 !Data.add_iterator_meta name constraints pure; tok) }
370
371 %inline metakind_atomic_expi:
372 TError
373 { (fun arity name pure check_meta constraints ->
374 let tok = check_meta(Ast.MetaErrDecl(arity,name)) in
375 !Data.add_err_meta name constraints pure; tok) }
376 | l=option(TLocal) TIdExpression ty=ioption(meta_exp_type)
377 { (fun arity name pure check_meta constraints ->
378 match l with
379 None ->
380 !Data.add_idexp_meta ty name constraints pure;
381 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
382 | Some _ ->
383 !Data.add_local_idexp_meta ty name constraints pure;
384 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
385 | l=option(TLocal) TIdExpression 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 match l with
389 None ->
390 !Data.add_idexp_meta ty name constraints pure;
391 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
392 | Some _ ->
393 !Data.add_local_idexp_meta ty name constraints pure;
394 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
395 | TExpression m=nonempty_list(TMul)
396 { (fun arity name pure check_meta constraints ->
397 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
398 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
399 !Data.add_exp_meta ty name constraints pure; tok) }
400 | vl=meta_exp_type TOCro TCCro
401 { (fun arity name pure check_meta constraints ->
402 let ty = Some (List.map (function x -> Type_cocci.Array x) vl) in
403 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
404 !Data.add_exp_meta ty name constraints pure; tok) }
405 | TConstant ty=ioption(meta_exp_type)
406 { (fun arity name pure check_meta constraints ->
407 let tok = check_meta(Ast.MetaConstDecl(arity,name,ty)) in
408 !Data.add_const_meta ty name constraints pure; tok) }
409
410 %inline metakind_atomic_expe:
411 TExpression
412 { (fun arity name pure check_meta constraints ->
413 let tok = check_meta(Ast.MetaExpDecl(arity,name,None)) in
414 !Data.add_exp_meta None name constraints pure; tok) }
415 | vl=meta_exp_type // no error if use $1 but doesn't type check
416 { (fun arity name pure check_meta constraints ->
417 let ty = Some vl in
418 List.iter
419 (function c ->
420 match Ast0.unwrap c with
421 Ast0.Constant(_) ->
422 if not
423 (List.exists
424 (function
425 Type_cocci.BaseType(Type_cocci.IntType) -> true
426 | Type_cocci.BaseType(Type_cocci.ShortType) -> true
427 | Type_cocci.BaseType(Type_cocci.LongType) -> true
428 | _ -> false)
429 vl)
430 then failwith "metavariable with int constraint must be an int"
431 | _ -> ())
432 constraints;
433 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
434 !Data.add_exp_meta ty name constraints pure; tok) }
435
436
437 meta_exp_type:
438 t=ctype
439 { [Ast0_cocci.ast0_type_to_type t] }
440 | TOBrace t=comma_list(ctype) TCBrace m=list(TMul)
441 { List.map
442 (function x -> P.ty_pointerify (Ast0_cocci.ast0_type_to_type x) m)
443 t }
444
445 arity: TBang0 { Ast.UNIQUE }
446 | TWhy0 { Ast.OPT }
447 | TPlus0 { Ast.MULTI }
448 | /* empty */ { Ast.NONE }
449
450 generic_ctype_full:
451 q=ctype_qualif_opt ty=Tchar
452 { q (Ast0.wrap(Ast0.BaseType(Ast.CharType,[P.clt2mcode "char" ty]))) }
453 | q=ctype_qualif_opt ty=Tshort
454 { q (Ast0.wrap(Ast0.BaseType(Ast.ShortType,[P.clt2mcode "short" ty])))}
455 | q=ctype_qualif_opt ty=Tint
456 { q (Ast0.wrap(Ast0.BaseType(Ast.IntType,[P.clt2mcode "int" ty]))) }
457 | t=Tdouble
458 { Ast0.wrap(Ast0.BaseType(Ast.DoubleType,[P.clt2mcode "double" t])) }
459 | t=Tfloat
460 { Ast0.wrap(Ast0.BaseType(Ast.FloatType,[P.clt2mcode "float" t])) }
461 | q=ctype_qualif_opt ty=Tlong
462 { q (Ast0.wrap(Ast0.BaseType(Ast.LongType,[P.clt2mcode "long" ty]))) }
463 | q=ctype_qualif_opt ty=Tlong ty1=Tlong
464 { q (Ast0.wrap
465 (Ast0.BaseType
466 (Ast.LongLongType,
467 [P.clt2mcode "long" ty;P.clt2mcode "long" ty1]))) }
468 | s=Tenum i=ident
469 { Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, i)) }
470 | s=struct_or_union i=ident
471 { Ast0.wrap(Ast0.StructUnionName(s, Some i)) }
472 | s=struct_or_union i=ioption(ident)
473 l=TOBrace d=struct_decl_list r=TCBrace
474 { (if i = None && !Data.in_iso
475 then failwith "structures must be named in the iso file");
476 Ast0.wrap(Ast0.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)),
477 P.clt2mcode "{" l,
478 d, P.clt2mcode "}" r)) }
479 | s=TMetaType l=TOBrace d=struct_decl_list r=TCBrace
480 { let (nm,pure,clt) = s in
481 let ty =
482 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) in
483 Ast0.wrap
484 (Ast0.StructUnionDef(ty,P.clt2mcode "{" l,d,P.clt2mcode "}" r)) }
485 | r=TRuleName TDot p=TIdent
486 { let nm = (r,P.id2name p) in
487 (* this is only possible when we are in a metavar decl. Otherwise,
488 it will be represented already as a MetaType *)
489 let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in
490 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p),
491 Ast0.Impure (*will be ignored*))) }
492 | p=TTypeId
493 { Ast0.wrap(Ast0.TypeName(P.id2mcode p)) }
494 | q=ctype_qualif_opt p=TMetaType
495 { let (nm,pure,clt) = p in
496 q (Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure))) }
497
498 generic_ctype:
499 q=ctype_qualif { q None }
500 | generic_ctype_full { $1 }
501
502 struct_or_union:
503 s=Tstruct { P.clt2mcode Ast.Struct s }
504 | u=Tunion { P.clt2mcode Ast.Union u }
505
506 struct_decl:
507 TNothing { [] }
508 | t=ctype d=d_ident pv=TPtVirg
509 { let (id,fn) = d in
510 [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
511 | t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
512 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar pv=TPtVirg
513 { let (id,fn) = d in
514 let t =
515 Ast0.wrap
516 (Ast0.FunctionPointer
517 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
518 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
519 [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
520 | cv=ioption(const_vol) i=pure_ident d=d_ident pv=TPtVirg
521 { let (id,fn) = d in
522 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
523 [Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv))] }
524
525 struct_decl_list:
526 struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) }
527
528 struct_decl_list_start:
529 struct_decl { $1 }
530 | struct_decl struct_decl_list_start { $1@$2 }
531 | d=edots_when(TEllipsis,struct_decl) r=continue_struct_decl_list
532 { (P.mkddots "..." d)::r }
533
534 continue_struct_decl_list:
535 /* empty */ { [] }
536 | struct_decl struct_decl_list_start { $1@$2 }
537 | struct_decl { $1 }
538
539 ctype:
540 cv=ioption(const_vol) ty=generic_ctype m=list(TMul)
541 { P.pointerify (P.make_cv cv ty) m }
542 | cv=ioption(const_vol) t=Tvoid m=nonempty_list(TMul)
543 { let ty =
544 Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" t])) in
545 P.pointerify (P.make_cv cv ty) m }
546 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
547 /* more hacks */
548 { let (mids,code) = t in
549 Ast0.wrap
550 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
551
552 ctype_full:
553 cv=ioption(const_vol) ty=generic_ctype_full m=list(TMul)
554 { P.pointerify (P.make_cv cv ty) m }
555 | cv=ioption(const_vol) t=Tvoid m=nonempty_list(TMul)
556 { let ty =
557 Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" t])) in
558 P.pointerify (P.make_cv cv ty) m }
559 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
560 /* more hacks */
561 { let (mids,code) = t in
562 Ast0.wrap
563 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
564
565
566 fn_ctype: // allows metavariables
567 ty=generic_ctype m=list(TMul) { P.pointerify ty m }
568 | t=Tvoid m=list(TMul)
569 { P.pointerify
570 (Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" t])))
571 m }
572
573 %inline ctype_qualif:
574 r=Tunsigned
575 { function x -> Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,x)) }
576 | r=Tsigned
577 { function x -> Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,x)) }
578
579 %inline ctype_qualif_opt:
580 s=ctype_qualif { function x -> s (Some x) }
581 | /* empty */ { function x -> x }
582
583 /*****************************************************************************/
584
585 /* have to inline everything to avoid conflicts? switch to proper
586 declarations, statements, and expressions for the subterms */
587
588 minus_body:
589 f=loption(filespec)
590 b=loption(minus_start)
591 ew=loption(error_words)
592 { match f@b@ew with
593 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
594 | code -> Top_level.top_level code }
595
596 plus_body:
597 f=loption(filespec)
598 b=loption(plus_start)
599 ew=loption(error_words)
600 { Top_level.top_level (f@b@ew) }
601
602 minus_exp_body:
603 f=loption(filespec)
604 b=top_eexpr
605 ew=loption(error_words)
606 { match f@[b]@ew with
607 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
608 | code -> Top_level.top_level code }
609
610 plus_exp_body:
611 f=loption(filespec)
612 b=top_eexpr
613 ew=loption(error_words)
614 { Top_level.top_level (f@[b]@ew) }
615
616 filespec:
617 TMinusFile TPlusFile
618 { [Ast0.wrap
619 (Ast0.FILEINFO(P.id2mcode $1,
620 P.id2mcode $2))] }
621
622 includes:
623 TIncludeL
624 { Ast0.wrap
625 (Ast0.Include(P.clt2mcode "#include" (P.drop_aft (P.id2clt $1)),
626 let (arity,ln,lln,offset,col,strbef,straft,pos) =
627 P.id2clt $1 in
628 let clt =
629 (arity,ln,lln,offset,0,strbef,straft,pos) in
630 P.clt2mcode
631 (Ast.Local (Parse_aux.str2inc (P.id2name $1)))
632 (P.drop_bef clt))) }
633 | TIncludeNL
634 { Ast0.wrap
635 (Ast0.Include(P.clt2mcode "#include" (P.drop_aft (P.id2clt $1)),
636 let (arity,ln,lln,offset,col,strbef,straft,pos) =
637 P.id2clt $1 in
638 let clt =
639 (arity,ln,lln,offset,0,strbef,straft,pos) in
640 P.clt2mcode
641 (Ast.NonLocal (Parse_aux.str2inc (P.id2name $1)))
642 (P.drop_bef clt))) }
643 | d=defineop t=ctype TLineEnd
644 { let ty = Ast0.wrap(Ast0.TopExp(Ast0.wrap(Ast0.TypeExp(t)))) in
645 d (Ast0.wrap(Ast0.DOTS([ty]))) }
646 | defineop b=toplevel_seq_start(toplevel_after_dots) TLineEnd
647 { let body =
648 match b with
649 [e] ->
650 (match Ast0.unwrap e with
651 Ast0.Exp(e1) ->
652 [Ast0.rewrap e (Ast0.TopExp(Ast0.set_arg_exp (e1)))]
653 | _ -> b)
654 | _ -> b in
655 $1 (Ast0.wrap(Ast0.DOTS(body))) }
656
657 defineop:
658 TDefine
659 { let (clt,ident) = $1 in
660 function body ->
661 Ast0.wrap
662 (Ast0.Define
663 (P.clt2mcode "#define" clt,
664 (match ident with
665 TMetaId((nm,constraints,pure,clt)) ->
666 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
667 | TIdent(nm_pure) ->
668 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
669 | _ ->
670 raise
671 (Semantic_cocci.Semantic
672 "unexpected name for a #define")),
673 Ast0.wrap Ast0.NoParams,
674 body)) }
675 | TDefineParam define_param_list_option TCPar
676 { let (clt,ident,parenoff) = $1 in
677 let (arity,line,lline,offset,col,strbef,straft,pos) = clt in
678 let lp =
679 P.clt2mcode "(" (arity,line,lline,parenoff,0,[],[],Ast0.NoMetaPos) in
680 function body ->
681 Ast0.wrap
682 (Ast0.Define
683 (P.clt2mcode "#define" clt,
684 (match ident with
685 TMetaId((nm,constraints,pure,clt)) ->
686 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
687 | TIdent(nm_pure) ->
688 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
689 | _ ->
690 raise
691 (Semantic_cocci.Semantic
692 "unexpected name for a #define")),
693 Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" $3)),body)) }
694
695 /* ---------------------------------------------------------------------- */
696
697 define_param_list: define_param_list_start
698 {let circle x =
699 match Ast0.unwrap x with Ast0.DPcircles(_) -> true | _ -> false in
700 if List.exists circle $1
701 then Ast0.wrap(Ast0.CIRCLES($1))
702 else Ast0.wrap(Ast0.DOTS($1)) }
703
704 define_param_list_start:
705 ident { [Ast0.wrap(Ast0.DParam $1)] }
706 | ident TComma define_param_list_start
707 { Ast0.wrap(Ast0.DParam $1)::
708 Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $2))::$3 }
709 | d=TEllipsis r=list(dp_comma_args(TEllipsis))
710 { (P.mkdpdots "..." d)::
711 (List.concat (List.map (function x -> x (P.mkdpdots "...")) r)) }
712
713 dp_comma_args(dotter):
714 c=TComma d=dotter
715 { function dot_builder ->
716 [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," c)); dot_builder d] }
717 | TComma ident
718 { function dot_builder ->
719 [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $1));
720 Ast0.wrap(Ast0.DParam $2)] }
721
722 define_param_list_option: define_param_list { $1 }
723 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
724
725 /*****************************************************************************/
726
727 funproto:
728 s=ioption(storage) t=ctype
729 id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
730 { Ast0.wrap
731 (Ast0.UnInit
732 (s,
733 Ast0.wrap
734 (Ast0.FunctionType(Some t,
735 P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
736 id, P.clt2mcode ";" pt)) }
737 | s=ioption(storage) t=Tvoid
738 id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
739 { let t = Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" t])) in
740 Ast0.wrap
741 (Ast0.UnInit
742 (s,
743 Ast0.wrap
744 (Ast0.FunctionType(Some t,
745 P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
746 id, P.clt2mcode ";" pt)) }
747
748
749 fundecl:
750 f=fninfo
751 TFunDecl i=func_ident lp=TOPar d=decl_list(decl) rp=TCPar
752 lb=TOBrace b=fun_start rb=TCBrace
753 { Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()),
754 f, i,
755 P.clt2mcode "(" lp, d,
756 P.clt2mcode ")" rp,
757 P.clt2mcode "{" lb, b,
758 P.clt2mcode "}" rb)) }
759
760 fninfo:
761 /* empty */ { [] }
762 | storage fninfo
763 { try
764 let _ =
765 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
766 raise (Semantic_cocci.Semantic "duplicate storage")
767 with Not_found -> (Ast0.FStorage($1))::$2 }
768 | t=fn_ctype r=fninfo_nt { (Ast0.FType(t))::r }
769 | Tinline fninfo
770 { try
771 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
772 raise (Semantic_cocci.Semantic "duplicate inline")
773 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
774 | Tattr fninfo
775 { try
776 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
777 raise (Semantic_cocci.Semantic "multiple attributes")
778 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
779
780 fninfo_nt:
781 /* empty */ { [] }
782 | storage fninfo_nt
783 { try
784 let _ =
785 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
786 raise (Semantic_cocci.Semantic "duplicate storage")
787 with Not_found -> (Ast0.FStorage($1))::$2 }
788 | Tinline fninfo_nt
789 { try
790 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
791 raise (Semantic_cocci.Semantic "duplicate inline")
792 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
793 | Tattr fninfo_nt
794 { try
795 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
796 raise (Semantic_cocci.Semantic "duplicate init")
797 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
798
799 storage:
800 s=Tstatic { P.clt2mcode Ast.Static s }
801 | s=Tauto { P.clt2mcode Ast.Auto s }
802 | s=Tregister { P.clt2mcode Ast.Register s }
803 | s=Textern { P.clt2mcode Ast.Extern s }
804
805 decl: t=ctype i=ident
806 { Ast0.wrap(Ast0.Param(t, Some i)) }
807 | t=fn_ctype lp=TOPar s=TMul i=ident rp=TCPar
808 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
809 { let fnptr =
810 Ast0.wrap
811 (Ast0.FunctionPointer
812 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
813 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
814 Ast0.wrap(Ast0.Param(fnptr, Some i)) }
815 | t=Tvoid
816 { let ty =
817 Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" t])) in
818 Ast0.wrap(Ast0.VoidParam(ty)) }
819 | TMetaParam
820 { let (nm,pure,clt) = $1 in
821 Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
822
823 name_opt_decl:
824 decl { $1 }
825 | t=ctype { Ast0.wrap(Ast0.Param(t, None)) }
826 | t=fn_ctype lp=TOPar s=TMul rp=TCPar
827 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
828 { let fnptr =
829 Ast0.wrap
830 (Ast0.FunctionPointer
831 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
832 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
833 Ast0.wrap(Ast0.Param(fnptr, None)) }
834
835 const_vol:
836 Tconst { P.clt2mcode Ast.Const $1 }
837 | Tvolatile { P.clt2mcode Ast.Volatile $1 }
838
839 /*****************************************************************************/
840
841 statement:
842 includes { $1 } /* shouldn't be allowed to be a single_statement... */
843 | TMetaStm
844 { P.meta_stm $1 }
845 | expr TPtVirg
846 { P.exp_stm $1 $2 }
847 | TIf TOPar eexpr TCPar single_statement %prec TIf
848 { P.ifthen $1 $2 $3 $4 $5 }
849 | TIf TOPar eexpr TCPar single_statement TElse single_statement
850 { P.ifthenelse $1 $2 $3 $4 $5 $6 $7 }
851 | TFor TOPar option(eexpr) TPtVirg option(eexpr) TPtVirg
852 option(eexpr) TCPar single_statement
853 { P.forloop $1 $2 $3 $4 $5 $6 $7 $8 $9 }
854 | TWhile TOPar eexpr TCPar single_statement
855 { P.whileloop $1 $2 $3 $4 $5 }
856 | TDo single_statement TWhile TOPar eexpr TCPar TPtVirg
857 { P.doloop $1 $2 $3 $4 $5 $6 $7 }
858 | iter_ident TOPar eexpr_list_option TCPar single_statement
859 { P.iterator $1 $2 $3 $4 $5 }
860 | TSwitch TOPar eexpr TCPar TOBrace list(case_line) TCBrace
861 { P.switch $1 $2 $3 $4 $5 $6 $7 }
862 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
863 | TReturn TPtVirg { P.ret $1 $2 }
864 | TBreak TPtVirg { P.break $1 $2 }
865 | TContinue TPtVirg { P.cont $1 $2 }
866 | ident TDotDot { P.label $1 $2 }
867 | TGoto ident TPtVirg { P.goto $1 $2 $3 }
868 | TOBrace fun_start TCBrace
869 { P.seq $1 $2 $3 }
870
871 stm_dots:
872 TEllipsis w=list(whenppdecs)
873 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." $1, List.concat w)) }
874 | TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
875 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." $1, b,
876 P.clt2mcode "...>" c, List.concat w, false)) }
877 | TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
878 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." $1, b,
879 P.clt2mcode "...+>" c, List.concat w, true)) }
880
881 %inline stm_dots_ell:
882 a=TEllipsis w=list(whenppdecs)
883 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." a, List.concat w)) }
884
885 %inline stm_dots_nest:
886 a=TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
887 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." a, b,
888 P.clt2mcode "...>" c, List.concat w, false)) }
889 | a=TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
890 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." a, b,
891 P.clt2mcode "...+>" c, List.concat w, true)) }
892
893 whenppdecs: w=whens(when_start,rule_elem_statement)
894 { w }
895
896 /* a statement that fits into a single rule_elem. should nests be included?
897 what about statement metavariables? */
898 rule_elem_statement:
899 one_decl_var
900 { Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),$1)) }
901 | expr TPtVirg { P.exp_stm $1 $2 }
902 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
903 | TReturn TPtVirg { P.ret $1 $2 }
904 | TBreak TPtVirg { P.break $1 $2 }
905 | TContinue TPtVirg { P.cont $1 $2 }
906 | TOPar0 midzero_list(rule_elem_statement,rule_elem_statement) TCPar0
907 { let (mids,code) = $2 in
908 Ast0.wrap
909 (Ast0.Disj(P.clt2mcode "(" $1,
910 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
911 mids, P.clt2mcode ")" $3)) }
912
913 /* a statement on its own */
914 single_statement:
915 statement { $1 }
916 | TOPar0 midzero_list(statement,statement) TCPar0
917 /* degenerate case, elements are single statements and thus don't
918 contain dots */
919 { let (mids,code) = $2 in
920 Ast0.wrap
921 (Ast0.Disj(P.clt2mcode "(" $1,
922 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
923 mids, P.clt2mcode ")" $3)) }
924
925 case_line:
926 TDefault TDotDot fun_start
927 { Ast0.wrap(Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) }
928 | TCase eexpr TDotDot fun_start
929 { Ast0.wrap(Ast0.Case(P.clt2mcode "case" $1,$2,P.clt2mcode ":" $3,$4)) }
930
931 /* In the following, an identifier as a type is not fully supported. Indeed,
932 the language is ambiguous: what is foo * bar; */
933 /* The AST DisjDecl cannot be generated because it would be ambiguous with
934 a disjunction on a statement with a declaration in each branch */
935 decl_var:
936 t=ctype pv=TPtVirg
937 { [Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv))] }
938 | s=ioption(storage) t=ctype d=comma_list(d_ident) pv=TPtVirg
939 { List.map
940 (function (id,fn) ->
941 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)))
942 d }
943 | f=funproto { [f] }
944 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
945 {let (id,fn) = d in
946 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
947 /* type is a typedef name */
948 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
949 d=comma_list(d_ident) pv=TPtVirg
950 { List.map
951 (function (id,fn) ->
952 let idtype =
953 P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
954 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
955 d }
956 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
957 e=initialize pv=TPtVirg
958 { let (id,fn) = d in
959 !Data.add_type_name (P.id2name i);
960 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
961 [Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
962 P.clt2mcode ";" pv))] }
963 /* function pointer type */
964 | s=ioption(storage)
965 t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
966 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
967 pv=TPtVirg
968 { let (id,fn) = d in
969 let t =
970 Ast0.wrap
971 (Ast0.FunctionPointer
972 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
973 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
974 [Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv))] }
975 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
976 { [Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
977 P.clt2mcode ")" $4,P.clt2mcode ";" $5))] }
978 | s=ioption(storage)
979 t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
980 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
981 q=TEq e=initialize pv=TPtVirg
982 { let (id,fn) = d in
983 let t =
984 Ast0.wrap
985 (Ast0.FunctionPointer
986 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
987 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
988 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
989 | s=Ttypedef t=ctype_full id=typedef_ident pv=TPtVirg
990 { let s = P.clt2mcode "typedef" s in
991 [Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv))] }
992
993 one_decl_var:
994 t=ctype pv=TPtVirg
995 { Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv)) }
996 | s=ioption(storage) t=ctype d=d_ident pv=TPtVirg
997 { let (id,fn) = d in
998 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
999 | f=funproto { f }
1000 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
1001 { let (id,fn) = d in
1002 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)) }
1003 /* type is a typedef name */
1004 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
1005 d=d_ident pv=TPtVirg
1006 { let (id,fn) = d in
1007 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1008 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) }
1009 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
1010 e=initialize pv=TPtVirg
1011 { let (id,fn) = d in
1012 !Data.add_type_name (P.id2name i);
1013 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1014 Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1015 P.clt2mcode ";" pv)) }
1016 /* function pointer type */
1017 | s=ioption(storage)
1018 t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1019 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1020 pv=TPtVirg
1021 { let (id,fn) = d in
1022 let t =
1023 Ast0.wrap
1024 (Ast0.FunctionPointer
1025 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1026 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1027 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1028 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1029 { Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
1030 P.clt2mcode ")" $4,P.clt2mcode ";" $5)) }
1031 | s=ioption(storage)
1032 t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1033 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1034 q=TEq e=initialize pv=TPtVirg
1035 { let (id,fn) = d in
1036 let t =
1037 Ast0.wrap
1038 (Ast0.FunctionPointer
1039 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1040 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1041 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))}
1042
1043
1044 d_ident:
1045 ident list(array_dec)
1046 { ($1,
1047 function t ->
1048 List.fold_right
1049 (function (l,i,r) ->
1050 function rest ->
1051 Ast0.wrap
1052 (Ast0.Array(rest,P.clt2mcode "[" l,i,P.clt2mcode "]" r)))
1053 $2 t) }
1054
1055 array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
1056
1057 initialize:
1058 eexpr
1059 { Ast0.wrap(Ast0.InitExpr($1)) }
1060 | TOBrace initialize_list TCBrace
1061 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1062 | TOBrace TCBrace
1063 { Ast0.wrap
1064 (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
1065 P.clt2mcode "}" $2)) }
1066
1067 initialize2:
1068 /*arithexpr and not eexpr because can have ambiguity with comma*/
1069 /*dots and nests probably not allowed at top level, haven't looked into why*/
1070 arith_expr(eexpr,invalid) { Ast0.wrap(Ast0.InitExpr($1)) }
1071 | TOBrace initialize_list TCBrace
1072 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1073 | TOBrace TCBrace
1074 { Ast0.wrap
1075 (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
1076 P.clt2mcode "}" $2)) }
1077 /* gccext:, labeled elements */
1078 | TDot ident TEq initialize2
1079 { Ast0.wrap(Ast0.InitGccDotName(P.clt2mcode "." $1,$2,P.clt2mcode "=" $3,$4)) }
1080 | ident TDotDot initialize2
1081 { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
1082 | TOCro eexpr TCCro TEq initialize2
1083 { Ast0.wrap(Ast0.InitGccIndex(P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3,
1084 P.clt2mcode "=" $4,$5)) }
1085 | TOCro eexpr TEllipsis eexpr TCCro TEq initialize2
1086 { Ast0.wrap(Ast0.InitGccRange(P.clt2mcode "[" $1,$2,P.clt2mcode "..." $3,
1087 $4,P.clt2mcode "]" $5,P.clt2mcode "=" $6,$7)) }
1088
1089 initialize_list:
1090 initialize_list_start { Ast0.wrap(Ast0.DOTS($1)) }
1091
1092 initialize_list_start:
1093 initialize2 TComma { [$1;Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))] }
1094 | initialize2 TComma initialize_list_start
1095 { $1::Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))::$3 }
1096 | d=edots_when(TEllipsis,initialize)
1097 r=comma_initializers(edots_when(TEllipsis,initialize))
1098 { (P.mkidots "..." d)::
1099 (List.concat(List.map (function x -> x (P.mkidots "...")) r)) }
1100
1101 comma_initializers(dotter):
1102 /* empty */ { [] }
1103 | d=dotter r=comma_initializers2(dotter)
1104 { (function dot_builder -> [dot_builder d])::r }
1105 | i=initialize2 c=TComma r=comma_initializers(dotter)
1106 { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
1107 r }
1108
1109 comma_initializers2(dotter):
1110 /* empty */ { [] }
1111 | i=initialize2 c=TComma r=comma_initializers(dotter)
1112 { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
1113 r }
1114
1115 /* a statement that is part of a list */
1116 decl_statement:
1117 TMetaStmList
1118 { let (nm,pure,clt) = $1 in
1119 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1120 | decl_var
1121 { List.map
1122 (function x ->
1123 Ast0.wrap
1124 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1125 $1 }
1126 | statement { [$1] }
1127 /* this doesn't allow expressions at top level, because the parser doesn't
1128 know whether there is one. If there is one, this is not sequencible.
1129 If there is not one, then it is. It seems complicated to get around
1130 this at the parser level. We would have to have a check afterwards to
1131 allow this. One case where this would be useful is for a when. Now
1132 we allow a sequence of whens, so one can be on only statements and
1133 one can be on only expressions. */
1134 | TOPar0 t=midzero_list(fun_start,fun_start) TCPar0
1135 { let (mids,code) = t in
1136 if List.for_all
1137 (function x ->
1138 match Ast0.unwrap x with Ast0.DOTS([]) -> true | _ -> false)
1139 code
1140 then []
1141 else
1142 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, code, mids,
1143 P.clt2mcode ")" $3))] }
1144
1145 /* a statement that is part of a list */
1146 decl_statement_expr:
1147 TMetaStmList
1148 { let (nm,pure,clt) = $1 in
1149 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1150 | decl_var
1151 { List.map
1152 (function x ->
1153 Ast0.wrap
1154 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1155 $1 }
1156 | statement { [$1] }
1157 /* this doesn't allow expressions at top level, because the parser doesn't
1158 know whether there is one. If there is one, this is not sequencible.
1159 If there is not one, then it is. It seems complicated to get around
1160 this at the parser level. We would have to have a check afterwards to
1161 allow this. One case where this would be useful is for a when. Now
1162 we allow a sequence of whens, so one can be on only statements and
1163 one can be on only expressions. */
1164 | TOPar0 t=midzero_list(fun_after_stm,fun_after_dots_or) TCPar0
1165 { let (mids,code) = t in
1166 if List.for_all (function [] -> true | _ -> false) code
1167 then []
1168 else
1169 let dot_code =
1170 List.map (function x -> Ast0.wrap(Ast0.DOTS x)) code in
1171 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, dot_code, mids,
1172 P.clt2mcode ")" $3))] }
1173
1174 /*****************************************************************************/
1175
1176 /* The following cannot contain <... ...> at the top level. This can only
1177 be allowed as an expression when the expression is delimited on both sides
1178 by expression-specific markers. In that case, the rule eexpr is used, which
1179 allows <... ...> anywhere. Hopefully, this will not be too much of a problem
1180 in practice. */
1181 expr: basic_expr(expr,invalid) { $1 }
1182 /* allows ... and nests */
1183 eexpr: basic_expr(eexpr,dot_expressions) { $1 }
1184 /* allows nests but not .... */
1185 dexpr: basic_expr(eexpr,nest_expressions) { $1 }
1186
1187 top_eexpr:
1188 eexpr { Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))) }
1189
1190 invalid:
1191 TInvalid { raise (Semantic_cocci.Semantic "not matchable") }
1192
1193 dot_expressions:
1194 TEllipsis { Ast0.wrap(Ast0.Edots(P.clt2mcode "..." $1,None)) }
1195 | nest_expressions { $1 }
1196
1197 /* not clear what whencode would mean, so just drop it */
1198 nest_expressions:
1199 TOEllipsis e=expr_dots(TEllipsis) c=TCEllipsis
1200 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." $1,
1201 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1202 P.clt2mcode "...>" c, None, false)) }
1203 | TPOEllipsis e=expr_dots(TEllipsis) c=TPCEllipsis
1204 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
1205 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1206 P.clt2mcode "...+>" c, None, true)) }
1207
1208 //whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
1209
1210 basic_expr(recurser,primary_extra):
1211 assign_expr(recurser,primary_extra) { $1 }
1212
1213 assign_expr(r,pe):
1214 cond_expr(r,pe) { $1 }
1215 | unary_expr(r,pe) TAssign assign_expr_bis
1216 { let (op,clt) = $2 in
1217 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1218 Ast0.set_arg_exp $3,false)) }
1219 | unary_expr(r,pe) TEq assign_expr_bis
1220 { Ast0.wrap
1221 (Ast0.Assignment
1222 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1223
1224 assign_expr_bis:
1225 cond_expr(eexpr,dot_expressions) { $1 }
1226 | unary_expr(eexpr,dot_expressions) TAssign assign_expr_bis
1227 { let (op,clt) = $2 in
1228 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1229 Ast0.set_arg_exp $3,false)) }
1230 | unary_expr(eexpr,dot_expressions) TEq assign_expr_bis
1231 { Ast0.wrap
1232 (Ast0.Assignment
1233 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1234
1235 cond_expr(r,pe):
1236 arith_expr(r,pe) { $1 }
1237 | l=arith_expr(r,pe) w=TWhy t=option(eexpr) dd=TDotDot r=cond_expr(r,pe)
1238 { Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
1239 P.clt2mcode ":" dd, r)) }
1240
1241 arith_expr(r,pe):
1242 cast_expr(r,pe) { $1 }
1243 | arith_expr(r,pe) TMul arith_expr(r,pe)
1244 { P.arith_op Ast.Mul $1 $2 $3 }
1245 | arith_expr(r,pe) TDmOp arith_expr(r,pe)
1246 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1247 | arith_expr(r,pe) TPlus arith_expr(r,pe)
1248 { P.arith_op Ast.Plus $1 $2 $3 }
1249 | arith_expr(r,pe) TMinus arith_expr(r,pe)
1250 { P.arith_op Ast.Minus $1 $2 $3 }
1251 | arith_expr(r,pe) TShOp arith_expr(r,pe)
1252 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1253 | arith_expr(r,pe) TLogOp arith_expr(r,pe)
1254 { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
1255 | arith_expr(r,pe) TEqEq arith_expr(r,pe)
1256 { P.logic_op Ast.Eq $1 $2 $3 }
1257 | arith_expr(r,pe) TNotEq arith_expr(r,pe)
1258 { P.logic_op Ast.NotEq $1 $2 $3 }
1259 | arith_expr(r,pe) TAnd arith_expr(r,pe)
1260 { P.arith_op Ast.And $1 $2 $3 }
1261 | arith_expr(r,pe) TOr arith_expr(r,pe)
1262 { P.arith_op Ast.Or $1 $2 $3 }
1263 | arith_expr(r,pe) TXor arith_expr(r,pe)
1264 { P.arith_op Ast.Xor $1 $2 $3 }
1265 | arith_expr(r,pe) TAndLog arith_expr(r,pe)
1266 { P.logic_op Ast.AndLog $1 $2 $3 }
1267 | arith_expr(r,pe) TOrLog arith_expr(r,pe)
1268 { P.logic_op Ast.OrLog $1 $2 $3 }
1269
1270 cast_expr(r,pe):
1271 unary_expr(r,pe) { $1 }
1272 | lp=TOPar t=ctype rp=TCPar e=cast_expr(r,pe)
1273 { Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
1274 P.clt2mcode ")" rp, e)) }
1275
1276 unary_expr(r,pe):
1277 postfix_expr(r,pe) { $1 }
1278 | TInc unary_expr(r,pe)
1279 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
1280 | TDec unary_expr(r,pe)
1281 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
1282 | unary_op unary_expr(r,pe)
1283 { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
1284 | TBang unary_expr(r,pe)
1285 { let mcode = P.clt2mcode Ast.Not $1 in
1286 Ast0.wrap(Ast0.Unary($2, mcode)) }
1287 | TSizeof unary_expr(r,pe)
1288 { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
1289 | s=TSizeof lp=TOPar t=ctype rp=TCPar
1290 { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
1291 P.clt2mcode "(" lp,t,
1292 P.clt2mcode ")" rp)) }
1293
1294 unary_op: TAnd { P.clt2mcode Ast.GetRef $1 }
1295 | TMul { P.clt2mcode Ast.DeRef $1 }
1296 | TPlus { P.clt2mcode Ast.UnPlus $1 }
1297 | TMinus { P.clt2mcode Ast.UnMinus $1 }
1298 | TTilde { P.clt2mcode Ast.Tilde $1 }
1299
1300 postfix_expr(r,pe):
1301 primary_expr(r,pe) { $1 }
1302 | postfix_expr(r,pe) TOCro eexpr TCCro
1303 { Ast0.wrap(Ast0.ArrayAccess ($1,P.clt2mcode "[" $2,$3,
1304 P.clt2mcode "]" $4)) }
1305 | postfix_expr(r,pe) TDot ident
1306 { Ast0.wrap(Ast0.RecordAccess($1, P.clt2mcode "." $2, $3)) }
1307 | postfix_expr(r,pe) TPtrOp ident
1308 { Ast0.wrap(Ast0.RecordPtAccess($1, P.clt2mcode "->" $2,
1309 $3)) }
1310 | postfix_expr(r,pe) TInc
1311 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Inc $2)) }
1312 | postfix_expr(r,pe) TDec
1313 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Dec $2)) }
1314 | postfix_expr(r,pe) TOPar eexpr_list_option TCPar
1315 { Ast0.wrap(Ast0.FunCall($1,P.clt2mcode "(" $2,
1316 $3,
1317 P.clt2mcode ")" $4)) }
1318
1319 primary_expr(recurser,primary_extra):
1320 func_ident { Ast0.wrap(Ast0.Ident($1)) }
1321 | TInt
1322 { let (x,clt) = $1 in
1323 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1324 | TFloat
1325 { let (x,clt) = $1 in
1326 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) }
1327 | TString
1328 { let (x,clt) = $1 in
1329 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) }
1330 | TChar
1331 { let (x,clt) = $1 in
1332 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) }
1333 | TMetaConst
1334 { let (nm,constraints,pure,ty,clt) = $1 in
1335 Ast0.wrap
1336 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
1337 | TMetaErr
1338 { let (nm,constraints,pure,clt) = $1 in
1339 Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) }
1340 | TMetaExp
1341 { let (nm,constraints,pure,ty,clt) = $1 in
1342 Ast0.wrap
1343 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
1344 | TMetaIdExp
1345 { let (nm,constraints,pure,ty,clt) = $1 in
1346 Ast0.wrap
1347 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
1348 | TMetaLocalIdExp
1349 { let (nm,constraints,pure,ty,clt) = $1 in
1350 Ast0.wrap
1351 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) }
1352 | TOPar eexpr TCPar
1353 { Ast0.wrap(Ast0.Paren(P.clt2mcode "(" $1,$2,
1354 P.clt2mcode ")" $3)) }
1355 | TOPar0 midzero_list(recurser,eexpr) TCPar0
1356 { let (mids,code) = $2 in
1357 Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" $1,
1358 code, mids,
1359 P.clt2mcode ")" $3)) }
1360 | primary_extra { $1 }
1361
1362 expr_dots(dotter):
1363 r=no_dot_start_end(dexpr,edots_when(dotter,eexpr)) { r }
1364
1365 // used in NEST
1366 no_dot_start_end(grammar,dotter):
1367 g=grammar dg=list(pair(dotter,grammar))
1368 { function dot_builder ->
1369 g :: (List.concat(List.map (function (d,g) -> [dot_builder d;g]) dg)) }
1370
1371 /*****************************************************************************/
1372
1373 pure_ident:
1374 TIdent { $1 }
1375
1376 meta_ident:
1377 TRuleName TDot pure_ident { (Some $1,P.id2name $3) }
1378
1379 pure_ident_or_meta_ident:
1380 pure_ident { (None,P.id2name $1) }
1381 | meta_ident { $1 }
1382 | Tlist { (None,"list") }
1383 | TError { (None,"error") }
1384 | TType { (None,"type") }
1385 | TName { (None,"name") }
1386
1387 pure_ident_or_meta_ident_with_not_eq(not_eq):
1388 i=pure_ident_or_meta_ident l=loption(not_eq) { (i,l) }
1389
1390 not_eq:
1391 TNotEq i=pure_ident
1392 { (if !Data.in_iso
1393 then failwith "constraints not allowed in iso file");
1394 (if !Data.in_generating
1395 (* pb: constraints not stored with metavars; too lazy to search for
1396 them in the pattern *)
1397 then failwith "constraints not allowed in a generated rule file");
1398 [Ast0.wrap(Ast0.Id(P.id2mcode i))] }
1399 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1400 { (if !Data.in_iso
1401 then failwith "constraints not allowed in iso file");
1402 (if !Data.in_generating
1403 then failwith "constraints not allowed in a generated rule file");
1404 List.map (function i -> Ast0.wrap(Ast0.Id(P.id2mcode i))) l }
1405
1406 not_eqe:
1407 TNotEq i=pure_ident
1408 { (if !Data.in_iso
1409 then failwith "constraints not allowed in iso file");
1410 (if !Data.in_generating
1411 then failwith "constraints not allowed in a generated rule file");
1412 [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))] }
1413 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1414 { (if !Data.in_iso
1415 then failwith "constraints not allowed in iso file");
1416 (if !Data.in_generating
1417 then failwith "constraints not allowed in a generated rule file");
1418 List.map
1419 (function i ->
1420 Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
1421 l }
1422
1423 not_ceq:
1424 TNotEq i=ident_or_const
1425 { (if !Data.in_iso
1426 then failwith "constraints not allowed in iso file");
1427 (if !Data.in_generating
1428 then failwith "constraints not allowed in a generated rule file");
1429 [i] }
1430 | TNotEq TOBrace l=comma_list(ident_or_const) TCBrace
1431 { (if !Data.in_iso
1432 then failwith "constraints not allowed in iso file");
1433 (if !Data.in_generating
1434 then failwith "constraints not allowed in a generated rule file");
1435 l }
1436
1437 ident_or_const:
1438 i=pure_ident { Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))) }
1439 | TInt
1440 { let (x,clt) = $1 in
1441 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1442
1443 not_pos:
1444 TNotEq i=meta_ident
1445 { (if !Data.in_iso
1446 then failwith "constraints not allowed in iso file");
1447 (if !Data.in_generating
1448 then failwith "constraints not allowed in a generated rule file");
1449 match i with
1450 (None,_) -> failwith "constraint must be an inherited variable"
1451 | (Some rule,name) ->
1452 let i = (rule,name) in
1453 P.check_meta(Ast.MetaPosDecl(Ast.NONE,i));
1454 [i] }
1455 | TNotEq TOBrace l=comma_list(meta_ident) TCBrace
1456 { (if !Data.in_iso
1457 then failwith "constraints not allowed in iso file");
1458 (if !Data.in_generating
1459 then failwith "constraints not allowed in a generated rule file");
1460 List.map
1461 (function
1462 (None,_) ->
1463 failwith "constraint must be an inherited variable"
1464 | (Some rule,name) ->
1465 let i = (rule,name) in
1466 P.check_meta(Ast.MetaPosDecl(Ast.NONE,i));
1467 i)
1468 l }
1469
1470 func_ident: pure_ident
1471 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1472 | TMetaId
1473 { let (nm,constraints,pure,clt) = $1 in
1474 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1475 | TMetaFunc
1476 { let (nm,constraints,pure,clt) = $1 in
1477 Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
1478 | TMetaLocalFunc
1479 { let (nm,constraints,pure,clt) = $1 in
1480 Ast0.wrap
1481 (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
1482
1483 ident: pure_ident
1484 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1485 | TMetaId
1486 { let (nm,constraints,pure,clt) = $1 in
1487 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1488
1489 decl_ident:
1490 TDeclarerId
1491 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1492 | TMetaDeclarer
1493 { let (nm,constraints,pure,clt) = $1 in
1494 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1495
1496 iter_ident:
1497 TIteratorId
1498 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1499 | TMetaIterator
1500 { let (nm,constraints,pure,clt) = $1 in
1501 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1502
1503 typedef_ident:
1504 pure_ident
1505 { Ast0.wrap(Ast0.TypeName(P.id2mcode $1)) }
1506 | TMetaType
1507 { let (nm,pure,clt) = $1 in
1508 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
1509
1510 /*****************************************************************************/
1511
1512 decl_list(decl):
1513 decl_list_start(decl)
1514 {let circle x =
1515 match Ast0.unwrap x with Ast0.Pcircles(_) -> true | _ -> false in
1516 if List.exists circle $1
1517 then Ast0.wrap(Ast0.CIRCLES($1))
1518 else Ast0.wrap(Ast0.DOTS($1)) }
1519
1520 decl_list_start(decl):
1521 one_dec(decl) { [$1] }
1522 | one_dec(decl) TComma decl_list_start(decl)
1523 { $1::Ast0.wrap(Ast0.PComma(P.clt2mcode "," $2))::$3 }
1524 | TEllipsis list(comma_decls(TEllipsis,decl))
1525 { Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." $1))::
1526 (List.concat(List.map (function x -> x (P.mkpdots "...")) $2)) }
1527
1528 one_dec(decl):
1529 decl { $1 }
1530 | TMetaParamList
1531 { let (nm,lenname,pure,clt) = $1 in
1532 let nm = P.clt2mcode nm clt in
1533 let lenname =
1534 match lenname with
1535 Some nm -> Some(P.clt2mcode nm clt)
1536 | None -> None in
1537 Ast0.wrap(Ast0.MetaParamList(nm,lenname,pure)) }
1538
1539 comma_decls(dotter,decl):
1540 TComma dotter
1541 { function dot_builder ->
1542 [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1));
1543 dot_builder $2] }
1544 | TComma one_dec(decl)
1545 { function dot_builder ->
1546 [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1)); $2] }
1547
1548 /* ---------------------------------------------------------------------- */
1549
1550 error_words:
1551 TError TWords TEq TOCro cl=comma_list(dexpr) TCCro
1552 { [Ast0.wrap(Ast0.ERRORWORDS(cl))] }
1553
1554 /* ---------------------------------------------------------------------- */
1555 /* sequences of statements and expressions */
1556
1557 /* There are number of cases that must be considered:
1558
1559 1. Top level:
1560 Dots and nests allowed at the beginning or end
1561 Expressions allowed at the beginning or end
1562 One function allowed, by itself
1563 2. A function body:
1564 Dots and nests allowed at the beginning or end
1565 Expressions not allowed at the beginning or end
1566 Functions not allowed
1567 3. The body of a nest:
1568 Dots and nests not allowed at the beginning or end
1569 Expressions allowed at the beginning or end
1570 Functions not allowed
1571 4. Whencode:
1572 Dots and nests not allowed at the beginning but allowed at the end
1573 Expressions allowed at the beginning or end
1574 Functions not allowed
1575
1576 These are implemented by the rules minus_toplevel_sequence,
1577 plus_toplevel_sequence, function_body_sequence, nest_body_sequence, and
1578 when_body_sequence.
1579 */
1580 /* ------------------------------------------------------------------------ */
1581 /* Minus top level */
1582
1583 /* doesn't allow only ... */
1584 minus_start:
1585 fundecl { [Ast0.wrap(Ast0.DECL($1))] }
1586 | ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1587 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1588 | toplevel_seq_startne(toplevel_after_dots_init)
1589 { List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1 }
1590
1591 toplevel_seq_startne(after_dots_init):
1592 a=stm_dots_ell b=after_dots_init { a::b }
1593 | a=stm_dots_nest b=after_dots_init { a::b }
1594 | a=stm_dots_nest { [a] }
1595 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1596 | decl_statement_expr toplevel_after_stm { $1@$2 }
1597
1598 toplevel_seq_start(after_dots_init):
1599 stm_dots after_dots_init { $1::$2 }
1600 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1601 | decl_statement_expr toplevel_after_stm { $1@$2 }
1602
1603 toplevel_after_dots_init:
1604 TNothing toplevel_after_exp {$2}
1605 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1606 | decl_statement_expr toplevel_after_stm {$1@$2}
1607
1608 toplevel_after_exp:
1609 /* empty */ {[]}
1610 | stm_dots toplevel_after_dots {$1::$2}
1611
1612 toplevel_after_dots:
1613 /* empty */ {[]}
1614 | TNothing toplevel_after_exp {$2}
1615 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1616 | decl_statement_expr toplevel_after_stm {$1@$2}
1617
1618 toplevel_after_stm:
1619 /* empty */ {[]}
1620 | stm_dots toplevel_after_dots {$1::$2}
1621 | decl_statement toplevel_after_stm {$1@$2}
1622
1623 top_init:
1624 TOInit initialize_list TCBrace
1625 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1626
1627 /* ------------------------------------------------------------------------ */
1628 /* Plus top level */
1629
1630 /* does allow only ... also allows multiple top-level functions */
1631 plus_start:
1632 ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1633 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1634 | stm_dots plus_after_dots
1635 { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1636 | expr plus_after_exp
1637 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1638 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1639 | decl_statement_expr plus_after_stm
1640 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1641
1642 plus_after_exp:
1643 /* empty */ {[]}
1644 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1645
1646 plus_after_dots:
1647 /* empty */ {[]}
1648 | TNothing plus_after_exp {$2}
1649 | expr plus_after_exp
1650 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1651 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1652 | decl_statement_expr plus_after_stm
1653 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1654
1655 plus_after_stm:
1656 /* empty */ {[]}
1657 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1658 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1659 | decl_statement plus_after_stm
1660 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1661
1662 /* ------------------------------------------------------------------------ */
1663 /* Function body */
1664
1665 fun_start:
1666 fun_after_stm { Ast0.wrap(Ast0.DOTS($1)) }
1667
1668 fun_after_stm:
1669 /* empty */ {[]}
1670 | stm_dots fun_after_dots {$1::$2}
1671 | decl_statement fun_after_stm {$1@$2}
1672
1673 fun_after_dots:
1674 /* empty */ {[]}
1675 | TNothing fun_after_exp {$2}
1676 | expr fun_after_exp {Ast0.wrap(Ast0.Exp($1))::$2}
1677 | decl_statement_expr fun_after_stm {$1@$2}
1678
1679 fun_after_exp:
1680 stm_dots fun_after_dots {$1::$2}
1681
1682 /* hack to allow mixing statements and expressions in an or */
1683 fun_after_dots_or:
1684 /* empty */ {[]}
1685 | TNothing fun_after_exp_or {$2}
1686 | expr fun_after_exp_or {Ast0.wrap(Ast0.Exp($1))::$2}
1687 | decl_statement_expr fun_after_stm {$1@$2}
1688
1689 fun_after_exp_or:
1690 /* empty */ {[]}
1691 | stm_dots fun_after_dots {$1::$2}
1692
1693 /* ------------------------------------------------------------------------ */
1694 /* Nest body */
1695
1696 nest_start:
1697 nest_after_dots { Ast0.wrap(Ast0.DOTS($1)) }
1698
1699 nest_after_dots:
1700 decl_statement_expr nest_after_stm {$1@$2}
1701 | TNothing nest_after_exp {$2}
1702 | expr nest_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1703
1704 nest_after_stm:
1705 /* empty */ {[]}
1706 | stm_dots nest_after_dots {$1::$2}
1707 | decl_statement nest_after_stm {$1@$2}
1708
1709 nest_after_exp:
1710 /* empty */ {[]}
1711 | stm_dots nest_after_dots {$1::$2}
1712
1713 /* ------------------------------------------------------------------------ */
1714 /*Whencode*/
1715
1716 when_start:
1717 expr toplevel_after_exp
1718 { Ast0.wrap(Ast0.DOTS((Ast0.wrap(Ast0.Exp($1)))::$2)) }
1719 | decl_statement toplevel_after_stm
1720 { Ast0.wrap(Ast0.DOTS($1@$2)) }
1721
1722 /* ---------------------------------------------------------------------- */
1723
1724 eexpr_list:
1725 eexpr_list_start
1726 {let circle x =
1727 match Ast0.unwrap x with Ast0.Ecircles(_) -> true | _ -> false in
1728 let star x =
1729 match Ast0.unwrap x with Ast0.Estars(_) -> true | _ -> false in
1730 if List.exists circle $1
1731 then Ast0.wrap(Ast0.CIRCLES($1))
1732 else
1733 if List.exists star $1
1734 then Ast0.wrap(Ast0.STARS($1))
1735 else Ast0.wrap(Ast0.DOTS($1)) }
1736
1737 /* arg expr. may contain a type or a explist metavariable */
1738 aexpr:
1739 eexpr
1740 { Ast0.set_arg_exp $1 }
1741 | TMetaExpList
1742 { let (nm,lenname,pure,clt) = $1 in
1743 let nm = P.clt2mcode nm clt in
1744 let lenname =
1745 match lenname with
1746 Some nm -> Some(P.clt2mcode nm clt)
1747 | None -> None in
1748 Ast0.wrap(Ast0.MetaExprList(nm,lenname,pure)) }
1749 | ctype
1750 { Ast0.set_arg_exp(Ast0.wrap(Ast0.TypeExp($1))) }
1751
1752 eexpr_list_start:
1753 aexpr { [$1] }
1754 | aexpr TComma eexpr_list_start
1755 { $1::Ast0.wrap(Ast0.EComma(P.clt2mcode "," $2))::$3 }
1756
1757 comma_args(dotter):
1758 c=TComma d=dotter
1759 { function dot_builder ->
1760 [Ast0.wrap(Ast0.EComma(P.clt2mcode "," c)); dot_builder d] }
1761 | TComma aexpr
1762 { function dot_builder ->
1763 [Ast0.wrap(Ast0.EComma(P.clt2mcode "," $1)); $2] }
1764
1765 eexpr_list_option: eexpr_list { $1 }
1766 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
1767
1768 /****************************************************************************/
1769
1770 // non-empty lists - drop separator
1771 comma_list(elem):
1772 separated_nonempty_list(TComma,elem) { $1 }
1773
1774 midzero_list(elem,aft):
1775 a=elem b=list(mzl(aft))
1776 { let (mids,code) = List.split b in (mids,(a::code)) }
1777
1778 mzl(elem):
1779 a=TMid0 b=elem { (P.clt2mcode "|" a, b) }
1780
1781 edots_when(dotter,when_grammar):
1782 d=dotter { (d,None) }
1783 | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
1784
1785 whens(when_grammar,simple_when_grammar):
1786 TWhen TNotEq w=when_grammar TLineEnd { [Ast0.WhenNot w] }
1787 | TWhen TEq w=simple_when_grammar TLineEnd { [Ast0.WhenAlways w] }
1788 | TWhen comma_list(any_strict) TLineEnd
1789 { List.map (function x -> Ast0.WhenModifier(x)) $2 }
1790 | TWhenTrue TNotEq e = eexpr TLineEnd { [Ast0.WhenNotTrue e] }
1791 | TWhenFalse TNotEq e = eexpr TLineEnd { [Ast0.WhenNotFalse e] }
1792
1793 any_strict:
1794 TAny { Ast.WhenAny }
1795 | TStrict { Ast.WhenStrict }
1796 | TForall { Ast.WhenForall }
1797 | TExists { Ast.WhenExists }
1798
1799 /*****************************************************************************
1800 *
1801 *
1802 *****************************************************************************/
1803
1804 iso_main:
1805 TIsoExpression e1=dexpr el=list(iso(dexpr)) EOF
1806 { P.iso_adjust (function x -> Ast0.ExprTag x) e1 el }
1807 | TIsoArgExpression e1=dexpr el=list(iso(dexpr)) EOF
1808 { P.iso_adjust (function x -> Ast0.ArgExprTag x) e1 el }
1809 | TIsoTestExpression e1=dexpr el=list(iso(dexpr)) EOF
1810 { P.iso_adjust (function x -> Ast0.TestExprTag x) e1 el }
1811 | TIsoStatement s1=single_statement sl=list(iso(single_statement)) EOF
1812 { P.iso_adjust (function x -> Ast0.StmtTag x) s1 sl }
1813 | TIsoType t1=ctype tl=list(iso(ctype)) EOF
1814 { P.iso_adjust (function x -> Ast0.TypeCTag x) t1 tl }
1815 | TIsoTopLevel e1=nest_start el=list(iso(nest_start)) EOF
1816 { P.iso_adjust (function x -> Ast0.DotsStmtTag x) e1 el }
1817 | TIsoDeclaration d1=decl_var dl=list(iso(decl_var)) EOF
1818 { let check_one = function
1819 [x] -> x
1820 | _ ->
1821 raise
1822 (Semantic_cocci.Semantic
1823 "only one variable per declaration in an isomorphism rule") in
1824 let d1 = check_one d1 in
1825 let dl =
1826 List.map
1827 (function
1828 Common.Left x -> Common.Left(check_one x)
1829 | Common.Right x -> Common.Right(check_one x))
1830 dl in
1831 P.iso_adjust (function x -> Ast0.DeclTag x) d1 dl }
1832
1833 iso(term):
1834 TIso t=term { Common.Left t }
1835 | TRightIso t=term { Common.Right t }
1836
1837 /*****************************************************************************
1838 *
1839 *
1840 *****************************************************************************/
1841
1842 never_used: TPragma { () }
1843 | TPArob TMetaPos { () }
1844 | TScriptData { () }
1845
1846 script_meta_main: py=pure_ident TShOp TRuleName TDot cocci=pure_ident TMPtVirg
1847 { (P.id2name py, ($3, P.id2name cocci)) }