* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License (GPL)
* version 2 as published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* file license.txt for more details.
- *
+ *
* This file was part of Coccinelle.
*)
open Common
(*****************************************************************************)
-(* mostly a copy paste of parsing_cocci/pretty_print_cocci.ml
+(* mostly a copy paste of parsing_cocci/pretty_print_cocci.ml
* todo?: try to factorize ?
*)
(*****************************************************************************)
let term s = Ast.unwrap_mcode s
-(* or perhaps can have in plus, for instance a Disj, but those Disj must be
- * handled by interactive tool (by proposing alternatives)
+(* or perhaps can have in plus, for instance a Disj, but those Disj must be
+ * handled by interactive tool (by proposing alternatives)
*)
exception CantBeInPlus
let unknown = -1
-let rec pp_list_list_any
+let rec do_all
(env, pr, pr_celem, pr_cspace, pr_space, pr_arity, pr_barrier,
indent, unindent)
generating xxs before =
pr s line lcol rcol in
let print_text s = pr s unknown unknown unknown in
let close_box _ = () in
-let force_newline () = print_text "\n" in
+let force_newline _ = print_text "\n" in
let start_block () = force_newline(); indent() in
let end_block () = unindent(); force_newline () in
let print_string_box s = print_string s in
let print_option = Common.do_option in
+let print_option_prespace fn = function
+ None -> ()
+ | Some x -> pr_space(); fn x in
+let print_option_space fn = function
+ None -> ()
+ | Some x -> fn x; pr_space() in
let print_between = Common.print_between in
let outdent _ = () (* should go to leftmost col, does nothing now *) in
let print_around printer term = function
Ast.NOTHING -> printer term
- | Ast.BEFORE(bef) -> print_anything bef; printer term
- | Ast.AFTER(aft) -> printer term; print_anything aft
- | Ast.BEFOREAFTER(bef,aft) ->
+ | Ast.BEFORE(bef,_) -> print_anything bef; printer term
+ | Ast.AFTER(aft,_) -> printer term; print_anything aft
+ | Ast.BEFOREAFTER(bef,aft,_) ->
print_anything bef; printer term; print_anything aft in
let print_string_befaft fn fn1 x info =
List.iter
(function (s,ln,col) -> force_newline(); fn1(); print_string s ln col)
info.Ast.straft in
-
let print_meta (r,x) = print_text x in
let print_pos = function
| _ -> force_newline());
fn s line lcol;
let _ = print_comments (Some info.Ast.line) info.Ast.straft in
+ (* newline after a pragma
+ should really store parsed versions of the strings, but make a cheap
+ effort here
+ print_comments takes care of interior newlines *)
+ (match List.rev info.Ast.straft with
+ (str,_,_)::_ when String.length str > 0 && String.get str 0 = '#' ->
+ force_newline()
+ | _ -> ());
()
(* printing for rule generation *)
| (true, Ast.MINUS(_,_,_,plus_stream)) ->
| (true, Ast.CONTEXT(_,plus_streams)) ->
let fn s = force_newline(); fn s line lcol; print_pos pos in
print_around fn s plus_streams
- | (true,Ast.PLUS) ->
+ | (true,Ast.PLUS Ast.ONE) ->
let fn s =
force_newline(); print_text "+ "; fn s line lcol; print_pos pos in
print_string_befaft fn (function _ -> print_text "+ ") s info
+ | (true,Ast.PLUS Ast.MANY) ->
+ let fn s =
+ force_newline(); print_text "++ "; fn s line lcol; print_pos pos in
+ print_string_befaft fn (function _ -> print_text "++ ") s info
in
let rec ident i =
match Ast.unwrap i with
- Ast.Id(name) -> mcode print_string name
- | Ast.MetaId(name,_,_,_) ->
- handle_metavar name (function
- | (Ast_c.MetaIdVal id) -> print_text id
- | _ -> raise Impossible
- )
- | Ast.MetaFunc(name,_,_,_) ->
- handle_metavar name (function
- | (Ast_c.MetaFuncVal id) -> print_text id
- | _ -> raise Impossible
- )
- | Ast.MetaLocalFunc(name,_,_,_) ->
- handle_metavar name (function
- | (Ast_c.MetaLocalFuncVal id) -> print_text id
- | _ -> raise Impossible
- )
-
- | Ast.OptIdent(_) | Ast.UniqueIdent(_) ->
- raise CantBeInPlus
+ Ast.Id(name) -> mcode print_string name
+ | Ast.MetaId(name,_,_,_) ->
+ handle_metavar name (function
+ | (Ast_c.MetaIdVal id) -> print_text id
+ | _ -> raise Impossible
+ )
+ | Ast.MetaFunc(name,_,_,_) ->
+ handle_metavar name (function
+ | (Ast_c.MetaFuncVal id) -> print_text id
+ | _ -> raise Impossible
+ )
+ | Ast.MetaLocalFunc(name,_,_,_) ->
+ handle_metavar name (function
+ | (Ast_c.MetaLocalFuncVal id) -> print_text id
+ | _ -> raise Impossible
+ )
+
+ | Ast.OptIdent(_) | Ast.UniqueIdent(_) ->
+ raise CantBeInPlus
in
| Ast.Constant(const) -> mcode constant const
| Ast.FunCall(fn,lp,args,rp) ->
expression fn; mcode print_string_box lp;
- dots (function _ -> ()) expression args;
+ let comma e =
+ expression e;
+ match Ast.unwrap e with
+ Ast.EComma(cm) -> pr_space()
+ | _ -> () in
+ dots (function _ -> ()) comma args;
close_box(); mcode print_string rp
| Ast.Assignment(left,op,right,_) ->
expression left; pr_space(); mcode assignOp op;
| _ -> raise Impossible
)
- | Ast.EComma(cm) -> mcode print_string cm; pr_space()
+ | Ast.EComma(cm) -> mcode print_string cm
| Ast.DisjExpr(exp_list) ->
if generating
and fullType ft =
match Ast.unwrap ft with
- Ast.Type(cv,ty) ->
- print_option (mcode const_vol) cv;
- typeC ty
+ Ast.Type(cv,ty) -> print_option_space (mcode const_vol) cv; typeC ty
| Ast.DisjType _ -> failwith "can't be in plus"
| Ast.OptType(_) | Ast.UniqueType(_) ->
raise CantBeInPlus
match Ast.unwrap ty with
Ast.BaseType(ty,strings) ->
print_between pr_space (mcode print_string) strings
- | Ast.SignedT(sgn,Some ty) -> mcode sign sgn; typeC ty
- | Ast.SignedT(sgn,None) -> mcode signns sgn
+ | Ast.SignedT(sgn,ty) -> mcode sign sgn; print_option_prespace typeC ty
| Ast.Pointer(ty,star) -> fullType ty; ft_space ty; mcode print_string star
| Ast.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
print_function_pointer (ty,lp1,star,rp1,lp2,params,rp2)
| Ast.EnumName(kind,name) -> mcode print_string kind; pr_space();
ident name
| Ast.StructUnionName(kind,name) ->
- mcode structUnion kind;
- print_option ident name
+ mcode structUnion kind; print_option_prespace ident name
| Ast.StructUnionDef(ty,lb,decls,rb) ->
fullType ty; ft_space ty;
mcode print_string lb;
| Ast.LongLongType -> print_string "long long"
and structUnion = function
- Ast.Struct -> print_string "struct "
- | Ast.Union -> print_string "union "
+ Ast.Struct -> print_string "struct"
+ | Ast.Union -> print_string "union"
and sign = function
- Ast.Signed -> print_string "signed "
- | Ast.Unsigned -> print_string "unsigned "
-
-and signns = function (* no space, like a normal type *)
Ast.Signed -> print_string "signed"
| Ast.Unsigned -> print_string "unsigned"
and const_vol = function
- Ast.Const -> print_string "const "
- | Ast.Volatile -> print_string "volatile "
+ Ast.Const -> print_string "const"
+ | Ast.Volatile -> print_string "volatile"
(* --------------------------------------------------------------------- *)
(* Function declaration *)
and storage = function
- Ast.Static -> print_string "static "
- | Ast.Auto -> print_string "auto "
- | Ast.Register -> print_string "register "
- | Ast.Extern -> print_string "extern "
+ Ast.Static -> print_string "static"
+ | Ast.Auto -> print_string "auto"
+ | Ast.Register -> print_string "register"
+ | Ast.Extern -> print_string "extern"
(* --------------------------------------------------------------------- *)
(* Variable declaration *)
match Ast.unwrap d with
Ast.Init(stg,ty,id,eq,ini,sem) ->
print_option (mcode storage) stg;
+ print_option (function _ -> pr_space()) stg;
print_named_type ty id;
pr_space(); mcode print_string eq;
pr_space(); initialiser true ini; mcode print_string sem
| Ast.UnInit(stg,ty,id,sem) ->
print_option (mcode storage) stg;
+ print_option (function _ -> pr_space()) stg;
print_named_type ty id;
mcode print_string sem
| Ast.MacroDecl(name,lp,args,rp,sem) ->
| Ast.MetaParamList(name,_,_,_) ->
failwith "not handling MetaParamList"
- | Ast.PComma(cm) -> mcode print_string cm; pr_space()
+ | Ast.PComma(cm) -> mcode print_string cm
| Ast.Pdots(dots) | Ast.Pcircles(dots) when generating ->
mcode print_string dots
| Ast.Pdots(dots) | Ast.Pcircles(dots) -> raise CantBeInPlus
| Ast.OptParam(param) | Ast.UniqueParam(param) -> raise CantBeInPlus
-and parameter_list l = dots (function _ -> ()) parameterTypeDef l
+and parameter_list l =
+ let comma p =
+ parameterTypeDef p;
+ match Ast.unwrap p with
+ Ast.PComma(cm) -> pr_space()
+ | _ -> () in
+ dots (function _ -> ()) comma l
in
indent_if_needed body (function _ -> statement arity body);
mcode (fun _ _ _ -> ()) ((),Ast.no_info,aft,Ast.NoMetaPos)
- | Ast.Switch(header,lb,cases,rb) ->
+ | Ast.Switch(header,lb,decls,cases,rb) ->
rule_elem arity header; pr_space(); rule_elem arity lb;
+ dots force_newline (statement arity) decls;
List.iter (function x -> case_line arity x; force_newline()) cases;
rule_elem arity rb
(match x with
"else" -> force_newline()
| _ -> ());
- print_string x line lcol;
- (match x with
- "else" -> pr_space()
- | _ -> ()))
+ print_string x line lcol)
(let nomcodekind = Ast.CONTEXT(Ast.DontCarePos,Ast.NOTHING) in
(x,info,nomcodekind,Ast.NoMetaPos));
if_open_brace x
| (true,false) -> force_newline(); indent()
| (false,true) -> unindent(); force_newline()
| (false,false) -> force_newline());
+ let space_needed_before = function
+ Ast.ParamTag(x) ->
+ (match Ast.unwrap x with
+ Ast.PComma _ -> false
+ | _ -> true)
+ | Ast.ExpressionTag(x) ->
+ (match Ast.unwrap x with
+ Ast.EComma _ -> false
+ | _ -> true)
+ | Ast.InitTag(x) ->
+ (match Ast.unwrap x with
+ Ast.IComma _ -> false
+ | _ -> true)
+ | Ast.Token(t,_) when List.mem t [",";";";"(";")"] -> false
+ | _ -> true in
+ let space_needed_after = function
+ Ast.Token(t,_) when List.mem t ["("] -> (*never needed*) false
+ | Ast.Token(t,_) when List.mem t ["if";"for";"while";"do"] ->
+ (* space always needed *)
+ pr_space(); false
+ | _ -> true in
let indent_needed =
- List.fold_left (function indent_needed -> pp_any) false x in
+ let rec loop space_after indent_needed = function
+ [] -> indent_needed
+ | x::xs ->
+ (if space_after && space_needed_before x
+ then pr_space());
+ let indent_needed = pp_any x in
+ let space_after = space_needed_after x in
+ loop space_after indent_needed xs in
+ loop false false x in
loop true indent_needed xs in
loop false false (x::xs);
(* print a newline at the end, if needed *)
newline_after()
+let rec pp_list_list_any (envs, pr, pr_celem, pr_cspace, pr_space, pr_arity,
+ pr_barrier, indent, unindent)
+ generating xxs before =
+ List.iter
+ (function env ->
+ do_all (env, pr, pr_celem, pr_cspace, pr_space, pr_arity, pr_barrier,
+ indent, unindent)
+ generating xxs before)
+ envs