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