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