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