Release coccinelle-0.1.5
[bpt/coccinelle.git] / parsing_c / unparse_cocci.ml
CommitLineData
34e49164
C
1open Common
2
3(*****************************************************************************)
4(* mostly a copy paste of parsing_cocci/pretty_print_cocci.ml
5 * todo?: try to factorize ?
6 *)
7(*****************************************************************************)
8
9module Ast = Ast_cocci
10
11let term s = Ast.unwrap_mcode s
12
13(* or perhaps can have in plus, for instance a Disj, but those Disj must be
14 * handled by interactive tool (by proposing alternatives)
15 *)
16exception CantBeInPlus
17
18(*****************************************************************************)
19
20type pos = Before | After | InPlace
21
22let rec pp_list_list_any (env, pr, pr_elem, pr_space, indent, unindent)
faf9a90c 23 generating xxs before =
34e49164
C
24
25(* Just to be able to copy paste the code from pretty_print_cocci.ml. *)
26let print_string = pr in
27let close_box _ = () in
28let print_space() = pr " " in
29let force_newline () = pr "\n" in
30
31let start_block () = force_newline(); indent() in
32let end_block () = unindent(); force_newline () in
33let print_string_box s = print_string s in
34
35let print_option = Common.do_option in
36let print_between = Common.print_between in
37
113803cf
C
38let outdent _ = () (* should go to leftmost col, does nothing now *) in
39
40let pretty_print_c =
41 Pretty_print_c.pretty_print_c pr_elem pr_space
42 force_newline indent outdent unindent in
43
34e49164 44(* --------------------------------------------------------------------- *)
faf9a90c 45(* Only for make_hrule, print plus code, unbound metavariables *)
34e49164 46
faf9a90c
C
47(* avoid polyvariance problems *)
48let anything : (Ast.anything -> unit) ref = ref (function _ -> ()) in
34e49164 49
faf9a90c
C
50let rec print_anything = function
51 [] -> ()
52 | stream ->
53 start_block();
54 print_between force_newline print_anything_list stream;
55 end_block()
56
57and print_anything_list = function
34e49164 58 [] -> ()
faf9a90c
C
59 | [x] -> !anything x
60 | bef::((aft::_) as rest) ->
61 !anything bef;
62 let space =
63 (match bef with
64 Ast.Rule_elemTag(_) | Ast.AssignOpTag(_) | Ast.BinaryOpTag(_)
65 | Ast.ArithOpTag(_) | Ast.LogicalOpTag(_)
66 | Ast.Token("if",_) | Ast.Token("while",_) -> true | _ -> false) or
67 (match aft with
68 Ast.Rule_elemTag(_) | Ast.AssignOpTag(_) | Ast.BinaryOpTag(_)
69 | Ast.ArithOpTag(_) | Ast.LogicalOpTag(_) | Ast.Token("{",_) -> true
70 | _ -> false) in
71 if space then print_string " ";
72 print_anything_list rest in
73
74let print_around printer term = function
75 Ast.NOTHING -> printer term
76 | Ast.BEFORE(bef) -> print_anything bef; printer term
77 | Ast.AFTER(aft) -> printer term; print_anything aft
78 | Ast.BEFOREAFTER(bef,aft) ->
79 print_anything bef; printer term; print_anything aft in
80
81let print_string_befaft fn x info =
82 List.iter (function s -> print_string s; force_newline())
83 info.Ast.strbef;
84 fn x;
85 List.iter (function s -> force_newline(); print_string s)
86 info.Ast.straft in
87
88let print_meta (r,x) = print_string x in
89
90let print_pos = function
91 Ast.MetaPos(name,_,_,_,_) ->
92 let name = Ast.unwrap_mcode name in
93 print_string "@"; print_meta name
94 | _ -> () in
95
96(* --------------------------------------------------------------------- *)
97
98let mcode fn arg =
99 match (generating,arg) with
100 (false,(s,info,_,_)) ->
101 (* printing for transformation *)
102 (* Here we don't care about the annotation on s. *)
103 List.iter (function str -> print_string str; print_string "\n")
104 info.Ast.strbef;
105 if info.Ast.column > 0 && not(info.Ast.strbef = [])
106 then print_string (String.make info.Ast.column ' ');
107 fn s;
108 (match info.Ast.straft with
109 [] -> ()
110 | aft ->
111 List.iter (function str -> print_string "\n"; print_string str) aft;
112 print_string "\n") (*XXX pr current_tabbing *)
113 (* printing for rule generation *)
114 | (true, (x, _, Ast.MINUS(_,plus_stream), pos)) ->
115 print_string "\n- ";
116 fn x; print_pos pos;
117 print_anything plus_stream
118 | (true, (x, _, Ast.CONTEXT(_,plus_streams), pos)) ->
119 let fn x = print_string "\n "; fn x; print_pos pos in
120 print_around fn x plus_streams
121 | (true,( x, info, Ast.PLUS, pos)) ->
122 let fn x = print_string "\n+ "; fn x; print_pos pos in
123 print_string_befaft fn x info
34e49164
C
124in
125
faf9a90c
C
126
127(* --------------------------------------------------------------------- *)
128
129let handle_metavar name fn =
130 match (Common.optionise (fun () -> List.assoc (term name) env)) with
131 | None ->
132 let name_string (_,s) = s in
133 if generating
134 then pr (name_string (term name))
135 else
136 failwith
137 (Printf.sprintf "SP line %d: Not found a value in env for: %s"
138 (Ast_cocci.get_mcode_line name) (name_string (term name)))
139 | Some e ->
140 if generating
141 then mcode (function _ -> fn e) name
142 else fn e
143in
34e49164
C
144(* --------------------------------------------------------------------- *)
145let dots between fn d =
146 match Ast.unwrap d with
147 Ast.DOTS(l) -> print_between between fn l
148 | Ast.CIRCLES(l) -> print_between between fn l
149 | Ast.STARS(l) -> print_between between fn l
150in
151
faf9a90c
C
152let nest_dots multi fn f d =
153 let mo s = if multi then "<+"^s else "<"^s in
154 let mc s = if multi then s^"+>" else s^">" in
155 match Ast.unwrap d with
156 Ast.DOTS(l) ->
157 print_string (mo "..."); f(); start_block();
158 print_between force_newline fn l;
159 end_block(); print_string (mc "...")
160 | Ast.CIRCLES(l) ->
161 print_string (mo "ooo"); f(); start_block();
162 print_between force_newline fn l;
163 end_block(); print_string (mc "ooo")
164 | Ast.STARS(l) ->
165 print_string (mo "***"); f(); start_block();
166 print_between force_newline fn l;
167 end_block(); print_string (mc "***")
168in
34e49164
C
169
170(* --------------------------------------------------------------------- *)
171(* Identifier *)
172
173let rec ident i =
174 match Ast.unwrap i with
175 Ast.Id(name) -> mcode print_string name
176 | Ast.MetaId(name,_,_,_) ->
177 handle_metavar name (function
178 | (Ast_c.MetaIdVal id) -> pr id
179 | _ -> raise Impossible
180 )
181 | Ast.MetaFunc(name,_,_,_) ->
182 handle_metavar name (function
183 | (Ast_c.MetaFuncVal id) -> pr id
184 | _ -> raise Impossible
185 )
186 | Ast.MetaLocalFunc(name,_,_,_) ->
187 handle_metavar name (function
188 | (Ast_c.MetaLocalFuncVal id) -> pr id
189 | _ -> raise Impossible
190 )
191
192 | Ast.OptIdent(_) | Ast.UniqueIdent(_) ->
193 raise CantBeInPlus
194
195in
196
197(* --------------------------------------------------------------------- *)
198(* Expression *)
199
faf9a90c
C
200let print_disj_list fn l =
201 force_newline(); print_string "("; force_newline();
202 print_between
203 (function _ ->
204 force_newline(); print_string "|"; force_newline())
205 fn l;
206 force_newline(); print_string ")"; force_newline() in
207
34e49164
C
208let rec expression e =
209 match Ast.unwrap e with
210 Ast.Ident(id) -> ident id
211
212 | Ast.Constant(const) -> mcode constant const
213 | Ast.FunCall(fn,lp,args,rp) ->
214 expression fn; mcode print_string_box lp;
215 dots (function _ -> ()) expression args;
216 close_box(); mcode print_string rp
217 | Ast.Assignment(left,op,right,_) ->
218 expression left; print_string " "; mcode assignOp op;
219 print_string " "; expression right
220 | Ast.CondExpr(exp1,why,exp2,colon,exp3) ->
221 expression exp1; print_string " "; mcode print_string why;
222 print_option (function e -> print_string " "; expression e) exp2;
223 print_string " "; mcode print_string colon; expression exp3
224 | Ast.Postfix(exp,op) -> expression exp; mcode fixOp op
225 | Ast.Infix(exp,op) -> mcode fixOp op; expression exp
226 | Ast.Unary(exp,op) -> mcode unaryOp op; expression exp
227 | Ast.Binary(left,op,right) ->
228 expression left; print_string " "; mcode binaryOp op; print_string " ";
229 expression right
230 | Ast.Nested(left,op,right) -> failwith "nested only in minus code"
231 | Ast.Paren(lp,exp,rp) ->
232 mcode print_string_box lp; expression exp; close_box();
233 mcode print_string rp
234 | Ast.ArrayAccess(exp1,lb,exp2,rb) ->
235 expression exp1; mcode print_string_box lb; expression exp2; close_box();
236 mcode print_string rb
237 | Ast.RecordAccess(exp,pt,field) ->
238 expression exp; mcode print_string pt; ident field
239 | Ast.RecordPtAccess(exp,ar,field) ->
240 expression exp; mcode print_string ar; ident field
241 | Ast.Cast(lp,ty,rp,exp) ->
242 mcode print_string_box lp; fullType ty; close_box();
243 mcode print_string rp; expression exp
244 | Ast.SizeOfExpr(sizeof,exp) ->
245 mcode print_string sizeof; expression exp
246 | Ast.SizeOfType(sizeof,lp,ty,rp) ->
247 mcode print_string sizeof;
248 mcode print_string_box lp; fullType ty; close_box();
249 mcode print_string rp
250 | Ast.TypeExp(ty) -> fullType ty
251
252 | Ast.MetaErr(name,_,_,_) ->
253 failwith "metaErr not handled"
254
255 | Ast.MetaExpr (name,_,_,_typedontcare,_formdontcare,_) ->
256 handle_metavar name (function
257 | Ast_c.MetaExprVal exp ->
113803cf 258 pretty_print_c.Pretty_print_c.expression exp
34e49164
C
259 | _ -> raise Impossible
260 )
261
262 | Ast.MetaExprList (name,_,_,_) ->
faf9a90c
C
263 handle_metavar name (function
264 | Ast_c.MetaExprListVal args ->
113803cf 265 pretty_print_c.Pretty_print_c.arg_list args
faf9a90c
C
266 | _ -> raise Impossible
267 )
268
34e49164
C
269 | Ast.EComma(cm) -> mcode print_string cm; print_space()
270
faf9a90c
C
271 | Ast.DisjExpr(exp_list) ->
272 if generating
273 then print_disj_list expression exp_list
274 else raise CantBeInPlus
275 | Ast.NestExpr(expr_dots,Some whencode,multi) when generating ->
276 nest_dots multi expression
277 (function _ -> print_string " when != "; expression whencode)
278 expr_dots
279 | Ast.NestExpr(expr_dots,None,multi) when generating ->
280 nest_dots multi expression (function _ -> ()) expr_dots
281 | Ast.NestExpr(_) -> raise CantBeInPlus
282 | Ast.Edots(dots,Some whencode)
283 | Ast.Ecircles(dots,Some whencode)
284 | Ast.Estars(dots,Some whencode) ->
285 if generating
286 then
287 (mcode print_string dots;
288 print_string " when != ";
289 expression whencode)
290 else raise CantBeInPlus
291 | Ast.Edots(dots,None)
292 | Ast.Ecircles(dots,None)
293 | Ast.Estars(dots,None) ->
294 if generating
295 then mcode print_string dots
296 else raise CantBeInPlus
34e49164
C
297
298 | Ast.OptExp(exp) | Ast.UniqueExp(exp) ->
299 raise CantBeInPlus
300
301and unaryOp = function
302 Ast.GetRef -> print_string "&"
303 | Ast.DeRef -> print_string "*"
304 | Ast.UnPlus -> print_string "+"
305 | Ast.UnMinus -> print_string "-"
306 | Ast.Tilde -> print_string "~"
307 | Ast.Not -> print_string "!"
308
309and assignOp = function
310 Ast.SimpleAssign -> print_string "="
311 | Ast.OpAssign(aop) -> arithOp aop; print_string "="
312
313and fixOp = function
314 Ast.Dec -> print_string "--"
315 | Ast.Inc -> print_string "++"
316
317and binaryOp = function
318 Ast.Arith(aop) -> arithOp aop
319 | Ast.Logical(lop) -> logicalOp lop
320
321and arithOp = function
322 Ast.Plus -> print_string "+"
323 | Ast.Minus -> print_string "-"
324 | Ast.Mul -> print_string "*"
325 | Ast.Div -> print_string "/"
326 | Ast.Mod -> print_string "%"
327 | Ast.DecLeft -> print_string "<<"
328 | Ast.DecRight -> print_string ">>"
329 | Ast.And -> print_string "&"
330 | Ast.Or -> print_string "|"
331 | Ast.Xor -> print_string "^"
332
333and logicalOp = function
334 Ast.Inf -> print_string "<"
335 | Ast.Sup -> print_string ">"
336 | Ast.InfEq -> print_string "<="
337 | Ast.SupEq -> print_string ">="
338 | Ast.Eq -> print_string "=="
339 | Ast.NotEq -> print_string "!="
340 | Ast.AndLog -> print_string "&&"
341 | Ast.OrLog -> print_string "||"
342
343and constant = function
344 Ast.String(s) -> print_string "\""; print_string s; print_string "\""
345 | Ast.Char(s) -> print_string s
346 | Ast.Int(s) -> print_string s
347 | Ast.Float(s) -> print_string s
348
349(* --------------------------------------------------------------------- *)
350(* Types *)
351
352
353and fullType ft =
354 match Ast.unwrap ft with
355 Ast.Type(cv,ty) ->
113803cf 356 print_option (mcode const_vol) cv;
34e49164
C
357 typeC ty
358 | Ast.DisjType _ -> failwith "can't be in plus"
359 | Ast.OptType(_) | Ast.UniqueType(_) ->
360 raise CantBeInPlus
361
362and print_function_pointer (ty,lp1,star,rp1,lp2,params,rp2) fn =
363 fullType ty; mcode print_string lp1; mcode print_string star; fn();
364 mcode print_string rp1; mcode print_string lp1;
365 parameter_list params; mcode print_string rp2
366
367and print_function_type (ty,lp1,params,rp1) fn =
368 print_option fullType ty; fn(); mcode print_string lp1;
369 parameter_list params; mcode print_string rp1
370
371and typeC ty =
372 match Ast.unwrap ty with
faf9a90c
C
373 Ast.BaseType(ty,strings) ->
374 print_between pr_space (mcode print_string) strings
375 | Ast.SignedT(sgn,Some ty) -> mcode sign sgn; typeC ty
376 | Ast.SignedT(sgn,None) -> mcode signns sgn
34e49164
C
377 | Ast.Pointer(ty,star) -> fullType ty; ft_space ty; mcode print_string star
378 | Ast.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
379 print_function_pointer (ty,lp1,star,rp1,lp2,params,rp2)
380 (function _ -> ())
381 | Ast.FunctionType (am,ty,lp1,params,rp1) ->
382 print_function_type (ty,lp1,params,rp1) (function _ -> ())
383 | Ast.Array(ty,lb,size,rb) ->
384 fullType ty; mcode print_string lb; print_option expression size;
385 mcode print_string rb
faf9a90c
C
386 | Ast.EnumName(kind,name) -> mcode print_string kind; print_string " ";
387 ident name
34e49164
C
388 | Ast.StructUnionName(kind,name) ->
389 mcode structUnion kind;
390 print_option ident name
391 | Ast.StructUnionDef(ty,lb,decls,rb) ->
392 fullType ty;
393 mcode print_string lb;
394 dots force_newline declaration decls;
395 mcode print_string rb
396 | Ast.TypeName(name)-> mcode print_string name
397 | Ast.MetaType(name,_,_) ->
398 handle_metavar name (function
399 Ast_c.MetaTypeVal exp ->
113803cf 400 pretty_print_c.Pretty_print_c.ty exp
34e49164
C
401 | _ -> raise Impossible)
402
403and baseType = function
404 Ast.VoidType -> print_string "void"
405 | Ast.CharType -> print_string "char"
406 | Ast.ShortType -> print_string "short"
407 | Ast.IntType -> print_string "int"
408 | Ast.DoubleType -> print_string "double"
409 | Ast.FloatType -> print_string "float"
410 | Ast.LongType -> print_string "long"
faf9a90c 411 | Ast.LongLongType -> print_string "long long"
34e49164
C
412
413and structUnion = function
414 Ast.Struct -> print_string "struct "
415 | Ast.Union -> print_string "union "
416
417and sign = function
418 Ast.Signed -> print_string "signed "
419 | Ast.Unsigned -> print_string "unsigned "
420
421and signns = function (* no space, like a normal type *)
422 Ast.Signed -> print_string "signed"
423 | Ast.Unsigned -> print_string "unsigned"
424
425
426and const_vol = function
427 Ast.Const -> print_string "const "
428 | Ast.Volatile -> print_string "volatile "
429
430(* --------------------------------------------------------------------- *)
431(* Function declaration *)
432
433and storage = function
434 Ast.Static -> print_string "static "
435 | Ast.Auto -> print_string "auto "
436 | Ast.Register -> print_string "register "
437 | Ast.Extern -> print_string "extern "
438
439(* --------------------------------------------------------------------- *)
440(* Variable declaration *)
441
442and print_named_type ty id =
443 match Ast.unwrap ty with
444 Ast.Type(None,ty1) ->
445 (match Ast.unwrap ty1 with
446 Ast.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
447 print_function_pointer (ty,lp1,star,rp1,lp2,params,rp2)
448 (function _ -> print_string " "; ident id)
449 | Ast.FunctionType(am,ty,lp1,params,rp1) ->
450 print_function_type (ty,lp1,params,rp1)
451 (function _ -> print_string " "; ident id)
452 | Ast.Array(_,_,_,_) ->
453 let rec loop ty k =
454 match Ast.unwrap ty with
455 Ast.Array(ty,lb,size,rb) ->
456 (match Ast.unwrap ty with
457 Ast.Type(None,ty) ->
458 loop ty
459 (function _ ->
460 k ();
461 mcode print_string lb;
462 print_option expression size;
463 mcode print_string rb)
464 | _ -> failwith "complex array types not supported")
465 | _ -> typeC ty; ty_space ty; ident id; k () in
466 loop ty1 (function _ -> ())
467 (*| should have a case here for pointer to array or function type
468 that would put ( * ) around the variable. This makes one wonder
469 why we really need a special case for function pointer *)
470 | _ -> fullType ty; ft_space ty; ident id)
471 | _ -> fullType ty; ft_space ty; ident id
472
473and ty_space ty =
474 match Ast.unwrap ty with
475 Ast.Pointer(_,_) -> ()
476 | _ -> print_space()
477
478and ft_space ty =
479 match Ast.unwrap ty with
480 Ast.Type(cv,ty) ->
481 (match Ast.unwrap ty with
482 Ast.Pointer(_,_) -> ()
483 | _ -> print_space())
484 | _ -> print_space()
485
486and declaration d =
487 match Ast.unwrap d with
488 Ast.Init(stg,ty,id,eq,ini,sem) ->
489 print_option (mcode storage) stg;
490 print_named_type ty id;
491 print_string " "; mcode print_string eq;
492 print_string " "; initialiser true ini; mcode print_string sem
493 | Ast.UnInit(stg,ty,id,sem) ->
494 print_option (mcode storage) stg;
495 print_named_type ty id;
496 mcode print_string sem
497 | Ast.MacroDecl(name,lp,args,rp,sem) ->
498 ident name; mcode print_string_box lp;
499 dots (function _ -> ()) expression args;
500 close_box(); mcode print_string rp; mcode print_string sem
501 | Ast.TyDecl(ty,sem) -> fullType ty; mcode print_string sem
502 | Ast.Typedef(stg,ty,id,sem) ->
503 mcode print_string stg;
504 fullType ty; typeC id;
505 mcode print_string sem
506 | Ast.DisjDecl(_) | Ast.MetaDecl(_,_,_) -> raise CantBeInPlus
507 | Ast.Ddots(_,_) -> raise CantBeInPlus
508 | Ast.OptDecl(decl) | Ast.UniqueDecl(decl) ->
509 raise CantBeInPlus
510
511(* --------------------------------------------------------------------- *)
512(* Initialiser *)
513
514and initialiser nlcomma i =
515 match Ast.unwrap i with
113803cf
C
516 Ast.MetaInit(name,_,_) ->
517 handle_metavar name (function
518 Ast_c.MetaInitVal ini ->
519 pretty_print_c.Pretty_print_c.init ini
520 | _ -> raise Impossible)
521 | Ast.InitExpr(exp) -> expression exp
34e49164
C
522 | Ast.InitList(lb,initlist,rb,[]) ->
523 mcode print_string lb; start_block();
524 (* awkward, because the comma is separate from the initialiser *)
525 let rec loop = function
526 [] -> ()
527 | [x] -> initialiser false x
528 | x::xs -> initialiser nlcomma x; loop xs in
529 loop initlist;
530 end_block(); mcode print_string rb
531 | Ast.InitList(lb,initlist,rb,_) -> failwith "unexpected whencode in plus"
113803cf
C
532 | Ast.InitGccExt(designators,eq,ini) ->
533 List.iter designator designators; print_string " ";
34e49164
C
534 mcode print_string eq; print_string " "; initialiser nlcomma ini
535 | Ast.InitGccName(name,eq,ini) ->
536 ident name; mcode print_string eq; initialiser nlcomma ini
34e49164
C
537 | Ast.IComma(comma) ->
538 mcode print_string comma;
539 if nlcomma then force_newline()
540 | Ast.OptIni(ini) | Ast.UniqueIni(ini) ->
541 raise CantBeInPlus
542
113803cf
C
543and designator = function
544 Ast.DesignatorField(dot,id) -> mcode print_string dot; ident id
545 | Ast.DesignatorIndex(lb,exp,rb) ->
546 mcode print_string lb; expression exp; mcode print_string rb
547 | Ast.DesignatorRange(lb,min,dots,max,rb) ->
548 mcode print_string lb; expression min; mcode print_string dots;
549 expression max; mcode print_string rb
550
34e49164
C
551(* --------------------------------------------------------------------- *)
552(* Parameter *)
553
554and parameterTypeDef p =
555 match Ast.unwrap p with
556 Ast.VoidParam(ty) -> fullType ty
557 | Ast.Param(ty,Some id) -> print_named_type ty id
558 | Ast.Param(ty,None) -> fullType ty
559
560 | Ast.MetaParam(name,_,_) ->
561 failwith "not handling MetaParam"
562 | Ast.MetaParamList(name,_,_,_) ->
563 failwith "not handling MetaParamList"
564
565 | Ast.PComma(cm) -> mcode print_string cm; print_space()
faf9a90c
C
566 | Ast.Pdots(dots) | Ast.Pcircles(dots) when generating ->
567 mcode print_string dots
568 | Ast.Pdots(dots) | Ast.Pcircles(dots) -> raise CantBeInPlus
34e49164
C
569 | Ast.OptParam(param) | Ast.UniqueParam(param) -> raise CantBeInPlus
570
571and parameter_list l = dots (function _ -> ()) parameterTypeDef l
572in
573
574
575(* --------------------------------------------------------------------- *)
576(* CPP code *)
577
578let rec inc_file = function
579 Ast.Local(elems) ->
580 print_string "\"";
581 print_between (function _ -> print_string "/") inc_elem elems;
582 print_string "\""
583 | Ast.NonLocal(elems) ->
584 print_string "<";
585 print_between (function _ -> print_string "/") inc_elem elems;
586 print_string ">"
587
588and inc_elem = function
589 Ast.IncPath s -> print_string s
590 | Ast.IncDots -> print_string "..."
591
592(* --------------------------------------------------------------------- *)
593(* Top-level code *)
594
595and rule_elem arity re =
596 match Ast.unwrap re with
597 Ast.FunHeader(_,_,fninfo,name,lp,params,rp) ->
598 print_string arity; List.iter print_fninfo fninfo;
599 ident name; mcode print_string_box lp;
600 parameter_list params; close_box(); mcode print_string rp;
601 print_string " "
602 | Ast.Decl(_,_,decl) -> print_string arity; declaration decl
603
604 | Ast.SeqStart(brace) ->
605 print_string arity; mcode print_string brace; start_block()
606 | Ast.SeqEnd(brace) ->
607 end_block(); print_string arity; mcode print_string brace
608
609 | Ast.ExprStatement(exp,sem) ->
610 print_string arity; expression exp; mcode print_string sem
611
612 | Ast.IfHeader(iff,lp,exp,rp) ->
613 print_string arity;
614 mcode print_string iff; print_string " "; mcode print_string_box lp;
113803cf 615 expression exp; close_box(); mcode print_string rp
34e49164 616 | Ast.Else(els) ->
113803cf 617 print_string arity; mcode print_string els
34e49164
C
618
619 | Ast.WhileHeader(whl,lp,exp,rp) ->
620 print_string arity;
621 mcode print_string whl; print_string " "; mcode print_string_box lp;
113803cf 622 expression exp; close_box(); mcode print_string rp
34e49164 623 | Ast.DoHeader(d) ->
113803cf 624 print_string arity; mcode print_string d
34e49164
C
625 | Ast.WhileTail(whl,lp,exp,rp,sem) ->
626 print_string arity;
627 mcode print_string whl; print_string " "; mcode print_string_box lp;
628 expression exp; close_box(); mcode print_string rp;
629 mcode print_string sem
630 | Ast.ForHeader(fr,lp,e1,sem1,e2,sem2,e3,rp) ->
631 print_string arity;
632 mcode print_string fr; mcode print_string_box lp;
633 print_option expression e1; mcode print_string sem1;
634 print_option expression e2; mcode print_string sem2;
635 print_option expression e3; close_box();
113803cf 636 mcode print_string rp
34e49164
C
637 | Ast.IteratorHeader(nm,lp,args,rp) ->
638 print_string arity;
639 ident nm; print_string " "; mcode print_string_box lp;
640 dots (function _ -> ()) expression args; close_box();
113803cf 641 mcode print_string rp
34e49164
C
642
643 | Ast.SwitchHeader(switch,lp,exp,rp) ->
644 print_string arity;
645 mcode print_string switch; print_string " "; mcode print_string_box lp;
113803cf 646 expression exp; close_box(); mcode print_string rp
34e49164
C
647
648 | Ast.Break(br,sem) ->
649 print_string arity; mcode print_string br; mcode print_string sem
650 | Ast.Continue(cont,sem) ->
651 print_string arity; mcode print_string cont; mcode print_string sem
652 | Ast.Label(l,dd) -> ident l; mcode print_string dd
653 | Ast.Goto(goto,l,sem) ->
654 mcode print_string goto; ident l; mcode print_string sem
655 | Ast.Return(ret,sem) ->
656 print_string arity; mcode print_string ret;
657 mcode print_string sem
658 | Ast.ReturnExpr(ret,exp,sem) ->
659 print_string arity; mcode print_string ret; print_string " ";
660 expression exp; mcode print_string sem
661
662 | Ast.Exp(exp) -> print_string arity; expression exp
663 | Ast.TopExp(exp) -> print_string arity; expression exp
664 | Ast.Ty(ty) -> print_string arity; fullType ty
1be43e12 665 | Ast.TopInit(init) -> initialiser false init
34e49164
C
666 | Ast.Include(inc,s) ->
667 mcode print_string inc; print_string " "; mcode inc_file s
668 | Ast.DefineHeader(def,id,params) ->
669 mcode print_string def; print_string " "; ident id;
670 print_define_parameters params
671 | Ast.Default(def,colon) ->
672 mcode print_string def; mcode print_string colon; print_string " "
673 | Ast.Case(case,exp,colon) ->
674 mcode print_string case; print_string " "; expression exp;
675 mcode print_string colon; print_string " "
faf9a90c
C
676 | Ast.DisjRuleElem(res) ->
677 if generating
678 then
679 (print_string arity;
680 force_newline(); print_string "("; force_newline();
681 print_between
682 (function _ -> force_newline(); print_string "|"; force_newline())
683 (rule_elem arity)
684 res;
685 force_newline(); print_string ")")
686 else raise CantBeInPlus
34e49164
C
687
688 | Ast.MetaRuleElem(name,_,_) ->
689 raise Impossible
690
691 | Ast.MetaStmt(name,_,_,_) ->
692 handle_metavar name (function
113803cf
C
693 | Ast_c.MetaStmtVal stm ->
694 pretty_print_c.Pretty_print_c.statement stm
34e49164
C
695 | _ -> raise Impossible
696 )
697 | Ast.MetaStmtList(name,_,_) ->
698 failwith
699 "MetaStmtList not supported (not even in ast_c metavars binding)"
700
701and print_define_parameters params =
702 match Ast.unwrap params with
703 Ast.NoParams -> ()
704 | Ast.DParams(lp,params,rp) ->
705 mcode print_string lp;
706 dots (function _ -> ()) print_define_param params; mcode print_string rp
707
708and print_define_param param =
709 match Ast.unwrap param with
710 Ast.DParam(id) -> ident id
711 | Ast.DPComma(comma) -> mcode print_string comma
712 | Ast.DPdots(dots) -> mcode print_string dots
713 | Ast.DPcircles(circles) -> mcode print_string circles
714 | Ast.OptDParam(dp) -> print_string "?"; print_define_param dp
715 | Ast.UniqueDParam(dp) -> print_string "!"; print_define_param dp
716
717and print_fninfo = function
718 Ast.FStorage(stg) -> mcode storage stg
719 | Ast.FType(ty) -> fullType ty
720 | Ast.FInline(inline) -> mcode print_string inline; print_string " "
721 | Ast.FAttr(attr) -> mcode print_string attr; print_string " " in
722
faf9a90c
C
723let indent_if_needed s f =
724 match Ast.unwrap s with
113803cf 725 Ast.Seq(lbrace,decls,body,rbrace) -> pr_space(); f()
faf9a90c
C
726 | _ ->
727 (*no newline at the end - someone else will do that*)
728 start_block(); f(); unindent() in
729
34e49164
C
730let rec statement arity s =
731 match Ast.unwrap s with
732 Ast.Seq(lbrace,decls,body,rbrace) ->
733 rule_elem arity lbrace;
734 dots force_newline (statement arity) decls;
735 dots force_newline (statement arity) body;
736 rule_elem arity rbrace
737
738 | Ast.IfThen(header,branch,_) ->
faf9a90c
C
739 rule_elem arity header;
740 indent_if_needed branch (function _ -> statement arity branch)
34e49164 741 | Ast.IfThenElse(header,branch1,els,branch2,_) ->
faf9a90c
C
742 rule_elem arity header;
743 indent_if_needed branch1 (function _ -> statement arity branch1);
744 print_string " ";
745 rule_elem arity els;
746 indent_if_needed branch2 (function _ -> statement arity branch2)
34e49164
C
747
748 | Ast.While(header,body,_) ->
faf9a90c
C
749 rule_elem arity header;
750 indent_if_needed body (function _ -> statement arity body)
34e49164 751 | Ast.Do(header,body,tail) ->
faf9a90c
C
752 rule_elem arity header;
753 indent_if_needed body (function _ -> statement arity body);
34e49164
C
754 rule_elem arity tail
755 | Ast.For(header,body,_) ->
faf9a90c
C
756 rule_elem arity header;
757 indent_if_needed body (function _ -> statement arity body)
34e49164 758 | Ast.Iterator(header,body,(_,_,_,aft)) ->
faf9a90c
C
759 rule_elem arity header;
760 indent_if_needed body (function _ -> statement arity body);
34e49164
C
761 mcode (function _ -> ()) ((),Ast.no_info,aft,Ast.NoMetaPos)
762
763 | Ast.Switch(header,lb,cases,rb) ->
113803cf 764 rule_elem arity header; print_string " "; rule_elem arity lb;
34e49164
C
765 List.iter (function x -> case_line arity x; force_newline()) cases;
766 rule_elem arity rb
767
768 | Ast.Atomic(re) -> rule_elem arity re
769
770 | Ast.FunDecl(header,lbrace,decls,body,rbrace) ->
771 rule_elem arity header; rule_elem arity lbrace;
772 dots force_newline (statement arity) decls;
773 dots force_newline (statement arity) body; rule_elem arity rbrace
774
775 | Ast.Define(header,body) ->
776 rule_elem arity header; print_string " ";
777 dots force_newline (statement arity) body
778
faf9a90c
C
779 | Ast.Disj([stmt_dots]) ->
780 if generating
781 then
782 (print_string arity;
783 dots force_newline (statement arity) stmt_dots)
784 else raise CantBeInPlus
785 | Ast.Disj(stmt_dots_list) -> (* ignores newline directive for readability *)
786 if generating
787 then
788 (print_string arity;
789 force_newline(); print_string "("; force_newline();
790 print_between
791 (function _ -> force_newline();print_string "|"; force_newline())
792 (dots force_newline (statement arity))
793 stmt_dots_list;
794 force_newline(); print_string ")")
795 else raise CantBeInPlus
796 | Ast.Nest(stmt_dots,whn,multi,_,_) when generating ->
797 print_string arity;
798 nest_dots multi (statement arity)
799 (function _ ->
800 print_between force_newline
801 (whencode (dots force_newline (statement "")) (statement "")) whn;
802 force_newline())
803 stmt_dots
804 | Ast.Nest(_) -> raise CantBeInPlus
805 | Ast.Dots(d,whn,_,_) | Ast.Circles(d,whn,_,_) | Ast.Stars(d,whn,_,_) ->
806 if generating
807 then
808 (print_string arity; mcode print_string d;
809 print_between force_newline
810 (whencode (dots force_newline (statement "")) (statement "")) whn;
811 force_newline())
812 else raise CantBeInPlus
34e49164
C
813
814 | Ast.OptStm(s) | Ast.UniqueStm(s) ->
815 raise CantBeInPlus
816
faf9a90c
C
817and whencode notfn alwaysfn = function
818 Ast.WhenNot a ->
819 print_string " WHEN != "; notfn a
820 | Ast.WhenAlways a ->
821 print_string " WHEN = "; alwaysfn a
822 | Ast.WhenModifier x -> print_string " WHEN "; print_when_modif x
823 | Ast.WhenNotTrue a ->
824 print_string " WHEN != TRUE "; rule_elem "" a
825 | Ast.WhenNotFalse a ->
826 print_string " WHEN != FALSE "; rule_elem "" a
827
828and print_when_modif = function
829 | Ast.WhenAny -> print_string "ANY"
830 | Ast.WhenStrict -> print_string "STRICT"
831 | Ast.WhenForall -> print_string "FORALL"
832 | Ast.WhenExists -> print_string "EXISTS"
833
34e49164
C
834and case_line arity c =
835 match Ast.unwrap c with
836 Ast.CaseLine(header,code) ->
837 rule_elem arity header; print_string " ";
838 dots force_newline (statement arity) code
839 | Ast.OptCase(case) -> raise CantBeInPlus in
840
841let top_level t =
842 match Ast.unwrap t with
843 Ast.FILEINFO(old_file,new_file) -> raise CantBeInPlus
844 | Ast.DECL(stmt) -> statement "" stmt
845 | Ast.CODE(stmt_dots) -> dots force_newline (statement "") stmt_dots
846 | Ast.ERRORWORDS(exps) -> raise CantBeInPlus
847in
848
849(*
850let rule =
851 print_between (function _ -> force_newline(); force_newline()) top_level
852in
853*)
854
855let if_open_brace = function "{" -> true | _ -> false in
856
857let rec pp_any = function
858 (* assert: normally there is only CONTEXT NOTHING tokens in any *)
859 Ast.FullTypeTag(x) -> fullType x; false
860 | Ast.BaseTypeTag(x) -> baseType x; false
861 | Ast.StructUnionTag(x) -> structUnion x; false
862 | Ast.SignTag(x) -> sign x; false
863
864 | Ast.IdentTag(x) -> ident x; false
865
866 | Ast.ExpressionTag(x) -> expression x; false
867
868 | Ast.ConstantTag(x) -> constant x; false
869 | Ast.UnaryOpTag(x) -> unaryOp x; false
870 | Ast.AssignOpTag(x) -> assignOp x; false
871 | Ast.FixOpTag(x) -> fixOp x; false
872 | Ast.BinaryOpTag(x) -> binaryOp x; false
873 | Ast.ArithOpTag(x) -> arithOp x; false
874 | Ast.LogicalOpTag(x) -> logicalOp x; false
875
876 | Ast.InitTag(x) -> initialiser false x; false
877 | Ast.DeclarationTag(x) -> declaration x; false
878
879 | Ast.StorageTag(x) -> storage x; false
880 | Ast.IncFileTag(x) -> inc_file x; false
881
882 | Ast.Rule_elemTag(x) -> rule_elem "" x; false
883 | Ast.StatementTag(x) -> statement "" x; false
884 | Ast.CaseLineTag(x) -> case_line "" x; false
885
886 | Ast.ConstVolTag(x) -> const_vol x; false
887 | Ast.Token(x,None) -> print_string x; if_open_brace x
888 | Ast.Token(x,Some info) ->
889 mcode
890 (function x ->
891 (match x with
892 "else" -> pr "\n"
893 | _ -> ());
894 print_string x;
895 (* if x ==~ Common.regexp_alpha then print_string " "; *)
896 (match x with
897 (*"return" |*) "else" -> print_string " "
898 | _ -> ()))
faf9a90c
C
899 (let nomcodekind = Ast.CONTEXT(Ast.DontCarePos,Ast.NOTHING) in
900 (x,info,nomcodekind,Ast.NoMetaPos));
34e49164
C
901 if_open_brace x
902
903 | Ast.Code(x) -> let _ = top_level x in false
904
905 (* this is not '...', but a list of expr/statement/params, and
906 normally there should be no '...' inside them *)
907 | Ast.ExprDotsTag(x) -> dots (function _ -> ()) expression x; false
908 | Ast.ParamDotsTag(x) -> parameter_list x; false
909 | Ast.StmtDotsTag(x) -> dots (function _ -> pr "\n") (statement "") x; false
910 | Ast.DeclDotsTag(x) -> dots (function _ -> pr "\n") declaration x; false
911
912 | Ast.TypeCTag(x) -> typeC x; false
913 | Ast.ParamTag(x) -> parameterTypeDef x; false
914 | Ast.SgrepStartTag(x) -> failwith "unexpected start tag"
915 | Ast.SgrepEndTag(x) -> failwith "unexpected end tag"
916in
917
faf9a90c
C
918 anything := (function x -> let _ = pp_any x in ());
919
34e49164
C
920 (* todo? imitate what is in pretty_print_cocci ? *)
921 match xxs with
922 [] -> ()
923 | x::xs ->
924 (* for many tags, we must not do a newline before the first '+' *)
925 let isfn s =
926 match Ast.unwrap s with Ast.FunDecl _ -> true | _ -> false in
927 let unindent_before = function
928 (* need to get unindent before newline for } *)
929 (Ast.Token ("}",_)::_) -> true
930 | _ -> false in
931 let prnl x =
932 (if unindent_before x then unindent());
933 pr "\n" in
934 let newline_before _ =
935 if before = After
936 then
937 let hd = List.hd xxs in
938 match hd with
939 (Ast.StatementTag s::_) when isfn s -> pr "\n\n"
940 | (Ast.Rule_elemTag _::_) | (Ast.StatementTag _::_)
941 | (Ast.InitTag _::_)
942 | (Ast.DeclarationTag _::_) | (Ast.Token ("}",_)::_) -> prnl hd
943 | _ -> () in
944 let newline_after _ =
945 if before = Before
946 then
947 match List.rev(List.hd(List.rev xxs)) with
948 (Ast.StatementTag s::_) when isfn s -> pr "\n\n"
949 | (Ast.Rule_elemTag _::_) | (Ast.StatementTag _::_)
950 | (Ast.InitTag _::_)
951 | (Ast.DeclarationTag _::_) | (Ast.Token ("{",_)::_) -> pr "\n"
952 | _ -> () in
953 (* print a newline at the beginning, if needed *)
954 newline_before();
955 (* print a newline before each of the rest *)
956 let rec loop leading_newline indent_needed = function
957 [] -> ()
958 | x::xs ->
959 (if leading_newline
960 then
961 match (indent_needed,unindent_before x) with
962 (true,true) -> pr "\n"
963 | (true,false) -> pr "\n"; indent()
964 | (false,true) -> unindent(); pr "\n"
965 | (false,false) -> pr "\n");
966 let indent_needed =
967 List.fold_left (function indent_needed -> pp_any) false x in
968 loop true indent_needed xs in
969 loop false false (x::xs);
970 (* print a newline at the end, if needed *)
971 newline_after()
972