Coccinelle release 1.0.0-rc3
[bpt/coccinelle.git] / parsing_c / unparse_hrule.ml
CommitLineData
ae4735db
C
1(*
2 * Copyright (C) 2010, University of Copenhagen DIKU and INRIA.
3 * Copyright (C) 2006, 2007 Julia Lawall
978fd7e5
C
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License (GPL)
7 * version 2 as published by the Free Software Foundation.
ae4735db 8 *
978fd7e5
C
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * file license.txt for more details.
ae4735db 13 *
978fd7e5
C
14 * This file was part of Coccinelle.
15 *)
16
faf9a90c
C
17module Ast = Ast_cocci
18module V = Visitor_ast
34e49164 19
faf9a90c
C
20let error x s =
21 failwith
22 (Printf.sprintf "unparse_hrule: line: %d, %s" (Ast.get_line x) s)
34e49164 23
faf9a90c 24let names = ref ([] : (string * int ref) list)
34e49164 25
0708f913
C
26let started_files = ref ([] : (string * bool) list)
27let typedefs = ref ([] : (string * string list ref) list)
28let current_outfile = ref ""
29
30let prefix = "_cocci_"
31
34e49164
C
32(* ----------------------------------------------------------------------- *)
33(* Create rule to check for header include *)
34
35let print_header_rule pr srcfile =
36 match Str.split (Str.regexp "/") srcfile with
37 [x] ->
0708f913
C
38 pr "@header@\n@@\n\n#include \"";
39 pr x; pr "\"\n\n"; true
34e49164
C
40 | l ->
41 let rec loop = function
42 [] -> false
43 | [x] ->
0708f913
C
44 pr "@header@\n@@\n\n#include \"";
45 pr x; pr "\"\n\n"; true
34e49164
C
46 | "include"::(x::xs) ->
47 pr "@header@\n@@\n\n#include <";
48 let x =
49 if Str.string_match (Str.regexp "asm-") x 0 then "asm" else x in
50 pr (String.concat "/" (x::xs));
51 pr ">\n\n"; true
52 | x::xs -> loop xs in
53 loop l
54
faf9a90c
C
55(* ----------------------------------------------------------------------- *)
56(* Print check that we are not in the defining function *)
57
0708f913 58let print_check_rule pr function_name function_name_count header_req =
faf9a90c 59 (if header_req
0708f913
C
60 then pr (Printf.sprintf "@same_%s depends on header@\n" function_name_count)
61 else pr (Printf.sprintf "@same_%s@\n" function_name_count));
faf9a90c
C
62 pr "position p;\n";
63 pr "@@\n\n";
64 pr function_name; pr "@p(...) { ... }\n\n"
65
66(* ----------------------------------------------------------------------- *)
0708f913 67(* get parameters of the matched function *)
faf9a90c
C
68
69let rec env_lookup fn = function
70 [] -> failwith "no binding"
71 | (nm,vl)::rest when fn nm -> vl
72 | _::rest -> env_lookup fn rest
73
74let get_paramst env =
75 let argname = ref ("","") in
76 let fn ((_,nm) as name) =
77 if nm = "ARGS"
78 then (argname := name; true)
79 else false in
80 match env_lookup fn env with
81 Ast_c.MetaParamListVal(paramst) -> (paramst,!argname)
82 | _ -> failwith "not possible"
83
84let get_function_name rule env =
85 let donothing r k e = k e in
86 let option_default = [] in
87 let bind = Common.union_set in
88 let do_any_list_list r any_list_list =
89 List.fold_left
90 (List.fold_left
91 (function prev -> function cur ->
92 bind (r.V.combiner_anything cur) prev))
93 [] any_list_list in
94 let mcode r mc =
95 match Ast.get_mcodekind mc with
8babbc8f
C
96 Ast.MINUS(_,_,_,any_list_list) ->
97 (match any_list_list with
98 Ast.NOREPLACEMENT -> []
99 | Ast.REPLACEMENT(any_list_list,_) ->
100 do_any_list_list r any_list_list)
faf9a90c
C
101 | Ast.CONTEXT(_,any_befaft) ->
102 (match any_befaft with
951c7801 103 Ast.BEFORE(any_list_list,_) | Ast.AFTER(any_list_list,_) ->
faf9a90c 104 do_any_list_list r any_list_list
951c7801 105 | Ast.BEFOREAFTER(ba,aa,_) ->
faf9a90c
C
106 bind (do_any_list_list r ba) (do_any_list_list r aa)
107 | Ast.NOTHING -> [])
951c7801 108 | Ast.PLUS _ -> [] in
faf9a90c
C
109 let expression r k e =
110 bind (k e)
111 (match Ast.unwrap e with
112 Ast.FunCall(fn,lp,args,rp) ->
113 (match Ast.undots args with
114 [e] ->
115 (match Ast.unwrap e with
116 Ast.MetaExprList(nm,_,_,_) ->
951c7801
C
117 (match (Ast.unwrap_mcode nm,Ast.get_mcodekind nm) with
118 ((_,"ARGS"), Ast.PLUS _) ->
faf9a90c
C
119 (match Ast.unwrap fn with
120 Ast.Ident(id) ->
121 (match Ast.unwrap id with
122 Ast.MetaId(nm,_,_,_)
123 | Ast.MetaFunc(nm,_,_,_)
124 | Ast.MetaLocalFunc(nm,_,_,_) ->
125 [Ast.unwrap_mcode nm]
126 | _ -> [])
127 | _ -> [])
128 | _ -> [])
129 | _ -> [])
130 | _ -> [])
131 | _ -> []) in
132 let names =
133 (V.combiner bind option_default
134 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
c491d8ee 135 donothing donothing donothing donothing donothing
faf9a90c
C
136 donothing expression donothing donothing donothing donothing donothing
137 donothing donothing donothing donothing donothing).V.combiner_top_level
138 rule in
139 match names with
140 [name] ->
141 (match env_lookup (function nm -> nm = name) env with
5636bb2c 142 Ast_c.MetaIdVal(s,_) | Ast_c.MetaFuncVal(s)
faf9a90c
C
143 | Ast_c.MetaLocalFuncVal(s) -> s
144 | _ -> error rule "not possible")
145 | _ -> error rule "inconsistent rule generation"
146
34e49164
C
147(* ----------------------------------------------------------------------- *)
148(* Print metavariable declarations *)
149
0708f913 150let rec print_typedef pr = function
b1b2de81
C
151 (Ast_c.TypeName(name,_),_) ->
152 let s = Ast_c.str_of_name name in
0708f913
C
153 let typedefs =
154 try List.assoc !current_outfile !typedefs
155 with Not_found ->
156 let td = ref [] in
157 typedefs := (!current_outfile,td)::!typedefs;
158 td in
34e49164
C
159 if not (List.mem s !typedefs)
160 then (typedefs := s::!typedefs; pr "typedef "; pr s; pr ";\n")
0708f913 161 | (Ast_c.Pointer(_,ty),_) -> print_typedef pr ty
34e49164
C
162 | _ -> ()
163
faf9a90c
C
164let rewrap_str s ii =
165 {ii with Ast_c.pinfo =
166 (match ii.Ast_c.pinfo with
167 Ast_c.OriginTok pi ->
168 Ast_c.OriginTok { pi with Common.str = s;}
169 | Ast_c.ExpandedTok (pi,vpi) ->
170 Ast_c.ExpandedTok ({ pi with Common.str = s;},vpi)
171 | Ast_c.FakeTok (_,vpi) -> Ast_c.FakeTok (s,vpi)
172 | Ast_c.AbstractLineTok pi ->
173 Ast_c.AbstractLineTok { pi with Common.str = s;})}
174
ae4735db 175let rewrap_prefix_name prefix name =
b1b2de81 176 match name with
ae4735db
C
177 | Ast_c.RegularName (s, iiname) ->
178 let iis = Common.tuple_of_list1 iiname in
b1b2de81
C
179 let iis' = rewrap_str (prefix^s) iis in
180 Ast_c.RegularName (prefix ^ s, [iis'])
ae4735db 181 | Ast_c.CppConcatenatedName _ | Ast_c.CppVariadicName _
b1b2de81
C
182 | Ast_c.CppIdentBuilder _
183 -> raise Common.Todo
184
185
0708f913 186let print_metavar pr = function
b1b2de81
C
187 | {Ast_c.p_namei = Some name;
188 p_type = (_,(Ast_c.Pointer(_,(Ast_c.BaseType(Ast_c.Void),_)),_));
189 }
34e49164 190 ->
b1b2de81 191 let param = Ast_c.str_of_name name in
0708f913 192 pr ("expression "^prefix); pr param
b1b2de81
C
193 | ({Ast_c.p_namei = Some name; p_type = (_,ty)} : Ast_c.parameterType) ->
194
ae4735db 195 let name' = rewrap_prefix_name prefix name in
b1b2de81 196
0708f913 197 print_typedef pr ty;
b1b2de81 198
34e49164
C
199 Pretty_print_c.pp_param_gen
200 (function x ->
201 let str = Ast_c.str_of_info x in
202 if not (List.mem str ["const";"volatile"])
faf9a90c 203 then pr str)
34e49164 204 (function _ -> pr " ")
b1b2de81
C
205 {Ast_c.p_register = (false,[]);
206 p_namei = Some name';
207 p_type = (({Ast_c.const = false; Ast_c.volatile = false},[]),ty)
208 }
34e49164
C
209 | _ -> failwith "function must have named parameters"
210
faf9a90c 211let make_exp = function
b1b2de81 212 ({Ast_c.p_namei = Some name; p_type = ty}, comma_ii) ->
faf9a90c 213 let no_info = (None,Ast_c.NotTest) in
b1b2de81
C
214
215 let name' = rewrap_prefix_name prefix name in
216
faf9a90c 217 let exp =
b1b2de81 218 ((Ast_c.Ident (name'),ref no_info),Ast_c.noii) in
faf9a90c
C
219 (name,(Common.Left exp,comma_ii))
220 | _ -> failwith "bad parameter"
221
0708f913 222let print_extra_typedefs pr env =
faf9a90c
C
223 let bigf =
224 { Visitor_c.default_visitor_c with
ae4735db 225 Visitor_c.ktype = (fun (k, bigf) ty ->
faf9a90c 226 match ty with
0708f913 227 (_,((Ast_c.TypeName(_,_),_) as ty)) -> print_typedef pr ty
faf9a90c
C
228 | _ -> k ty) } in
229 List.iter
230 (function (_,vl) ->
231 match vl with
232 Ast_c.MetaIdVal(_) | Ast_c.MetaFuncVal(_)
233 | Ast_c.MetaLocalFuncVal(_) -> ()
5636bb2c 234 | Ast_c.MetaExprVal(exp,_) -> Visitor_c.vk_expr bigf exp
faf9a90c
C
235 | Ast_c.MetaExprListVal(args) -> Visitor_c.vk_argument_list bigf args
236 | Ast_c.MetaParamVal(param) -> Visitor_c.vk_param bigf param
237 | Ast_c.MetaParamListVal(params) -> Visitor_c.vk_param_list bigf params
238
239 | Ast_c.MetaTypeVal(ty) -> Visitor_c.vk_type bigf ty
113803cf 240 | Ast_c.MetaInitVal(ty) -> Visitor_c.vk_ini bigf ty
8f657093 241 | Ast_c.MetaInitListVal(ty) -> Visitor_c.vk_ini_list bigf ty
413ffc02
C
242 | Ast_c.MetaDeclVal(decl) -> Visitor_c.vk_decl bigf decl
243 | Ast_c.MetaFieldVal(field) -> Visitor_c.vk_struct_field bigf field
190f1acf 244 | Ast_c.MetaFieldListVal(fields) -> Visitor_c.vk_struct_fields bigf fields
faf9a90c
C
245 | Ast_c.MetaStmtVal(stm) -> Visitor_c.vk_statement bigf stm
246 | Ast_c.MetaPosVal _ | Ast_c.MetaPosValList _
247 | Ast_c.MetaListlenVal _ -> ())
248 env
249
250let rename argids env =
ae4735db 251 let argenv = List.map (function name ->
b1b2de81
C
252 let arg = Ast_c.str_of_name name in
253 (arg,prefix^arg)
254 ) argids in
faf9a90c
C
255 let lookup x = try List.assoc x argenv with Not_found -> x in
256 let bigf =
257 { Visitor_c.default_visitor_c_s with
ae4735db 258 Visitor_c.kexpr_s = (fun (k,bigf) e ->
faf9a90c 259 match e with
b1b2de81
C
260 ((Ast_c.Ident (name), info), []) ->
261
262 (* pad: assert is_regular_ident ? *)
263 let s = Ast_c.str_of_name name in
264 let ii = Ast_c.info_of_name name in
faf9a90c 265 let new_name = lookup s in
b1b2de81
C
266 let new_id = Ast_c.RegularName (new_name, [rewrap_str new_name ii]) in
267 ((Ast_c.Ident (new_id), info), Ast_c.noii)
faf9a90c
C
268 | _ -> k e) } in
269 List.map
270 (function (x,vl) ->
271 (x,
272 match vl with
273 Ast_c.MetaIdVal(_) | Ast_c.MetaFuncVal(_)
274 | Ast_c.MetaLocalFuncVal(_) -> vl
5636bb2c
C
275 | Ast_c.MetaExprVal(exp,c) ->
276 Ast_c.MetaExprVal(Visitor_c.vk_expr_s bigf exp,c)
faf9a90c
C
277 | Ast_c.MetaExprListVal(args) ->
278 Ast_c.MetaExprListVal(Visitor_c.vk_arguments_s bigf args)
279 | Ast_c.MetaParamVal(param) ->
280 Ast_c.MetaParamVal(Visitor_c.vk_param_s bigf param)
281 | Ast_c.MetaParamListVal(params) ->
282 Ast_c.MetaParamListVal(Visitor_c.vk_params_s bigf params)
283
284 | Ast_c.MetaTypeVal(ty) ->
285 Ast_c.MetaTypeVal(Visitor_c.vk_type_s bigf ty)
113803cf
C
286 | Ast_c.MetaInitVal(ini) ->
287 Ast_c.MetaInitVal(Visitor_c.vk_ini_s bigf ini)
8f657093
C
288 | Ast_c.MetaInitListVal(ini) ->
289 Ast_c.MetaInitListVal(Visitor_c.vk_inis_s bigf ini)
413ffc02
C
290 | Ast_c.MetaDeclVal(stm) ->
291 Ast_c.MetaDeclVal(Visitor_c.vk_decl_s bigf stm)
292 | Ast_c.MetaFieldVal(stm) ->
293 Ast_c.MetaFieldVal(Visitor_c.vk_struct_field_s bigf stm)
190f1acf
C
294 | Ast_c.MetaFieldListVal(stm) ->
295 Ast_c.MetaFieldListVal(Visitor_c.vk_struct_fields_s bigf stm)
faf9a90c
C
296 | Ast_c.MetaStmtVal(stm) ->
297 Ast_c.MetaStmtVal(Visitor_c.vk_statement_s bigf stm)
298 | Ast_c.MetaPosVal _ | Ast_c.MetaPosValList _
299 | Ast_c.MetaListlenVal _ -> vl))
300 env
301
0708f913
C
302let print_one_type pr env = function
303 (Type_cocci.MetaType(name,keep,inherited)) as ty ->
304 (try
305 match List.assoc name env with
ae4735db 306 Ast_c.MetaTypeVal ty ->
0708f913
C
307 Pretty_print_c.pp_type_gen
308 (function x -> pr (Ast_c.str_of_info x))
309 (function _ -> pr " ")
310 ty
311 | _ -> failwith "impossible"
312 with Not_found -> pr (Type_cocci.type2c ty))
313 | ty -> pr (Type_cocci.type2c ty)
314
315let print_types pr env = function
faf9a90c 316 None -> ()
0708f913 317 | Some [ty] -> print_one_type pr env ty
faf9a90c
C
318 | Some types ->
319 pr "{";
0708f913
C
320 Common.print_between (function _ -> pr ", ") (print_one_type pr env)
321 types;
faf9a90c
C
322 pr "}"
323
190f1acf
C
324let pp_len pr len =
325 let pp_name (_,n) = pr n in
326 match len with
327 Ast.AnyLen -> ()
328 | Ast.MetaLen len -> pr "["; pp_name len; pr "]"
329 | Ast.CstLen len -> pr "["; pr (string_of_int len); pr "]"
330
0708f913 331let pp_meta_decl pr env decl =
faf9a90c
C
332 let no_arity = function Ast.NONE -> () | _ -> failwith "no arity allowed" in
333 let pp_name (_,n) = pr n in
334 match decl with
b23ff9c7
C
335 Ast.MetaMetaDecl(ar, name) ->
336 (* ignore virtual *)
337 no_arity ar; pr "metavariable "; pp_name name; pr ";\n"
338 | Ast.MetaIdDecl(ar, name) ->
ae4735db 339 (* ignore virtual *)
faf9a90c 340 no_arity ar; pr "identifier "; pp_name name; pr ";\n"
978fd7e5 341 | Ast.MetaFreshIdDecl(name, Ast.NoVal) ->
b1b2de81 342 pr "fresh identifier "; pp_name name; pr ";\n"
978fd7e5 343 | Ast.MetaFreshIdDecl(name, Ast.StringSeed x) ->
b1b2de81 344 pr "fresh identifier "; pp_name name; pr " = \""; pr x; pr "\";\n"
978fd7e5
C
345 | Ast.MetaFreshIdDecl(name, Ast.ListSeed x) ->
346 failwith "unparse_hrule: not supported"
faf9a90c
C
347 | Ast.MetaTypeDecl(ar, name) ->
348 no_arity ar; pr "type "; pp_name name; pr ";\n"
113803cf
C
349 | Ast.MetaInitDecl(ar, name) ->
350 no_arity ar; pr "initialiser "; pp_name name; pr ";\n"
8f657093
C
351 | Ast.MetaInitListDecl(ar, name, len) ->
352 no_arity ar; pr "initialiser list "; pp_name name; pp_len pr len; pr ";\n"
faf9a90c
C
353 | Ast.MetaListlenDecl(name) -> ()
354 | Ast.MetaParamDecl(ar, name) ->
355 no_arity ar; pr "parameter "; pp_name name; pr ";\n"
190f1acf
C
356 | Ast.MetaParamListDecl(ar, name, len) ->
357 no_arity ar; pr "parameter list "; pp_name name; pp_len pr len; pr ";\n"
faf9a90c 358 | Ast.MetaConstDecl(ar, name, types) ->
0708f913 359 no_arity ar; pr "constant "; print_types pr env types;
faf9a90c
C
360 pp_name name; pr ";\n"
361 | Ast.MetaErrDecl(ar, name) ->
362 no_arity ar; pr "error "; pp_name name; pr ";\n"
363 | Ast.MetaExpDecl(ar, name, None) ->
364 no_arity ar; pr "expression "; pp_name name; pr ";\n"
365 | Ast.MetaExpDecl(ar, name, types) ->
0708f913 366 no_arity ar; print_types pr env types; pp_name name; pr ";\n"
faf9a90c
C
367 | Ast.MetaIdExpDecl(ar, name, types) ->
368 no_arity ar; pr "idexpression ";
0708f913 369 print_types pr env types; pp_name name; pr ";\n"
faf9a90c
C
370 | Ast.MetaLocalIdExpDecl(ar, name, types) ->
371 no_arity ar; pr "local idexpression ";
0708f913 372 print_types pr env types; pp_name name; pr ";\n"
190f1acf
C
373 | Ast.MetaExpListDecl(ar, name, len) ->
374 no_arity ar; pr "parameter list "; pp_name name; pp_len pr len; pr ";\n"
413ffc02
C
375 | Ast.MetaDeclDecl(ar, name) ->
376 no_arity ar; pr "declaration "; pp_name name; pr ";\n"
377 | Ast.MetaFieldDecl(ar, name) ->
378 no_arity ar; pr "field "; pp_name name; pr ";\n"
190f1acf
C
379 | Ast.MetaFieldListDecl(ar, name, len) ->
380 no_arity ar; pr "field list "; pp_name name; pp_len pr len; pr ";\n"
faf9a90c
C
381 | Ast.MetaStmDecl(ar, name) ->
382 no_arity ar; pr "statement "; pp_name name; pr ";\n"
383 | Ast.MetaStmListDecl(ar, name) ->
384 no_arity ar; pr "statement list "; pp_name name; pr ";\n"
385 | Ast.MetaFuncDecl(ar, name) ->
386 no_arity ar; pr "function "; pp_name name; pr ";\n"
387 | Ast.MetaLocalFuncDecl(ar, name) ->
388 no_arity ar; pr "local function "; pp_name name; pr ";\n"
389 | Ast.MetaPosDecl(ar, name) ->
390 no_arity ar; pr "position "; pp_name name; pr ";\n"
391 | Ast.MetaDeclarerDecl(ar, name) ->
392 no_arity ar; pr "declarer "; pp_name name; pr ";\n"
393 | Ast.MetaIteratorDecl(ar, name) ->
394 no_arity ar; pr "iterator "; pp_name name; pr ";\n"
395
0708f913 396let print_metavariables pr local_metas paramst env header_req function_name =
34e49164
C
397 (if header_req
398 then pr "@depends on header@\n"
399 else pr "@@\n");
0708f913 400 pr (Printf.sprintf "position _p!=same_%s.p;\n" function_name);
faf9a90c 401 pr "identifier _f;\n";
faf9a90c 402 let rec loop = function
b1b2de81 403 [] | [{Ast_c.p_type =(_,(Ast_c.BaseType(Ast_c.Void),_))},_] -> []
faf9a90c 404 | ((first,_) as f)::rest ->
0708f913 405 print_metavar pr first; pr ";\n";
faf9a90c
C
406 (make_exp f) :: loop rest in
407 let args = loop paramst in
0708f913
C
408 print_extra_typedefs pr env;
409 List.iter (pp_meta_decl pr env) local_metas;
faf9a90c
C
410 pr "@@\n\n";
411 args
34e49164
C
412
413(* ----------------------------------------------------------------------- *)
faf9a90c
C
414(* print_start/end *)
415
416let print_start pr =
417 pr "_f@_p(...) { <+...\n"
34e49164 418
faf9a90c
C
419let print_end pr =
420 pr "\n...+> }\n"
34e49164
C
421
422(* ----------------------------------------------------------------------- *)
423(* Print call to the defined function *)
424
425let print_param_name pr = function
b1b2de81 426 {Ast_c.p_namei = Some name} -> pr (Ast_c.str_of_name name)
34e49164
C
427 | _ -> failwith "function must have named parameters"
428
485bce71 429let pp_def_gen pr defn isexp =
b1b2de81
C
430 let {Ast_c.f_name = name; f_type = (_, (paramst, (b, iib))); } = defn in
431 pr (Ast_c.str_of_name name); pr "(";
34e49164
C
432 (if b then failwith "not handling variable argument functions");
433 (match paramst with
b1b2de81 434 [] | [{Ast_c.p_type = (_,(Ast_c.BaseType(Ast_c.Void),_))},_] -> ()
34e49164
C
435 | (first,_)::rest ->
436 print_param_name pr first;
437 List.iter (function (x,_) -> pr ", "; print_param_name pr x) rest);
438 pr ")"; if not isexp then pr ";"
439
440(* ----------------------------------------------------------------------- *)
441(* Entry point *)
442
faf9a90c
C
443let pp_rule local_metas ast env srcfile =
444 let (paramst,args_name) = get_paramst env in
445 (* get rule information *)
446 let (rule,printable) =
447 match ast with
448 Ast.CocciRule(_,_,[body],_,_) -> (* could extend to use attributes *)
449 (body,
450 match Ast.unwrap body with
65038c61 451 Ast.NONDECL(s) -> [[Ast.StatementTag s]]
faf9a90c
C
452 | Ast.CODE(ss) -> [[Ast.StmtDotsTag ss]]
453 | _ -> error body "bad rule body")
454 | _ -> failwith "bad rule" in
455 (* create the output file *)
456 let outdir =
457 match !Flag.make_hrule with
458 Some outdir -> outdir
459 | None -> error rule "not possible" in
460 let function_name = get_function_name rule env in
0708f913 461 let function_name_count =
faf9a90c 462 try
0708f913 463 let cell = List.assoc function_name !names in
faf9a90c
C
464 let ct = !cell in
465 cell := ct + 1;
0708f913 466 function_name ^ (string_of_int ct)
faf9a90c 467 with Not_found ->
0708f913
C
468 let cell = ref 1 in
469 names := (function_name,cell) :: !names;
470 function_name in
471 let outfile = outdir ^ "/" ^
472 (if !Flag.hrule_per_file
473 then Filename.chop_extension (Filename.basename srcfile)
474 else function_name_count) in
475 let escape_re = Str.regexp_string "/" in
476 let dir = if !Flag.dir = "" then Filename.dirname srcfile else !Flag.dir in
477 let outdirfile = Str.global_replace escape_re "_"dir in
478 let outfile = outfile ^ outdirfile ^ ".cocci" in
479 let saved_header_req =
480 try let res = List.assoc outfile !started_files in Some res
481 with Not_found -> None in
482 current_outfile := outfile;
483 Common.with_open_outfile_append outfile (fun (pr,chan) ->
484 let header_req =
485 match saved_header_req with
486 Some x -> x
487 | None ->
488 let res = print_header_rule pr srcfile in
489 started_files := (outfile,res)::!started_files;
490 res in
491 print_check_rule pr function_name function_name_count header_req;
492 let args =
493 print_metavariables pr local_metas paramst env header_req
494 function_name_count in
faf9a90c
C
495 let (argids,args) = List.split args in
496 let env = rename argids env in
497 let env = (args_name,Ast_c.MetaExprListVal args)::env in
498 print_start pr;
499 (* for printing C tokens *)
500 let pr_c info =
501 match Ast_c.pinfo_of_info info with
502 Ast_c.AbstractLineTok _ -> pr (Ast_c.str_of_info info)
503 | Ast_c.FakeTok (s,_) -> pr s
504 | _ ->
505 Printf.printf "line: %s\n" (Common.dump info);
506 error rule "not an abstract line" in
708f4980 507 let pr_space _ = pr " " in
faf9a90c 508 Unparse_cocci.pp_list_list_any
5636bb2c 509 ([env], (fun s _ _ _ _ -> pr s), pr_c, pr_space, pr_space, pr,
708f4980 510 (fun _ _ -> ()), (function _ -> ()), (function _ -> ()))
faf9a90c
C
511 true printable Unparse_cocci.InPlace;
512 print_end pr;
513 pr "\n")