| 1 | (* detect statements that are between dots in the minus code, because they |
| 2 | may need a special treatment if they are if branches *) |
| 3 | |
| 4 | module Ast0 = Ast0_cocci |
| 5 | module Ast = Ast_cocci |
| 6 | module V0 = Visitor_ast0 |
| 7 | module VT0 = Visitor_ast0_types |
| 8 | |
| 9 | (* --------------------------------------------------------------------- *) |
| 10 | (* --------------------------------------------------------------------- *) |
| 11 | (* Helpers *) |
| 12 | |
| 13 | let left_dots f l = |
| 14 | match Ast0.undots l with |
| 15 | [] -> false |
| 16 | | x::xs -> f x |
| 17 | |
| 18 | let right_dots f l = |
| 19 | match List.rev (Ast0.undots l) with |
| 20 | [] -> false |
| 21 | | x::xs -> f x |
| 22 | |
| 23 | let modif_before_mcode mc = |
| 24 | match Ast0.get_mcode_mcodekind mc with |
| 25 | Ast0.MINUS mc -> true (*conservative; don't want to hunt right for + code*) |
| 26 | | Ast0.PLUS _ -> failwith "not possible" |
| 27 | | Ast0.CONTEXT mc -> |
| 28 | (match !mc with |
| 29 | (Ast.BEFORE _,_,_) -> true |
| 30 | | (Ast.BEFOREAFTER _,_,_) -> true |
| 31 | | _ -> false) |
| 32 | | Ast0.MIXED mc -> true (* don't think mcode can be mixed *) |
| 33 | |
| 34 | let modif_after_mcodekind = function |
| 35 | Ast0.MINUS mc -> true (*conservative; don't want to hunt right for + code*) |
| 36 | | Ast0.PLUS _ -> failwith "not possible" |
| 37 | | Ast0.CONTEXT mc -> |
| 38 | (match !mc with |
| 39 | (Ast.AFTER _,_,_) -> true |
| 40 | | (Ast.BEFOREAFTER _,_,_) -> true |
| 41 | | _ -> false) |
| 42 | | Ast0.MIXED mc -> true (* don't think mcode can be mixed *) |
| 43 | |
| 44 | let modif_after_mcode mc = modif_after_mcodekind (Ast0.get_mcode_mcodekind mc) |
| 45 | |
| 46 | let any_statements = |
| 47 | List.exists |
| 48 | (List.exists |
| 49 | (function |
| 50 | Ast.StatementTag(_) | Ast.StmtDotsTag(_) |
| 51 | | Ast.DeclarationTag(_) | Ast.DeclDotsTag(_) -> true | _ -> false)) |
| 52 | |
| 53 | let modif_before x = |
| 54 | match Ast0.get_mcodekind x with |
| 55 | Ast0.PLUS _ -> failwith "not possible" |
| 56 | | Ast0.MINUS mc -> |
| 57 | (match !mc with |
| 58 | (* do better for the common case of replacing a stmt by another one *) |
| 59 | ([[Ast.StatementTag(s)]],ti) -> |
| 60 | (match Ast.unwrap s with |
| 61 | Ast.IfThen(_,_,_) -> true (* potentially dangerous *) |
| 62 | | _ -> mc := ([[Ast.StatementTag(s)]],ti); false) |
| 63 | | (_,_) -> true) |
| 64 | | Ast0.CONTEXT mc | Ast0.MIXED mc -> |
| 65 | (match !mc with |
| 66 | (Ast.BEFORE _,_,_) -> true |
| 67 | | (Ast.BEFOREAFTER _,_,_) -> true |
| 68 | | _ -> false) |
| 69 | |
| 70 | let modif_after x = |
| 71 | match Ast0.get_mcodekind x with |
| 72 | Ast0.PLUS _ -> failwith "not possible" |
| 73 | | Ast0.MINUS mc -> |
| 74 | (match !mc with |
| 75 | (* do better for the common case of replacing a stmt by another one *) |
| 76 | ([[Ast.StatementTag(s)]],ti) -> |
| 77 | (match Ast.unwrap s with |
| 78 | Ast.IfThen(_,_,_) -> true (* potentially dangerous *) |
| 79 | | _ -> mc := ([[Ast.StatementTag(s)]],ti); false) |
| 80 | | (l,_) when any_statements l -> true |
| 81 | | (l,ti) -> mc := (l,ti); false) |
| 82 | | Ast0.CONTEXT mc | Ast0.MIXED mc -> |
| 83 | (match !mc with |
| 84 | (Ast.AFTER _,_,_) -> true |
| 85 | | (Ast.BEFOREAFTER _,_,_) -> true |
| 86 | | _ -> false) |
| 87 | |
| 88 | (* Identifier *) |
| 89 | let rec left_ident i = |
| 90 | modif_before i or |
| 91 | match Ast0.unwrap i with |
| 92 | Ast0.Id(name) -> modif_before_mcode name |
| 93 | | Ast0.MetaId(name,_,_) -> modif_before_mcode name |
| 94 | | Ast0.MetaFunc(name,_,_) -> modif_before_mcode name |
| 95 | | Ast0.MetaLocalFunc(name,_,_) -> modif_before_mcode name |
| 96 | | Ast0.OptIdent(id) -> left_ident id |
| 97 | | Ast0.UniqueIdent(id) -> left_ident id |
| 98 | |
| 99 | (* --------------------------------------------------------------------- *) |
| 100 | (* Expression *) |
| 101 | |
| 102 | let rec left_expression e = |
| 103 | modif_before e or |
| 104 | match Ast0.unwrap e with |
| 105 | Ast0.Ident(id) -> left_ident id |
| 106 | | Ast0.Constant(const) -> modif_before_mcode const |
| 107 | | Ast0.FunCall(fn,lp,args,rp) -> left_expression fn |
| 108 | | Ast0.Assignment(left,op,right,_) -> left_expression left |
| 109 | | Ast0.CondExpr(exp1,why,exp2,colon,exp3) -> left_expression exp1 |
| 110 | | Ast0.Postfix(exp,op) -> left_expression exp |
| 111 | | Ast0.Infix(exp,op) -> modif_before_mcode op |
| 112 | | Ast0.Unary(exp,op) -> modif_before_mcode op |
| 113 | | Ast0.Binary(left,op,right) -> left_expression left |
| 114 | | Ast0.Nested(left,op,right) -> left_expression left |
| 115 | | Ast0.Paren(lp,exp,rp) -> modif_before_mcode lp |
| 116 | | Ast0.ArrayAccess(exp1,lb,exp2,rb) -> left_expression exp1 |
| 117 | | Ast0.RecordAccess(exp,pt,field) -> left_expression exp |
| 118 | | Ast0.RecordPtAccess(exp,ar,field) -> left_expression exp |
| 119 | | Ast0.Cast(lp,ty,rp,exp) -> modif_before_mcode lp |
| 120 | | Ast0.SizeOfExpr(szf,exp) -> modif_before_mcode szf |
| 121 | | Ast0.SizeOfType(szf,lp,ty,rp) -> modif_before_mcode szf |
| 122 | | Ast0.TypeExp(ty) -> left_typeC ty |
| 123 | | Ast0.MetaErr(name,_,_) -> modif_before_mcode name |
| 124 | | Ast0.MetaExpr(name,_,ty,_,_) -> modif_before_mcode name |
| 125 | | Ast0.MetaExprList(name,_,_) -> modif_before_mcode name |
| 126 | | Ast0.EComma(cm) -> modif_before_mcode cm |
| 127 | | Ast0.DisjExpr(_,exp_list,_,_) -> List.exists left_expression exp_list |
| 128 | | Ast0.NestExpr(starter,expr_dots,ender,_,multi) -> |
| 129 | left_dots left_expression expr_dots |
| 130 | | Ast0.Edots(dots,_) | Ast0.Ecircles(dots,_) | Ast0.Estars(dots,_) -> false |
| 131 | | Ast0.OptExp(exp) -> left_expression exp |
| 132 | | Ast0.UniqueExp(exp) -> left_expression exp |
| 133 | |
| 134 | (* --------------------------------------------------------------------- *) |
| 135 | (* Types *) |
| 136 | |
| 137 | and left_typeC t = |
| 138 | modif_before t or |
| 139 | match Ast0.unwrap t with |
| 140 | Ast0.ConstVol(cv,ty) -> modif_before_mcode cv |
| 141 | | Ast0.BaseType(ty,strings) -> modif_before_mcode (List.hd strings) |
| 142 | | Ast0.Signed(sgn,ty) -> modif_before_mcode sgn |
| 143 | | Ast0.Pointer(ty,star) -> left_typeC ty |
| 144 | | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) -> left_typeC ty |
| 145 | | Ast0.FunctionType(Some ty,lp1,params,rp1) -> left_typeC ty |
| 146 | | Ast0.FunctionType(None,lp1,params,rp1) -> modif_before_mcode lp1 |
| 147 | | Ast0.Array(ty,lb,size,rb) -> left_typeC ty |
| 148 | | Ast0.EnumName(kind,name) -> modif_before_mcode kind |
| 149 | | Ast0.StructUnionName(kind,name) -> modif_before_mcode kind |
| 150 | | Ast0.StructUnionDef(ty,lb,decls,rb) -> left_typeC ty |
| 151 | | Ast0.TypeName(name) -> modif_before_mcode name |
| 152 | | Ast0.MetaType(name,_) -> modif_before_mcode name |
| 153 | | Ast0.DisjType(lp,types,mids,rp) -> List.exists left_typeC types |
| 154 | | Ast0.OptType(ty) -> left_typeC ty |
| 155 | | Ast0.UniqueType(ty) -> left_typeC ty |
| 156 | |
| 157 | (* --------------------------------------------------------------------- *) |
| 158 | (* Variable declaration *) |
| 159 | (* Even if the Cocci program specifies a list of declarations, they are |
| 160 | split out into multiple declarations of a single variable each. *) |
| 161 | |
| 162 | and left_declaration d = |
| 163 | modif_before d or |
| 164 | match Ast0.unwrap d with |
| 165 | Ast0.Init(Some stg,ty,id,eq,ini,sem) -> modif_before_mcode stg |
| 166 | | Ast0.Init(None,ty,id,eq,ini,sem) -> left_typeC ty |
| 167 | | Ast0.UnInit(Some stg,ty,id,sem) -> modif_before_mcode stg |
| 168 | | Ast0.UnInit(None,ty,id,sem) -> left_typeC ty |
| 169 | | Ast0.MacroDecl(name,lp,args,rp,sem) -> left_ident name |
| 170 | | Ast0.TyDecl(ty,sem) -> left_typeC ty |
| 171 | | Ast0.Typedef(stg,ty,id,sem) -> modif_before_mcode stg |
| 172 | | Ast0.DisjDecl(_,decls,_,_) -> List.exists left_declaration decls |
| 173 | | Ast0.Ddots(dots,_) -> false |
| 174 | | Ast0.OptDecl(decl) -> left_declaration decl |
| 175 | | Ast0.UniqueDecl(decl) -> left_declaration decl |
| 176 | |
| 177 | and right_declaration d = |
| 178 | modif_before d or |
| 179 | match Ast0.unwrap d with |
| 180 | Ast0.Init(_,ty,id,eq,ini,sem) -> modif_after_mcode sem |
| 181 | | Ast0.UnInit(_,ty,id,sem) -> modif_after_mcode sem |
| 182 | | Ast0.MacroDecl(name,lp,args,rp,sem) -> modif_after_mcode sem |
| 183 | | Ast0.TyDecl(ty,sem) -> modif_after_mcode sem |
| 184 | | Ast0.Typedef(stg,ty,id,sem) -> modif_after_mcode sem |
| 185 | | Ast0.DisjDecl(_,decls,_,_) -> List.exists right_declaration decls |
| 186 | | Ast0.Ddots(dots,_) -> false |
| 187 | | Ast0.OptDecl(decl) -> right_declaration decl |
| 188 | | Ast0.UniqueDecl(decl) -> right_declaration decl |
| 189 | |
| 190 | (* --------------------------------------------------------------------- *) |
| 191 | (* Top-level code *) |
| 192 | |
| 193 | and left_statement s = |
| 194 | modif_before s or |
| 195 | match Ast0.unwrap s with |
| 196 | Ast0.FunDecl(_,fninfo,name,lp,params,rp,lbrace,body,rbrace) -> |
| 197 | (* irrelevant *) false |
| 198 | | Ast0.Decl(_,decl) -> left_declaration decl |
| 199 | | Ast0.Seq(lbrace,body,rbrace) -> modif_before_mcode lbrace |
| 200 | | Ast0.ExprStatement(exp,sem) -> left_expression exp |
| 201 | | Ast0.IfThen(iff,lp,exp,rp,branch1,(info,aft)) -> modif_before_mcode iff |
| 202 | | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,(info,aft)) -> |
| 203 | modif_before_mcode iff |
| 204 | | Ast0.While(whl,lp,exp,rp,body,(info,aft)) -> modif_before_mcode whl |
| 205 | | Ast0.Do(d,body,whl,lp,exp,rp,sem) -> modif_before_mcode d |
| 206 | | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,(info,aft)) -> |
| 207 | modif_before_mcode fr |
| 208 | | Ast0.Iterator(nm,lp,args,rp,body,(info,aft)) -> left_ident nm |
| 209 | | Ast0.Switch(switch,lp,exp,rp,lb,decls,cases,rb) -> |
| 210 | modif_before_mcode switch |
| 211 | | Ast0.Break(br,sem) -> modif_before_mcode br |
| 212 | | Ast0.Continue(cont,sem) -> modif_before_mcode cont |
| 213 | | Ast0.Label(l,dd) -> left_ident l |
| 214 | | Ast0.Goto(goto,l,sem) -> modif_before_mcode goto |
| 215 | | Ast0.Return(ret,sem) -> modif_before_mcode ret |
| 216 | | Ast0.ReturnExpr(ret,exp,sem) -> modif_before_mcode ret |
| 217 | | Ast0.MetaStmt(name,pure) -> modif_before_mcode name |
| 218 | | Ast0.MetaStmtList(name,_) -> modif_before_mcode name |
| 219 | | Ast0.Disj(_,statement_dots_list,_,_) -> |
| 220 | List.exists (left_dots left_statement) statement_dots_list |
| 221 | | Ast0.Nest(starter,stmt_dots,ender,whencode,multi) -> |
| 222 | left_dots left_statement stmt_dots |
| 223 | | Ast0.Exp(exp) -> false (* can only be replaced by an expression *) |
| 224 | | Ast0.TopExp(exp) -> false (* as above *) |
| 225 | | Ast0.Ty(ty) -> false (* can only be replaced by a type *) |
| 226 | | Ast0.TopInit(init) -> false (* can only be replaced by an init *) |
| 227 | | Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) -> false |
| 228 | | Ast0.Include(inc,s) -> modif_before_mcode inc |
| 229 | | Ast0.Define(def,id,params,body) -> modif_before_mcode def |
| 230 | | Ast0.OptStm(re) -> left_statement re |
| 231 | | Ast0.UniqueStm(re) -> left_statement re |
| 232 | |
| 233 | and right_statement s = |
| 234 | modif_after s or |
| 235 | match Ast0.unwrap s with |
| 236 | Ast0.FunDecl(_,fninfo,name,lp,params,rp,lbrace,body,rbrace) -> |
| 237 | (* irrelevant *) false |
| 238 | | Ast0.Decl(_,decl) -> right_declaration decl |
| 239 | | Ast0.Seq(lbrace,body,rbrace) -> modif_after_mcode rbrace |
| 240 | | Ast0.ExprStatement(exp,sem) -> modif_after_mcode sem |
| 241 | | Ast0.IfThen(iff,lp,exp,rp,branch1,(info,aft)) -> modif_after_mcodekind aft |
| 242 | | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,(info,aft)) -> |
| 243 | modif_after_mcodekind aft |
| 244 | | Ast0.While(whl,lp,exp,rp,body,(info,aft)) -> modif_after_mcodekind aft |
| 245 | | Ast0.Do(d,body,whl,lp,exp,rp,sem) -> modif_after_mcode sem |
| 246 | | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,(info,aft)) -> |
| 247 | modif_after_mcodekind aft |
| 248 | | Ast0.Iterator(nm,lp,args,rp,body,(info,aft)) -> |
| 249 | modif_after_mcodekind aft |
| 250 | | Ast0.Switch(switch,lp,exp,rp,lb,decls,cases,rb) -> modif_after_mcode rb |
| 251 | | Ast0.Break(br,sem) -> modif_after_mcode sem |
| 252 | | Ast0.Continue(cont,sem) -> modif_after_mcode sem |
| 253 | | Ast0.Label(l,dd) -> modif_after_mcode dd |
| 254 | | Ast0.Goto(goto,l,sem) -> modif_after_mcode sem |
| 255 | | Ast0.Return(ret,sem) -> modif_after_mcode sem |
| 256 | | Ast0.ReturnExpr(ret,exp,sem) -> modif_after_mcode sem |
| 257 | | Ast0.MetaStmt(name,pure) -> modif_after_mcode name |
| 258 | | Ast0.MetaStmtList(name,_) -> modif_after_mcode name |
| 259 | | Ast0.Disj(_,statement_dots_list,_,_) -> |
| 260 | List.exists (right_dots right_statement) statement_dots_list |
| 261 | | Ast0.Nest(starter,stmt_dots,ender,whencode,multi) -> |
| 262 | right_dots right_statement stmt_dots |
| 263 | | Ast0.Exp(exp) -> false (* can only be replaced by an expression *) |
| 264 | | Ast0.TopExp(exp) -> false (* as above *) |
| 265 | | Ast0.Ty(ty) -> false (* can only be replaced by a type *) |
| 266 | | Ast0.TopInit(init) -> false (* can only be replaced by an init *) |
| 267 | | Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) -> false |
| 268 | | Ast0.Include(inc,s) -> modif_after_mcode s |
| 269 | | Ast0.Define(def,id,params,body) -> right_dots right_statement body |
| 270 | | Ast0.OptStm(re) -> right_statement re |
| 271 | | Ast0.UniqueStm(re) -> right_statement re |
| 272 | |
| 273 | (* --------------------------------------------------------------------- *) |
| 274 | |
| 275 | |
| 276 | (* A very coarse approximation. We would really only like to return true |
| 277 | if a new statement is added. For this it would be best to correlate with the |
| 278 | plus slice. Or at least be sure that the new stuff is on the far left or |
| 279 | far right. *) |
| 280 | |
| 281 | let rec adding_something s = |
| 282 | match Ast0.get_mcodekind s with |
| 283 | Ast0.MINUS(mc) -> |
| 284 | (match !mc with |
| 285 | (* do better for the common case of replacing a stmt by another one *) |
| 286 | ([[Ast.StatementTag(s)]],ti) -> |
| 287 | (match Ast.unwrap s with |
| 288 | Ast.IfThen(_,_,_) -> true (* potentially dangerous *) |
| 289 | | _ -> mc := ([[Ast.StatementTag(s)]],ti); false) |
| 290 | | (_,_) -> true) |
| 291 | | Ast0.CONTEXT(mc) -> |
| 292 | let (text,tinfo1,tinfo2) = !mc in |
| 293 | (match text with Ast.NOTHING -> false | _ -> true) |
| 294 | | Ast0.MIXED(_) -> |
| 295 | not(contains_only_minus.VT0.combiner_rec_statement s) (*&& |
| 296 | (left_statement s) or (right_statement s)*) |
| 297 | | _ -> failwith "unexpected plus code" |
| 298 | |
| 299 | (* why do we need this; MINUS should mean the same thing *) |
| 300 | and contains_only_minus = |
| 301 | let bind x y = x && y in |
| 302 | let option_default = true in |
| 303 | let mcodekind = function |
| 304 | Ast0.MINUS(mc) -> |
| 305 | (match !mc with |
| 306 | ([],_) -> true |
| 307 | | _ -> false) |
| 308 | | Ast0.CONTEXT(mc) -> false |
| 309 | | _ -> false in |
| 310 | let mcode (_,_,_,mc,_,_) = mcodekind mc in |
| 311 | |
| 312 | let donothing r k e = mcodekind (Ast0.get_mcodekind e) && k e in |
| 313 | |
| 314 | let dots r k e = |
| 315 | match Ast0.unwrap e with |
| 316 | Ast0.DOTS([]) | Ast0.CIRCLES([]) | Ast0.STARS([]) -> true |
| 317 | | _ -> k e in |
| 318 | |
| 319 | let expression r k e = |
| 320 | mcodekind (Ast0.get_mcodekind e) && |
| 321 | match Ast0.unwrap e with |
| 322 | Ast0.DisjExpr(starter,expr_list,mids,ender) -> |
| 323 | List.for_all r.VT0.combiner_rec_expression expr_list |
| 324 | | _ -> k e in |
| 325 | |
| 326 | let declaration r k e = |
| 327 | mcodekind (Ast0.get_mcodekind e) && |
| 328 | match Ast0.unwrap e with |
| 329 | Ast0.DisjDecl(starter,decls,mids,ender) -> |
| 330 | List.for_all r.VT0.combiner_rec_declaration decls |
| 331 | | _ -> k e in |
| 332 | |
| 333 | let typeC r k e = |
| 334 | mcodekind (Ast0.get_mcodekind e) && |
| 335 | match Ast0.unwrap e with |
| 336 | Ast0.DisjType(starter,types,mids,ender) -> |
| 337 | List.for_all r.VT0.combiner_rec_typeC types |
| 338 | | _ -> k e in |
| 339 | |
| 340 | let statement r k e = |
| 341 | mcodekind (Ast0.get_mcodekind e) && |
| 342 | match Ast0.unwrap e with |
| 343 | Ast0.Disj(starter,statement_dots_list,mids,ender) -> |
| 344 | List.for_all r.VT0.combiner_rec_statement_dots statement_dots_list |
| 345 | | _ -> k e in |
| 346 | |
| 347 | let case_line r k e = |
| 348 | mcodekind (Ast0.get_mcodekind e) && |
| 349 | match Ast0.unwrap e with |
| 350 | Ast0.DisjCase(starter,case_list,mids,ender) -> |
| 351 | List.for_all r.VT0.combiner_rec_case_line case_list |
| 352 | | _ -> k e in |
| 353 | |
| 354 | V0.flat_combiner bind option_default |
| 355 | mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode |
| 356 | dots dots dots dots dots dots |
| 357 | donothing expression typeC donothing donothing declaration |
| 358 | statement case_line donothing |
| 359 | |
| 360 | |
| 361 | (* needs a special case when there is a Disj or an empty DOTS *) |
| 362 | (* ---------------------------------------------------------------------- *) |
| 363 | |
| 364 | (* |
| 365 | Doesn't really work: |
| 366 | |
| 367 | if (acpi_device_dir(device)) |
| 368 | + { |
| 369 | remove_proc_entry(acpi_device_bid(device), acpi_ac_dir); |
| 370 | + acpi_device_dir(device) = NULL; |
| 371 | + } |
| 372 | |
| 373 | The last two + lines get associated with the end of the if, not with the |
| 374 | branch, so the braces get added in oddly. |
| 375 | *) |
| 376 | |
| 377 | let add_braces orig_s = |
| 378 | let s = |
| 379 | (Iso_pattern.rebuild_mcode None).VT0.rebuilder_rec_statement orig_s in |
| 380 | let new_mcodekind = |
| 381 | match Ast0.get_mcodekind s with |
| 382 | Ast0.MINUS(mc) -> |
| 383 | let (text,tinfo) = !mc in |
| 384 | Ast0.MINUS(ref([Ast.mkToken "{"]::text@[[Ast.mkToken "}"]],tinfo)) |
| 385 | | Ast0.CONTEXT(mc) -> |
| 386 | let (text,tinfo1,tinfo2) = !mc in |
| 387 | let new_text = |
| 388 | (* this is going to be a mess if we allow it to be iterable... |
| 389 | there would be one level of braces for every added things. |
| 390 | need to come up with something better, or just add {} in the |
| 391 | source code. *) |
| 392 | match text with |
| 393 | Ast.BEFORE(bef,_) -> |
| 394 | Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,[[Ast.mkToken "}"]], |
| 395 | Ast.ONE) |
| 396 | | Ast.AFTER(aft,_) -> |
| 397 | Ast.BEFOREAFTER([[Ast.mkToken "{"]],aft@[[Ast.mkToken "}"]], |
| 398 | Ast.ONE) |
| 399 | | Ast.BEFOREAFTER(bef,aft,_) -> |
| 400 | Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,aft@[[Ast.mkToken "}"]], |
| 401 | Ast.ONE) |
| 402 | | Ast.NOTHING -> |
| 403 | Ast.BEFOREAFTER([[Ast.mkToken "{"]],[[Ast.mkToken "}"]], |
| 404 | Ast.ONE) in |
| 405 | Ast0.CONTEXT(ref(new_text,tinfo1,tinfo2)) |
| 406 | | Ast0.MIXED(mc) -> |
| 407 | let (text,tinfo1,tinfo2) = !mc in |
| 408 | let new_text = |
| 409 | match text with |
| 410 | Ast.BEFORE(bef,_) -> |
| 411 | Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,[[Ast.mkToken "}"]], |
| 412 | Ast.ONE) |
| 413 | | Ast.AFTER(aft,_) -> |
| 414 | Ast.BEFOREAFTER([[Ast.mkToken "{"]],aft@[[Ast.mkToken "}"]], |
| 415 | Ast.ONE) |
| 416 | | Ast.BEFOREAFTER(bef,aft,_) -> |
| 417 | Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,aft@[[Ast.mkToken "}"]], |
| 418 | Ast.ONE) |
| 419 | | Ast.NOTHING -> |
| 420 | Ast.BEFOREAFTER([[Ast.mkToken "{"]],[[Ast.mkToken "}"]], |
| 421 | Ast.ONE) in |
| 422 | Ast0.MIXED(ref(new_text,tinfo1,tinfo2)) |
| 423 | | _ -> failwith "unexpected plus code" in |
| 424 | Ast0.set_mcodekind s new_mcodekind; |
| 425 | Compute_lines.compute_statement_lines true s |
| 426 | |
| 427 | (* ---------------------------------------------------------------------- *) |
| 428 | |
| 429 | let is_dots x = |
| 430 | match Ast0.unwrap x with |
| 431 | Ast0.Dots(_,_) | Ast0.Circles(_,_) | Ast0.Stars(_,_) |
| 432 | | Ast0.Nest(_,_,_,_,_) -> true |
| 433 | | _ -> false |
| 434 | |
| 435 | let all_minus s = |
| 436 | match Ast0.get_mcodekind s with |
| 437 | Ast0.MINUS(_) -> true |
| 438 | | _ -> false |
| 439 | |
| 440 | let rec unchanged_minus s = |
| 441 | match Ast0.get_mcodekind s with |
| 442 | Ast0.MINUS(mc) -> (match !mc with ([],_) -> true | _ -> false) |
| 443 | | _ -> false |
| 444 | |
| 445 | let rec do_branch s = |
| 446 | if unchanged_minus s |
| 447 | then |
| 448 | Ast0.set_dots_bef_aft s (Ast0.DroppingBetweenDots(add_braces s)) |
| 449 | else |
| 450 | match Ast0.unwrap s with |
| 451 | Ast0.Disj(starter,statement_dots_list,mids,ender) -> |
| 452 | let stmts = |
| 453 | List.map |
| 454 | (function s -> |
| 455 | match Ast0.unwrap s with |
| 456 | Ast0.DOTS([s]) -> |
| 457 | Ast0.rewrap s (Ast0.DOTS([do_branch s])) |
| 458 | | Ast0.DOTS(_) -> s |
| 459 | | _ -> failwith "not supported") |
| 460 | statement_dots_list in |
| 461 | Ast0.rewrap s (Ast0.Disj(starter,stmts,mids,ender)) |
| 462 | | _ -> s |
| 463 | |
| 464 | let rec statement dots_before dots_after s = |
| 465 | let do_one s = |
| 466 | if dots_before && dots_after |
| 467 | then |
| 468 | if unchanged_minus s |
| 469 | then |
| 470 | (let with_braces = add_braces s in |
| 471 | Ast0.set_dots_bef_aft s (Ast0.DroppingBetweenDots(with_braces))) |
| 472 | else if adding_something s |
| 473 | then |
| 474 | (let with_braces = add_braces s in |
| 475 | Ast0.set_dots_bef_aft s (Ast0.AddingBetweenDots(with_braces))) |
| 476 | else s |
| 477 | else s in |
| 478 | |
| 479 | match Ast0.unwrap s with |
| 480 | Ast0.FunDecl(x,fninfo,name,lp,params,rp,lbrace,body,rbrace) -> |
| 481 | (* true for close brace, because that represents any way we can |
| 482 | exit the function, which is not necessarily followed by an explicit |
| 483 | close brace. *) |
| 484 | Ast0.rewrap s |
| 485 | (Ast0.FunDecl(x,fninfo,name,lp,params,rp,lbrace, |
| 486 | statement_dots false true body, |
| 487 | rbrace)) |
| 488 | | Ast0.Decl(_,_) -> s |
| 489 | | Ast0.Seq(lbrace,body,rbrace) -> |
| 490 | Ast0.rewrap s |
| 491 | (Ast0.Seq(lbrace,statement_dots false false body,rbrace)) |
| 492 | | Ast0.ExprStatement(exp,sem) -> do_one s |
| 493 | | Ast0.IfThen(iff,lp,exp,rp,branch1,x) -> |
| 494 | do_one |
| 495 | (Ast0.rewrap s |
| 496 | (Ast0.IfThen(iff,lp,exp,rp,statement false false branch1,x))) |
| 497 | | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,x) -> |
| 498 | do_one |
| 499 | (Ast0.rewrap s |
| 500 | (Ast0.IfThenElse |
| 501 | (iff,lp,exp,rp, |
| 502 | statement false false branch1,els, |
| 503 | statement false false branch2,x))) |
| 504 | | Ast0.While(whl,lp,exp,rp,body,x) -> |
| 505 | do_one |
| 506 | (Ast0.rewrap s |
| 507 | (Ast0.While(whl,lp,exp,rp,statement false false body,x))) |
| 508 | | Ast0.Do(d,body,whl,lp,exp,rp,sem) -> |
| 509 | do_one |
| 510 | (Ast0.rewrap s |
| 511 | (Ast0.Do(d,statement false false body,whl,lp,exp,rp,sem))) |
| 512 | | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,x) -> |
| 513 | do_one |
| 514 | (Ast0.rewrap s |
| 515 | (Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp, |
| 516 | statement false false body,x))) |
| 517 | | Ast0.Iterator(nm,lp,args,rp,body,x) -> |
| 518 | do_one |
| 519 | (Ast0.rewrap s |
| 520 | (Ast0.Iterator(nm,lp,args,rp,statement false false body,x))) |
| 521 | | Ast0.Switch(switch,lp,exp,rp,lb,decls,cases,rb) -> |
| 522 | do_one |
| 523 | (Ast0.rewrap s |
| 524 | (Ast0.Switch(switch,lp,exp,rp,lb,decls, |
| 525 | Ast0.rewrap cases |
| 526 | (Ast0.DOTS |
| 527 | (List.map case_line (Ast0.undots cases))), |
| 528 | rb))) |
| 529 | | Ast0.Break(br,sem) -> do_one s |
| 530 | | Ast0.Continue(cont,sem) -> do_one s |
| 531 | | Ast0.Label(l,dd) -> do_one s |
| 532 | | Ast0.Goto(goto,l,sem) -> do_one s |
| 533 | | Ast0.Return(ret,sem) -> do_one s |
| 534 | | Ast0.ReturnExpr(ret,exp,sem) -> do_one s |
| 535 | | Ast0.MetaStmt(name,_) -> do_one s |
| 536 | | Ast0.MetaStmtList(name,_) -> do_one s |
| 537 | | Ast0.Disj(starter,statement_dots_list,mids,ender) -> |
| 538 | Ast0.rewrap s |
| 539 | (Ast0.Disj(starter, |
| 540 | List.map (statement_dots dots_before dots_after) |
| 541 | statement_dots_list, |
| 542 | mids,ender)) |
| 543 | | Ast0.Nest(starter,stmt_dots,ender,whencode,multi) -> |
| 544 | Ast0.rewrap s |
| 545 | (Ast0.Nest |
| 546 | (starter,statement_dots true true stmt_dots,ender,whencode,multi)) |
| 547 | | Ast0.Exp(exp) -> s |
| 548 | | Ast0.TopExp(exp) -> s |
| 549 | | Ast0.Ty(ty) -> s |
| 550 | | Ast0.TopInit(init) -> s |
| 551 | | Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) -> s |
| 552 | | Ast0.Include(inc,string) -> s (* doesn't affect the need for braces *) |
| 553 | | Ast0.Define(def,id,params,body) -> s (* same as include *) |
| 554 | | Ast0.OptStm(re) -> |
| 555 | Ast0.rewrap s |
| 556 | (Ast0.OptStm(statement dots_before dots_after re)) |
| 557 | | Ast0.UniqueStm(re) -> |
| 558 | Ast0.rewrap s |
| 559 | (Ast0.UniqueStm(statement dots_before dots_after re)) |
| 560 | |
| 561 | and case_line c = |
| 562 | Ast0.rewrap c |
| 563 | (match Ast0.unwrap c with |
| 564 | Ast0.Default(def,colon,code) -> |
| 565 | Ast0.Default(def,colon,statement_dots false false code) |
| 566 | | Ast0.Case(case,exp,colon,code) -> |
| 567 | Ast0.Case(case,exp,colon,statement_dots false false code) |
| 568 | | Ast0.DisjCase(starter,case_lines,mids,ender) -> |
| 569 | Ast0.DisjCase(starter,List.map case_line case_lines,mids,ender) |
| 570 | | Ast0.OptCase(case) -> Ast0.OptCase(case_line c)) |
| 571 | |
| 572 | and do_statement_dots dots_before dots_after = function |
| 573 | [] -> [] |
| 574 | | [x] -> [statement dots_before dots_after x] |
| 575 | | dots::rest when is_dots dots -> |
| 576 | dots::(do_statement_dots true dots_after rest) |
| 577 | | x::(dots::_ as rest) when is_dots dots -> |
| 578 | (statement dots_before true x):: |
| 579 | do_statement_dots false dots_after rest |
| 580 | | x::rest -> |
| 581 | (statement dots_before false x):: |
| 582 | do_statement_dots false dots_after rest |
| 583 | |
| 584 | and statement_dots dots_before dots_after d = |
| 585 | Ast0.rewrap d |
| 586 | (match Ast0.unwrap d with |
| 587 | Ast0.DOTS(l) -> |
| 588 | Ast0.DOTS(do_statement_dots dots_before dots_after l) |
| 589 | | Ast0.CIRCLES(l) -> |
| 590 | Ast0.CIRCLES(do_statement_dots dots_before dots_after l) |
| 591 | | Ast0.STARS(l) -> |
| 592 | Ast0.STARS(do_statement_dots dots_before dots_after l)) |
| 593 | |
| 594 | let top_level t = |
| 595 | Ast0.rewrap t |
| 596 | (match Ast0.unwrap t with |
| 597 | Ast0.DECL(stmt_dots) -> Ast0.DECL(statement true true stmt_dots) |
| 598 | | Ast0.CODE(stmt_dots) -> Ast0.CODE(statement_dots true true stmt_dots) |
| 599 | | t -> t) |
| 600 | |
| 601 | let single_statement l = |
| 602 | if !Flag_parsing_cocci.sgrep_mode then l else List.map top_level l |