3 (*****************************************************************************)
4 (* mostly a copy paste of parsing_cocci/pretty_print_cocci.ml
5 * todo?: try to factorize ?
7 (*****************************************************************************)
11 let term s
= Ast.unwrap_mcode s
13 (* or perhaps can have in plus, for instance a Disj, but those Disj must be
14 * handled by interactive tool (by proposing alternatives)
16 exception CantBeInPlus
18 (*****************************************************************************)
20 type pos
= Before
| After
| InPlace
22 let rec pp_list_list_any (env
, pr
, pr_elem
, pr_space
, indent
, unindent
)
23 generating xxs before
=
25 (* Just to be able to copy paste the code from pretty_print_cocci.ml. *)
26 let print_string = pr
in
27 let close_box _
= () in
28 let print_space() = pr
" " in
29 let force_newline () = pr
"\n" in
31 let start_block () = force_newline(); indent
() in
32 let end_block () = unindent
(); force_newline () in
33 let print_string_box s
= print_string s
in
35 let print_option = Common.do_option
in
36 let print_between = Common.print_between in
38 let outdent _
= () (* should go to leftmost col, does nothing now *) in
41 Pretty_print_c.pretty_print_c pr_elem pr_space
42 force_newline indent
outdent unindent
in
44 (* --------------------------------------------------------------------- *)
45 (* Only for make_hrule, print plus code, unbound metavariables *)
47 (* avoid polyvariance problems *)
48 let anything : (Ast.anything -> unit) ref = ref (function _
-> ()) in
50 let rec print_anything = function
54 print_between force_newline print_anything_list stream
;
57 and print_anything_list
= function
60 | bef
::((aft
::_
) as rest
) ->
64 Ast.Rule_elemTag
(_
) | Ast.AssignOpTag
(_
) | Ast.BinaryOpTag
(_
)
65 | Ast.ArithOpTag
(_
) | Ast.LogicalOpTag
(_
)
66 | Ast.Token
("if",_
) | Ast.Token
("while",_
) -> true | _
-> false) or
68 Ast.Rule_elemTag
(_
) | Ast.AssignOpTag
(_
) | Ast.BinaryOpTag
(_
)
69 | Ast.ArithOpTag
(_
) | Ast.LogicalOpTag
(_
) | Ast.Token
("{",_
) -> true
71 if space then print_string " ";
72 print_anything_list rest
in
74 let print_around printer
term = function
75 Ast.NOTHING
-> printer
term
76 | Ast.BEFORE
(bef
) -> print_anything bef
; printer
term
77 | Ast.AFTER
(aft
) -> printer
term; print_anything aft
78 | Ast.BEFOREAFTER
(bef
,aft
) ->
79 print_anything bef
; printer
term; print_anything aft
in
81 let print_string_befaft fn fn1 x info
=
82 List.iter
(function (s
,_
,_
) -> fn1
(); print_string s
; force_newline())
85 List.iter
(function (s
,_
,_
) -> force_newline(); fn1
(); print_string s
)
88 let print_meta (r
,x
) = print_string x
in
90 let print_pos = function
91 Ast.MetaPos
(name
,_
,_
,_
,_
) ->
92 let name = Ast.unwrap_mcode
name in
93 print_string "@"; print_meta name
96 (* --------------------------------------------------------------------- *)
99 match (generating
,arg
) with
100 (false,(s
,info
,_
,_
)) ->
101 (* printing for transformation *)
102 (* Here we don't care about the annotation on s. *)
103 let print_comments lb comments
=
105 (function line_before
->
106 function (str
,line
,col
) ->
107 match line_before
with
108 None
-> print_string str
; Some line
109 | Some lb
when line
=|= lb
-> print_string str
; Some line
110 | _
-> print_string "\n"; print_string str
; Some line
)
112 let line_before = print_comments None info
.Ast.strbef
in
113 (match line_before with
115 | Some lb
when lb
=|= info
.Ast.line
-> ()
116 | _
-> print_string "\n");
118 let _ = print_comments (Some info
.Ast.line
) info
.Ast.straft
in
120 (* printing for rule generation *)
121 | (true, (x
, _, Ast.MINUS
(_,plus_stream
), pos
)) ->
124 print_anything plus_stream
125 | (true, (x
, _, Ast.CONTEXT
(_,plus_streams
), pos
)) ->
126 let fn x
= print_string "\n "; fn x
; print_pos pos
in
127 print_around fn x plus_streams
128 | (true,( x
, info
, Ast.PLUS
, pos
)) ->
129 let fn x
= print_string "\n+ "; fn x
; print_pos pos
in
130 print_string_befaft fn (function _ -> print_string "+ ") x info
134 (* --------------------------------------------------------------------- *)
136 let handle_metavar name fn =
137 match (Common.optionise
(fun () -> List.assoc
(term name) env
)) with
139 let name_string (_,s
) = s
in
141 then mcode (function _ -> pr
(name_string (term name))) name
144 (Printf.sprintf
"SP line %d: Not found a value in env for: %s"
145 (Ast_cocci.get_mcode_line
name) (name_string (term name)))
148 then mcode (function _ -> fn e
) name
151 (* --------------------------------------------------------------------- *)
152 let dots between
fn d
=
153 match Ast.unwrap d
with
154 Ast.DOTS
(l
) -> print_between between
fn l
155 | Ast.CIRCLES
(l
) -> print_between between
fn l
156 | Ast.STARS
(l
) -> print_between between
fn l
159 let nest_dots multi
fn f d
=
160 let mo s
= if multi
then "<+"^s
else "<"^s
in
161 let mc s
= if multi
then s^
"+>" else s^
">" in
162 match Ast.unwrap d
with
164 print_string (mo "..."); f
(); start_block();
165 print_between force_newline fn l
;
166 end_block(); print_string (mc "...")
168 print_string (mo "ooo"); f
(); start_block();
169 print_between force_newline fn l
;
170 end_block(); print_string (mc "ooo")
172 print_string (mo "***"); f
(); start_block();
173 print_between force_newline fn l
;
174 end_block(); print_string (mc "***")
177 (* --------------------------------------------------------------------- *)
181 match Ast.unwrap i
with
182 Ast.Id
(name) -> mcode print_string name
183 | Ast.MetaId
(name,_,_,_) ->
184 handle_metavar name (function
185 | (Ast_c.MetaIdVal id
) -> pr id
186 | _ -> raise Impossible
188 | Ast.MetaFunc
(name,_,_,_) ->
189 handle_metavar name (function
190 | (Ast_c.MetaFuncVal id
) -> pr id
191 | _ -> raise Impossible
193 | Ast.MetaLocalFunc
(name,_,_,_) ->
194 handle_metavar name (function
195 | (Ast_c.MetaLocalFuncVal id
) -> pr id
196 | _ -> raise Impossible
199 | Ast.OptIdent
(_) | Ast.UniqueIdent
(_) ->
204 (* --------------------------------------------------------------------- *)
207 let print_disj_list fn l
=
208 force_newline(); print_string "("; force_newline();
211 force_newline(); print_string "|"; force_newline())
213 force_newline(); print_string ")"; force_newline() in
215 let rec expression e
=
216 match Ast.unwrap e
with
217 Ast.Ident
(id
) -> ident id
219 | Ast.Constant
(const
) -> mcode constant const
220 | Ast.FunCall
(fn,lp
,args
,rp
) ->
221 expression fn; mcode print_string_box lp
;
222 dots (function _ -> ()) expression args
;
223 close_box(); mcode print_string rp
224 | Ast.Assignment
(left
,op
,right
,_) ->
225 expression left
; print_string " "; mcode assignOp op
;
226 print_string " "; expression right
227 | Ast.CondExpr
(exp1
,why
,exp2
,colon
,exp3
) ->
228 expression exp1
; print_string " "; mcode print_string why
;
229 print_option (function e
-> print_string " "; expression e
) exp2
;
230 print_string " "; mcode print_string colon
; expression exp3
231 | Ast.Postfix
(exp
,op
) -> expression exp
; mcode fixOp op
232 | Ast.Infix
(exp
,op
) -> mcode fixOp op
; expression exp
233 | Ast.Unary
(exp
,op
) -> mcode unaryOp op
; expression exp
234 | Ast.Binary
(left
,op
,right
) ->
235 expression left
; print_string " "; mcode binaryOp op
; print_string " ";
237 | Ast.Nested
(left
,op
,right
) -> failwith
"nested only in minus code"
238 | Ast.Paren
(lp
,exp
,rp
) ->
239 mcode print_string_box lp
; expression exp
; close_box();
240 mcode print_string rp
241 | Ast.ArrayAccess
(exp1
,lb
,exp2
,rb
) ->
242 expression exp1
; mcode print_string_box lb
; expression exp2
; close_box();
243 mcode print_string rb
244 | Ast.RecordAccess
(exp
,pt
,field
) ->
245 expression exp
; mcode print_string pt
; ident field
246 | Ast.RecordPtAccess
(exp
,ar
,field
) ->
247 expression exp
; mcode print_string ar
; ident field
248 | Ast.Cast
(lp
,ty
,rp
,exp
) ->
249 mcode print_string_box lp
; fullType ty
; close_box();
250 mcode print_string rp
; expression exp
251 | Ast.SizeOfExpr
(sizeof
,exp
) ->
252 mcode print_string sizeof
; expression exp
253 | Ast.SizeOfType
(sizeof
,lp
,ty
,rp
) ->
254 mcode print_string sizeof
;
255 mcode print_string_box lp
; fullType ty
; close_box();
256 mcode print_string rp
257 | Ast.TypeExp
(ty
) -> fullType ty
259 | Ast.MetaErr
(name,_,_,_) ->
260 failwith
"metaErr not handled"
262 | Ast.MetaExpr
(name,_,_,_typedontcare
,_formdontcare
,_) ->
263 handle_metavar name (function
264 | Ast_c.MetaExprVal exp
->
265 pretty_print_c.Pretty_print_c.expression exp
266 | _ -> raise Impossible
269 | Ast.MetaExprList
(name,_,_,_) ->
270 handle_metavar name (function
271 | Ast_c.MetaExprListVal args
->
272 pretty_print_c.Pretty_print_c.arg_list args
273 | _ -> raise Impossible
276 | Ast.EComma
(cm
) -> mcode print_string cm
; print_space()
278 | Ast.DisjExpr
(exp_list
) ->
280 then print_disj_list expression exp_list
281 else raise CantBeInPlus
282 | Ast.NestExpr
(expr_dots
,Some whencode
,multi
) when generating
->
283 nest_dots multi
expression
284 (function _ -> print_string " when != "; expression whencode
)
286 | Ast.NestExpr
(expr_dots
,None
,multi
) when generating
->
287 nest_dots multi
expression (function _ -> ()) expr_dots
288 | Ast.NestExpr
(_) -> raise CantBeInPlus
289 | Ast.Edots
(dots,Some whencode
)
290 | Ast.Ecircles
(dots,Some whencode
)
291 | Ast.Estars
(dots,Some whencode
) ->
294 (mcode print_string dots;
295 print_string " when != ";
297 else raise CantBeInPlus
298 | Ast.Edots
(dots,None
)
299 | Ast.Ecircles
(dots,None
)
300 | Ast.Estars
(dots,None
) ->
302 then mcode print_string dots
303 else raise CantBeInPlus
305 | Ast.OptExp
(exp
) | Ast.UniqueExp
(exp
) ->
308 and unaryOp
= function
309 Ast.GetRef
-> print_string "&"
310 | Ast.DeRef
-> print_string "*"
311 | Ast.UnPlus
-> print_string "+"
312 | Ast.UnMinus
-> print_string "-"
313 | Ast.Tilde
-> print_string "~"
314 | Ast.Not
-> print_string "!"
316 and assignOp
= function
317 Ast.SimpleAssign
-> print_string "="
318 | Ast.OpAssign
(aop
) -> arithOp aop
; print_string "="
321 Ast.Dec
-> print_string "--"
322 | Ast.Inc
-> print_string "++"
324 and binaryOp
= function
325 Ast.Arith
(aop
) -> arithOp aop
326 | Ast.Logical
(lop
) -> logicalOp lop
328 and arithOp
= function
329 Ast.Plus
-> print_string "+"
330 | Ast.Minus
-> print_string "-"
331 | Ast.Mul
-> print_string "*"
332 | Ast.Div
-> print_string "/"
333 | Ast.Mod
-> print_string "%"
334 | Ast.DecLeft
-> print_string "<<"
335 | Ast.DecRight
-> print_string ">>"
336 | Ast.And
-> print_string "&"
337 | Ast.Or
-> print_string "|"
338 | Ast.Xor
-> print_string "^"
340 and logicalOp
= function
341 Ast.Inf
-> print_string "<"
342 | Ast.Sup
-> print_string ">"
343 | Ast.InfEq
-> print_string "<="
344 | Ast.SupEq
-> print_string ">="
345 | Ast.Eq
-> print_string "=="
346 | Ast.NotEq
-> print_string "!="
347 | Ast.AndLog
-> print_string "&&"
348 | Ast.OrLog
-> print_string "||"
350 and constant
= function
351 Ast.String
(s
) -> print_string "\""; print_string s
; print_string "\""
352 | Ast.Char
(s
) -> print_string s
353 | Ast.Int
(s
) -> print_string s
354 | Ast.Float
(s
) -> print_string s
356 (* --------------------------------------------------------------------- *)
361 match Ast.unwrap ft
with
363 print_option (mcode const_vol
) cv
;
365 | Ast.DisjType
_ -> failwith
"can't be in plus"
366 | Ast.OptType
(_) | Ast.UniqueType
(_) ->
369 and print_function_pointer
(ty
,lp1
,star
,rp1
,lp2
,params
,rp2
) fn =
370 fullType ty
; mcode print_string lp1
; mcode print_string star
; fn();
371 mcode print_string rp1
; mcode print_string lp1
;
372 parameter_list params
; mcode print_string rp2
374 and print_function_type
(ty
,lp1
,params
,rp1
) fn =
375 print_option fullType ty
; fn(); mcode print_string lp1
;
376 parameter_list params
; mcode print_string rp1
379 match Ast.unwrap ty
with
380 Ast.BaseType
(ty
,strings
) ->
381 print_between pr_space
(mcode print_string) strings
382 | Ast.SignedT
(sgn
,Some ty
) -> mcode sign sgn
; typeC ty
383 | Ast.SignedT
(sgn
,None
) -> mcode signns sgn
384 | Ast.Pointer
(ty
,star
) -> fullType ty
; ft_space ty
; mcode print_string star
385 | Ast.FunctionPointer
(ty
,lp1
,star
,rp1
,lp2
,params
,rp2
) ->
386 print_function_pointer
(ty
,lp1
,star
,rp1
,lp2
,params
,rp2
)
388 | Ast.FunctionType
(am
,ty
,lp1
,params
,rp1
) ->
389 print_function_type
(ty
,lp1
,params
,rp1
) (function _ -> ())
390 | Ast.Array
(ty
,lb
,size
,rb
) ->
391 fullType ty
; mcode print_string lb
; print_option expression size
;
392 mcode print_string rb
393 | Ast.EnumName
(kind
,name) -> mcode print_string kind
; print_string " ";
395 | Ast.StructUnionName
(kind
,name) ->
396 mcode structUnion kind
;
397 print_option ident name
398 | Ast.StructUnionDef
(ty
,lb
,decls
,rb
) ->
400 mcode print_string lb
;
401 dots force_newline declaration decls
;
402 mcode print_string rb
403 | Ast.TypeName
(name)-> mcode print_string name
404 | Ast.MetaType
(name,_,_) ->
405 handle_metavar name (function
406 Ast_c.MetaTypeVal exp
->
407 pretty_print_c.Pretty_print_c.ty exp
408 | _ -> raise Impossible
)
410 and baseType
= function
411 Ast.VoidType
-> print_string "void"
412 | Ast.CharType
-> print_string "char"
413 | Ast.ShortType
-> print_string "short"
414 | Ast.IntType
-> print_string "int"
415 | Ast.DoubleType
-> print_string "double"
416 | Ast.FloatType
-> print_string "float"
417 | Ast.LongType
-> print_string "long"
418 | Ast.LongLongType
-> print_string "long long"
420 and structUnion
= function
421 Ast.Struct
-> print_string "struct "
422 | Ast.Union
-> print_string "union "
425 Ast.Signed
-> print_string "signed "
426 | Ast.Unsigned
-> print_string "unsigned "
428 and signns
= function (* no space, like a normal type *)
429 Ast.Signed
-> print_string "signed"
430 | Ast.Unsigned
-> print_string "unsigned"
433 and const_vol
= function
434 Ast.Const
-> print_string "const "
435 | Ast.Volatile
-> print_string "volatile "
437 (* --------------------------------------------------------------------- *)
438 (* Function declaration *)
440 and storage
= function
441 Ast.Static
-> print_string "static "
442 | Ast.Auto
-> print_string "auto "
443 | Ast.Register
-> print_string "register "
444 | Ast.Extern
-> print_string "extern "
446 (* --------------------------------------------------------------------- *)
447 (* Variable declaration *)
449 and print_named_type ty id
=
450 match Ast.unwrap ty
with
451 Ast.Type
(None
,ty1
) ->
452 (match Ast.unwrap ty1
with
453 Ast.FunctionPointer
(ty
,lp1
,star
,rp1
,lp2
,params
,rp2
) ->
454 print_function_pointer
(ty
,lp1
,star
,rp1
,lp2
,params
,rp2
)
455 (function _ -> print_string " "; ident id
)
456 | Ast.FunctionType
(am
,ty
,lp1
,params
,rp1
) ->
457 print_function_type
(ty
,lp1
,params
,rp1
)
458 (function _ -> print_string " "; ident id
)
459 | Ast.Array
(_,_,_,_) ->
461 match Ast.unwrap ty
with
462 Ast.Array
(ty
,lb
,size
,rb
) ->
463 (match Ast.unwrap ty
with
468 mcode print_string lb
;
469 print_option expression size
;
470 mcode print_string rb
)
471 | _ -> failwith
"complex array types not supported")
472 | _ -> typeC ty
; ty_space ty
; ident id
; k
() in
473 loop ty1
(function _ -> ())
474 (*| should have a case here for pointer to array or function type
475 that would put ( * ) around the variable. This makes one wonder
476 why we really need a special case for function pointer *)
477 | _ -> fullType ty
; ft_space ty
; ident id
)
478 | _ -> fullType ty
; ft_space ty
; ident id
481 match Ast.unwrap ty
with
482 Ast.Pointer
(_,_) -> ()
486 match Ast.unwrap ty
with
488 (match Ast.unwrap ty
with
489 Ast.Pointer
(_,_) -> ()
490 | _ -> print_space())
494 match Ast.unwrap d
with
495 Ast.Init
(stg
,ty
,id
,eq
,ini
,sem
) ->
496 print_option (mcode storage
) stg
;
497 print_named_type ty id
;
498 print_string " "; mcode print_string eq
;
499 print_string " "; initialiser
true ini
; mcode print_string sem
500 | Ast.UnInit
(stg
,ty
,id
,sem
) ->
501 print_option (mcode storage
) stg
;
502 print_named_type ty id
;
503 mcode print_string sem
504 | Ast.MacroDecl
(name,lp
,args
,rp
,sem
) ->
505 ident name; mcode print_string_box lp
;
506 dots (function _ -> ()) expression args
;
507 close_box(); mcode print_string rp
; mcode print_string sem
508 | Ast.TyDecl
(ty
,sem
) -> fullType ty
; mcode print_string sem
509 | Ast.Typedef
(stg
,ty
,id
,sem
) ->
510 mcode print_string stg
;
511 fullType ty
; typeC id
;
512 mcode print_string sem
513 | Ast.DisjDecl
(_) | Ast.MetaDecl
(_,_,_) -> raise CantBeInPlus
514 | Ast.Ddots
(_,_) -> raise CantBeInPlus
515 | Ast.OptDecl
(decl
) | Ast.UniqueDecl
(decl
) ->
518 (* --------------------------------------------------------------------- *)
521 and initialiser nlcomma i
=
522 match Ast.unwrap i
with
523 Ast.MetaInit
(name,_,_) ->
524 handle_metavar name (function
525 Ast_c.MetaInitVal ini
->
526 pretty_print_c.Pretty_print_c.init ini
527 | _ -> raise Impossible
)
528 | Ast.InitExpr
(exp
) -> expression exp
529 | Ast.InitList
(lb
,initlist
,rb
,[]) ->
530 mcode print_string lb
; start_block();
531 (* awkward, because the comma is separate from the initialiser *)
532 let rec loop = function
534 | [x
] -> initialiser
false x
535 | x
::xs
-> initialiser nlcomma x
; loop xs
in
537 end_block(); mcode print_string rb
538 | Ast.InitList
(lb
,initlist
,rb
,_) -> failwith
"unexpected whencode in plus"
539 | Ast.InitGccExt
(designators
,eq
,ini
) ->
540 List.iter designator designators
; print_string " ";
541 mcode print_string eq
; print_string " "; initialiser nlcomma ini
542 | Ast.InitGccName
(name,eq
,ini
) ->
543 ident name; mcode print_string eq
; initialiser nlcomma ini
544 | Ast.IComma
(comma
) ->
545 mcode print_string comma
;
546 if nlcomma
then force_newline()
547 | Ast.OptIni
(ini
) | Ast.UniqueIni
(ini
) ->
550 and designator
= function
551 Ast.DesignatorField
(dot
,id
) -> mcode print_string dot
; ident id
552 | Ast.DesignatorIndex
(lb
,exp
,rb
) ->
553 mcode print_string lb
; expression exp
; mcode print_string rb
554 | Ast.DesignatorRange
(lb
,min
,dots,max
,rb
) ->
555 mcode print_string lb
; expression min
; mcode print_string dots;
556 expression max
; mcode print_string rb
558 (* --------------------------------------------------------------------- *)
561 and parameterTypeDef p
=
562 match Ast.unwrap p
with
563 Ast.VoidParam
(ty
) -> fullType ty
564 | Ast.Param
(ty
,Some id
) -> print_named_type ty id
565 | Ast.Param
(ty
,None
) -> fullType ty
567 | Ast.MetaParam
(name,_,_) ->
568 failwith
"not handling MetaParam"
569 | Ast.MetaParamList
(name,_,_,_) ->
570 failwith
"not handling MetaParamList"
572 | Ast.PComma
(cm
) -> mcode print_string cm
; print_space()
573 | Ast.Pdots
(dots) | Ast.Pcircles
(dots) when generating
->
574 mcode print_string dots
575 | Ast.Pdots
(dots) | Ast.Pcircles
(dots) -> raise CantBeInPlus
576 | Ast.OptParam
(param
) | Ast.UniqueParam
(param
) -> raise CantBeInPlus
578 and parameter_list l
= dots (function _ -> ()) parameterTypeDef l
582 (* --------------------------------------------------------------------- *)
585 let rec inc_file = function
588 print_between (function _ -> print_string "/") inc_elem elems
;
590 | Ast.NonLocal
(elems
) ->
592 print_between (function _ -> print_string "/") inc_elem elems
;
595 and inc_elem
= function
596 Ast.IncPath s
-> print_string s
597 | Ast.IncDots
-> print_string "..."
599 (* --------------------------------------------------------------------- *)
602 and rule_elem arity re
=
603 match Ast.unwrap re
with
604 Ast.FunHeader
(_,_,fninfo
,name,lp
,params
,rp
) ->
605 print_string arity
; List.iter print_fninfo fninfo
;
606 ident name; mcode print_string_box lp
;
607 parameter_list params
; close_box(); mcode print_string rp
;
609 | Ast.Decl
(_,_,decl
) -> print_string arity
; declaration decl
611 | Ast.SeqStart
(brace
) ->
612 print_string arity
; mcode print_string brace
; start_block()
613 | Ast.SeqEnd
(brace
) ->
614 end_block(); print_string arity
; mcode print_string brace
616 | Ast.ExprStatement
(exp
,sem
) ->
617 print_string arity
; expression exp
; mcode print_string sem
619 | Ast.IfHeader
(iff
,lp
,exp
,rp
) ->
621 mcode print_string iff
; print_string " "; mcode print_string_box lp
;
622 expression exp
; close_box(); mcode print_string rp
624 print_string arity
; mcode print_string els
626 | Ast.WhileHeader
(whl
,lp
,exp
,rp
) ->
628 mcode print_string whl
; print_string " "; mcode print_string_box lp
;
629 expression exp
; close_box(); mcode print_string rp
631 print_string arity
; mcode print_string d
632 | Ast.WhileTail
(whl
,lp
,exp
,rp
,sem
) ->
634 mcode print_string whl
; print_string " "; mcode print_string_box lp
;
635 expression exp
; close_box(); mcode print_string rp
;
636 mcode print_string sem
637 | Ast.ForHeader
(fr
,lp
,e1
,sem1
,e2
,sem2
,e3
,rp
) ->
639 mcode print_string fr
; mcode print_string_box lp
;
640 print_option expression e1
; mcode print_string sem1
;
641 print_option expression e2
; mcode print_string sem2
;
642 print_option expression e3
; close_box();
643 mcode print_string rp
644 | Ast.IteratorHeader
(nm
,lp
,args
,rp
) ->
646 ident nm
; print_string " "; mcode print_string_box lp
;
647 dots (function _ -> ()) expression args
; close_box();
648 mcode print_string rp
650 | Ast.SwitchHeader
(switch
,lp
,exp
,rp
) ->
652 mcode print_string switch
; print_string " "; mcode print_string_box lp
;
653 expression exp
; close_box(); mcode print_string rp
655 | Ast.Break
(br
,sem
) ->
656 print_string arity
; mcode print_string br
; mcode print_string sem
657 | Ast.Continue
(cont
,sem
) ->
658 print_string arity
; mcode print_string cont
; mcode print_string sem
659 | Ast.Label
(l
,dd
) -> ident l
; mcode print_string dd
660 | Ast.Goto
(goto
,l
,sem
) ->
661 mcode print_string goto
; ident l
; mcode print_string sem
662 | Ast.Return
(ret
,sem
) ->
663 print_string arity
; mcode print_string ret
;
664 mcode print_string sem
665 | Ast.ReturnExpr
(ret
,exp
,sem
) ->
666 print_string arity
; mcode print_string ret
; print_string " ";
667 expression exp
; mcode print_string sem
669 | Ast.Exp
(exp
) -> print_string arity
; expression exp
670 | Ast.TopExp
(exp
) -> print_string arity
; expression exp
671 | Ast.Ty
(ty
) -> print_string arity
; fullType ty
672 | Ast.TopInit
(init
) -> initialiser
false init
673 | Ast.Include
(inc
,s
) ->
674 mcode print_string inc
; print_string " "; mcode inc_file s
675 | Ast.DefineHeader
(def
,id
,params
) ->
676 mcode print_string def
; print_string " "; ident id
;
677 print_define_parameters params
678 | Ast.Default
(def
,colon
) ->
679 mcode print_string def
; mcode print_string colon
; print_string " "
680 | Ast.Case
(case
,exp
,colon
) ->
681 mcode print_string case
; print_string " "; expression exp
;
682 mcode print_string colon
; print_string " "
683 | Ast.DisjRuleElem
(res
) ->
687 force_newline(); print_string "("; force_newline();
689 (function _ -> force_newline(); print_string "|"; force_newline())
692 force_newline(); print_string ")")
693 else raise CantBeInPlus
695 | Ast.MetaRuleElem
(name,_,_) ->
698 | Ast.MetaStmt
(name,_,_,_) ->
699 handle_metavar name (function
700 | Ast_c.MetaStmtVal stm
->
701 pretty_print_c.Pretty_print_c.statement stm
702 | _ -> raise Impossible
704 | Ast.MetaStmtList
(name,_,_) ->
706 "MetaStmtList not supported (not even in ast_c metavars binding)"
708 and print_define_parameters params
=
709 match Ast.unwrap params
with
711 | Ast.DParams
(lp
,params
,rp
) ->
712 mcode print_string lp
;
713 dots (function _ -> ()) print_define_param params
; mcode print_string rp
715 and print_define_param param
=
716 match Ast.unwrap param
with
717 Ast.DParam
(id
) -> ident id
718 | Ast.DPComma
(comma
) -> mcode print_string comma
719 | Ast.DPdots
(dots) -> mcode print_string dots
720 | Ast.DPcircles
(circles
) -> mcode print_string circles
721 | Ast.OptDParam
(dp
) -> print_string "?"; print_define_param dp
722 | Ast.UniqueDParam
(dp
) -> print_string "!"; print_define_param dp
724 and print_fninfo
= function
725 Ast.FStorage
(stg
) -> mcode storage stg
726 | Ast.FType
(ty
) -> fullType ty
727 | Ast.FInline
(inline
) -> mcode print_string inline
; print_string " "
728 | Ast.FAttr
(attr
) -> mcode print_string attr
; print_string " " in
730 let indent_if_needed s f
=
731 match Ast.unwrap s
with
732 Ast.Seq
(lbrace
,decls
,body
,rbrace
) -> pr_space
(); f
()
734 (*no newline at the end - someone else will do that*)
735 start_block(); f
(); unindent
() in
737 let rec statement arity s
=
738 match Ast.unwrap s
with
739 Ast.Seq
(lbrace
,decls
,body
,rbrace
) ->
740 rule_elem arity lbrace
;
741 dots force_newline (statement arity
) decls
;
742 dots force_newline (statement arity
) body
;
743 rule_elem arity rbrace
745 | Ast.IfThen
(header
,branch
,_) ->
746 rule_elem arity header
;
747 indent_if_needed branch
(function _ -> statement arity branch
)
748 | Ast.IfThenElse
(header
,branch1
,els
,branch2
,_) ->
749 rule_elem arity header
;
750 indent_if_needed branch1
(function _ -> statement arity branch1
);
753 indent_if_needed branch2
(function _ -> statement arity branch2
)
755 | Ast.While
(header
,body
,_) ->
756 rule_elem arity header
;
757 indent_if_needed body
(function _ -> statement arity body
)
758 | Ast.Do
(header
,body
,tail
) ->
759 rule_elem arity header
;
760 indent_if_needed body
(function _ -> statement arity body
);
762 | Ast.For
(header
,body
,_) ->
763 rule_elem arity header
;
764 indent_if_needed body
(function _ -> statement arity body
)
765 | Ast.Iterator
(header
,body
,(_,_,_,aft
)) ->
766 rule_elem arity header
;
767 indent_if_needed body
(function _ -> statement arity body
);
768 mcode (function _ -> ()) ((),Ast.no_info
,aft
,Ast.NoMetaPos
)
770 | Ast.Switch
(header
,lb
,cases
,rb
) ->
771 rule_elem arity header
; print_string " "; rule_elem arity lb
;
772 List.iter
(function x
-> case_line arity x
; force_newline()) cases
;
775 | Ast.Atomic
(re
) -> rule_elem arity re
777 | Ast.FunDecl
(header
,lbrace
,decls
,body
,rbrace
) ->
778 rule_elem arity header
; rule_elem arity lbrace
;
779 dots force_newline (statement arity
) decls
;
780 dots force_newline (statement arity
) body
; rule_elem arity rbrace
782 | Ast.Define
(header
,body
) ->
783 rule_elem arity header
; print_string " ";
784 dots force_newline (statement arity
) body
786 | Ast.Disj
([stmt_dots
]) ->
790 dots force_newline (statement arity
) stmt_dots
)
791 else raise CantBeInPlus
792 | Ast.Disj
(stmt_dots_list
) -> (* ignores newline directive for readability *)
796 force_newline(); print_string "("; force_newline();
798 (function _ -> force_newline();print_string "|"; force_newline())
799 (dots force_newline (statement arity
))
801 force_newline(); print_string ")")
802 else raise CantBeInPlus
803 | Ast.Nest
(stmt_dots
,whn
,multi
,_,_) when generating
->
805 nest_dots multi
(statement arity
)
807 print_between force_newline
808 (whencode
(dots force_newline (statement "")) (statement "")) whn
;
811 | Ast.Nest
(_) -> raise CantBeInPlus
812 | Ast.Dots
(d
,whn
,_,_) | Ast.Circles
(d
,whn
,_,_) | Ast.Stars
(d
,whn
,_,_) ->
815 (print_string arity
; mcode print_string d
;
816 print_between force_newline
817 (whencode
(dots force_newline (statement "")) (statement "")) whn
;
819 else raise CantBeInPlus
821 | Ast.OptStm
(s
) | Ast.UniqueStm
(s
) ->
824 and whencode notfn alwaysfn
= function
826 print_string " WHEN != "; notfn a
827 | Ast.WhenAlways a
->
828 print_string " WHEN = "; alwaysfn a
829 | Ast.WhenModifier x
-> print_string " WHEN "; print_when_modif x
830 | Ast.WhenNotTrue a
->
831 print_string " WHEN != TRUE "; rule_elem
"" a
832 | Ast.WhenNotFalse a
->
833 print_string " WHEN != FALSE "; rule_elem
"" a
835 and print_when_modif
= function
836 | Ast.WhenAny
-> print_string "ANY"
837 | Ast.WhenStrict
-> print_string "STRICT"
838 | Ast.WhenForall
-> print_string "FORALL"
839 | Ast.WhenExists
-> print_string "EXISTS"
841 and case_line arity c
=
842 match Ast.unwrap c
with
843 Ast.CaseLine
(header
,code
) ->
844 rule_elem arity header
; print_string " ";
845 dots force_newline (statement arity
) code
846 | Ast.OptCase
(case
) -> raise CantBeInPlus
in
849 match Ast.unwrap t
with
850 Ast.FILEINFO
(old_file
,new_file
) -> raise CantBeInPlus
851 | Ast.DECL
(stmt
) -> statement "" stmt
852 | Ast.CODE
(stmt_dots
) -> dots force_newline (statement "") stmt_dots
853 | Ast.ERRORWORDS
(exps
) -> raise CantBeInPlus
858 print_between (function _ -> force_newline(); force_newline()) top_level
862 let if_open_brace = function "{" -> true | _ -> false in
864 (* boolean result indicates whether an indent is needed *)
865 let rec pp_any = function
866 (* assert: normally there is only CONTEXT NOTHING tokens in any *)
867 Ast.FullTypeTag
(x
) -> fullType x
; false
868 | Ast.BaseTypeTag
(x
) -> baseType x
; false
869 | Ast.StructUnionTag
(x
) -> structUnion x
; false
870 | Ast.SignTag
(x
) -> sign x
; false
872 | Ast.IdentTag
(x
) -> ident x
; false
874 | Ast.ExpressionTag
(x
) -> expression x
; false
876 | Ast.ConstantTag
(x
) -> constant x
; false
877 | Ast.UnaryOpTag
(x
) -> unaryOp x
; false
878 | Ast.AssignOpTag
(x
) -> assignOp x
; false
879 | Ast.FixOpTag
(x
) -> fixOp x
; false
880 | Ast.BinaryOpTag
(x
) -> binaryOp x
; false
881 | Ast.ArithOpTag
(x
) -> arithOp x
; false
882 | Ast.LogicalOpTag
(x
) -> logicalOp x
; false
884 | Ast.InitTag
(x
) -> initialiser
false x
; false
885 | Ast.DeclarationTag
(x
) -> declaration x
; false
887 | Ast.StorageTag
(x
) -> storage x
; false
888 | Ast.IncFileTag
(x
) -> inc_file x
; false
890 | Ast.Rule_elemTag
(x
) -> rule_elem
"" x
; false
891 | Ast.StatementTag
(x
) -> statement "" x
; false
892 | Ast.CaseLineTag
(x
) -> case_line
"" x
; false
894 | Ast.ConstVolTag
(x
) -> const_vol x
; false
895 | Ast.Pragma
(xs
) -> print_between force_newline print_string xs
; false
896 | Ast.Token
(x
,None
) -> print_string x
; if_open_brace x
897 | Ast.Token
(x
,Some info
) ->
904 (* if x ==~ Common.regexp_alpha then print_string " "; *)
906 (*"return" |*) "else" -> print_string " "
908 (let nomcodekind = Ast.CONTEXT
(Ast.DontCarePos
,Ast.NOTHING
) in
909 (x
,info
,nomcodekind,Ast.NoMetaPos
));
912 | Ast.Code
(x
) -> let _ = top_level x
in false
914 (* this is not '...', but a list of expr/statement/params, and
915 normally there should be no '...' inside them *)
916 | Ast.ExprDotsTag
(x
) -> dots (function _ -> ()) expression x
; false
917 | Ast.ParamDotsTag
(x
) -> parameter_list x
; false
918 | Ast.StmtDotsTag
(x
) -> dots (function _ -> pr
"\n") (statement "") x
; false
919 | Ast.DeclDotsTag
(x
) -> dots (function _ -> pr
"\n") declaration x
; false
921 | Ast.TypeCTag
(x
) -> typeC x
; false
922 | Ast.ParamTag
(x
) -> parameterTypeDef x
; false
923 | Ast.SgrepStartTag
(x
) -> failwith
"unexpected start tag"
924 | Ast.SgrepEndTag
(x
) -> failwith
"unexpected end tag"
927 anything := (function x
-> let _ = pp_any x
in ());
929 (* todo? imitate what is in pretty_print_cocci ? *)
933 (* for many tags, we must not do a newline before the first '+' *)
935 match Ast.unwrap s
with Ast.FunDecl
_ -> true | _ -> false in
936 let unindent_before = function
937 (* need to get unindent before newline for } *)
938 (Ast.Token
("}",_)::_) -> true
941 (if unindent_before x
then unindent
());
943 let newline_before _ =
946 let hd = List.hd xxs
in
948 (Ast.StatementTag s
::_) when isfn s
-> pr
"\n\n"
950 | (Ast.Rule_elemTag
_::_) | (Ast.StatementTag
_::_)
952 | (Ast.DeclarationTag
_::_) | (Ast.Token
("}",_)::_) -> prnl hd
954 let newline_after _ =
957 match List.rev
(List.hd(List.rev xxs
)) with
958 (Ast.StatementTag s
::_) ->
959 if isfn s
then pr
"\n\n" else pr
"\n"
961 | (Ast.Rule_elemTag
_::_) | (Ast.InitTag
_::_)
962 | (Ast.DeclarationTag
_::_) | (Ast.Token
("{",_)::_) -> pr
"\n"
964 (* print a newline at the beginning, if needed *)
966 (* print a newline before each of the rest *)
967 let rec loop leading_newline indent_needed
= function
972 match (indent_needed
,unindent_before x
) with
973 (true,true) -> pr
"\n"
974 | (true,false) -> pr
"\n"; indent
()
975 | (false,true) -> unindent
(); pr
"\n"
976 | (false,false) -> pr
"\n");
978 List.fold_left
(function indent_needed -> pp_any) false x
in
979 loop true indent_needed xs
in
980 loop false false (x
::xs
);
981 (* print a newline at the end, if needed *)