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