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