Commit | Line | Data |
---|---|---|
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 |
17 | module Ast = Ast_cocci |
18 | module V = Visitor_ast | |
34e49164 | 19 | |
faf9a90c C |
20 | let error x s = |
21 | failwith | |
22 | (Printf.sprintf "unparse_hrule: line: %d, %s" (Ast.get_line x) s) | |
34e49164 | 23 | |
faf9a90c | 24 | let names = ref ([] : (string * int ref) list) |
34e49164 | 25 | |
0708f913 C |
26 | let started_files = ref ([] : (string * bool) list) |
27 | let typedefs = ref ([] : (string * string list ref) list) | |
28 | let current_outfile = ref "" | |
29 | ||
30 | let prefix = "_cocci_" | |
31 | ||
34e49164 C |
32 | (* ----------------------------------------------------------------------- *) |
33 | (* Create rule to check for header include *) | |
34 | ||
35 | let 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 | 58 | let 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 | |
69 | let rec env_lookup fn = function | |
70 | [] -> failwith "no binding" | |
71 | | (nm,vl)::rest when fn nm -> vl | |
72 | | _::rest -> env_lookup fn rest | |
73 | ||
74 | let 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 | ||
84 | let 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 | 150 | let 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 |
164 | let 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 | 175 | let 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 | 186 | let 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 | 211 | let 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 | 222 | let 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 | ||
250 | let 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 |
302 | let 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 | ||
315 | let 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 |
324 | let 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 | 331 | let 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 | 396 | let 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 | ||
416 | let print_start pr = | |
417 | pr "_f@_p(...) { <+...\n" | |
34e49164 | 418 | |
faf9a90c C |
419 | let print_end pr = |
420 | pr "\n...+> }\n" | |
34e49164 C |
421 | |
422 | (* ----------------------------------------------------------------------- *) | |
423 | (* Print call to the defined function *) | |
424 | ||
425 | let 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 | 429 | let 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 |
443 | let 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") |