X-Git-Url: http://git.hcoop.net/bpt/coccinelle.git/blobdiff_plain/b1b2de814d2c59af2526bc19d41bb22a0c1fd16d..7fe62b653dbe13c8fc74c58c3ca4b8af523c1637:/parsing_c/unparse_cocci.ml diff --git a/parsing_c/unparse_cocci.ml b/parsing_c/unparse_cocci.ml index 89d25d4..ca08fd9 100644 --- a/parsing_c/unparse_cocci.ml +++ b/parsing_c/unparse_cocci.ml @@ -1,7 +1,22 @@ +(* + * Copyright (C) 2010, University of Copenhagen DIKU and INRIA. + * Copyright (C) 2006, 2007 Julia Lawall + * + * 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 ? *) (*****************************************************************************) @@ -10,36 +25,55 @@ module Ast = Ast_cocci 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 (*****************************************************************************) type pos = Before | After | InPlace +type nlhint = StartBox | EndBox | SpaceOrNewline of string ref + +let get_string_info = function + Ast.Noindent s | Ast.Indent s | Ast.Space s -> s -let rec pp_list_list_any (env, pr, pr_elem, pr_space, indent, unindent) +let unknown = -1 + +let rec do_all + (env, pr, pr_celem, pr_cspace, pr_space, pr_arity, pr_barrier, + indent, unindent, eatspace) generating xxs before = (* Just to be able to copy paste the code from pretty_print_cocci.ml. *) -let print_string = pr in +let print_string s line lcol = + let rcol = if lcol = unknown then unknown else lcol + (String.length s) in + pr s line lcol rcol None in +let print_string_with_hint hint s line lcol = + let rcol = if lcol = unknown then unknown else lcol + (String.length s) in + pr s line lcol rcol (Some hint) in +let print_text s = pr s unknown unknown unknown None in let close_box _ = () in -let print_space() = pr " " in -let force_newline () = pr "\n" in +let force_newline _ = print_text "\n" in let start_block () = force_newline(); indent() in -let end_block () = unindent(); force_newline () in +let end_block () = unindent true; 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 pretty_print_c = - Pretty_print_c.pretty_print_c pr_elem pr_space - force_newline indent outdent unindent in + Pretty_print_c.mk_pretty_printers pr_celem pr_cspace + force_newline indent outdent (function _ -> unindent true) in (* --------------------------------------------------------------------- *) (* Only for make_hrule, print plus code, unbound metavariables *) @@ -68,36 +102,42 @@ and print_anything_list = function Ast.Rule_elemTag(_) | Ast.AssignOpTag(_) | Ast.BinaryOpTag(_) | Ast.ArithOpTag(_) | Ast.LogicalOpTag(_) | Ast.Token("{",_) -> true | _ -> false) in - if space then print_string " "; + if space then pr_space (); print_anything_list rest 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,_,_) -> fn1(); print_string s; force_newline()) + let print ln col s = print_string (get_string_info s) ln col in + List.iter + (function (s,ln,col) -> fn1(); print ln col s; force_newline()) info.Ast.strbef; fn x; - List.iter (function (s,_,_) -> force_newline(); fn1(); print_string s) + List.iter + (function (s,ln,col) -> force_newline(); fn1(); print ln col s) info.Ast.straft in +let print_meta (r,x) = print_text x in -let print_meta (r,x) = print_string x in - -let print_pos = function - Ast.MetaPos(name,_,_,_,_) -> - let name = Ast.unwrap_mcode name in - print_string "@"; print_meta name - | _ -> () in +let print_pos l = + List.iter + (function + Ast.MetaPos(name,_,_,_,_) -> + let name = Ast.unwrap_mcode name in + print_text "@"; print_meta name) + l in (* --------------------------------------------------------------------- *) -let mcode fn arg = - match (generating,arg) with - (false,(s,info,_,_)) -> +let mcode fn (s,info,mc,pos) = + let line = info.Ast.line in + let lcol = info.Ast.column in + match (generating,mc) with + (false,_) -> (* printing for transformation *) (* Here we don't care about the annotation on s. *) let print_comments lb comments = @@ -105,48 +145,86 @@ let mcode fn arg = (function line_before -> function (str,line,col) -> match line_before with - None -> print_string str; Some line - | Some lb when line =|= lb -> print_string str; Some line - | _ -> print_string "\n"; print_string str; Some line) + None -> + let str = + match str with + Ast.Noindent s -> unindent false; s + | Ast.Indent s -> s + | Ast.Space s -> s in + print_string str line col; Some line + | Some lb when line =|= lb -> + print_string (get_string_info str) line col; Some line + | _ -> + force_newline(); + (* not super elegant to put side-effecting unindent in a let + expression... *) + let str = + match str with + Ast.Noindent s -> unindent false; s + | Ast.Indent s -> s + | Ast.Space s -> s in + print_string str line col; Some line) lb comments in let line_before = print_comments None info.Ast.strbef in (match line_before with None -> () | Some lb when lb =|= info.Ast.line -> () - | _ -> print_string "\n"); - fn s; + | _ -> 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 *) () (* printing for rule generation *) - | (true, (x, _, Ast.MINUS(_,plus_stream), pos)) -> - print_string "\n- "; - fn x; print_pos pos; - print_anything plus_stream - | (true, (x, _, Ast.CONTEXT(_,plus_streams), pos)) -> - let fn x = print_string "\n "; fn x; print_pos pos in - print_around fn x plus_streams - | (true,( x, info, Ast.PLUS, pos)) -> - let fn x = print_string "\n+ "; fn x; print_pos pos in - print_string_befaft fn (function _ -> print_string "+ ") x info + | (true, Ast.MINUS(_,_,_,plus_stream)) -> + force_newline(); + print_text "- "; + fn s line lcol; print_pos pos; + (match plus_stream with + Ast.NOREPLACEMENT -> () + | Ast.REPLACEMENT(plus_stream,ct) -> print_anything 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 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 handle_metavar name fn = - match (Common.optionise (fun () -> List.assoc (term name) env)) with - | None -> + let ((_,b) as s,info,mc,pos) = name in + let line = info.Ast.line in + let lcol = info.Ast.column in + match Common.optionise (fun () -> List.assoc s env) with + None -> let name_string (_,s) = s in if generating - then mcode (function _ -> pr (name_string (term name))) name + then + mcode (function _ -> print_string (name_string s)) name else failwith (Printf.sprintf "SP line %d: Not found a value in env for: %s" - (Ast_cocci.get_mcode_line name) (name_string (term name))) + line (name_string s)) | Some e -> - if generating - then mcode (function _ -> fn e) name - else fn e + pr_barrier line lcol; + (if generating + then + (* call mcode to preserve the -+ annotation *) + mcode (fun _ _ _ -> fn e) name + else fn e); + let rcol = + if lcol = unknown then unknown else lcol + (String.length b) in + pr_barrier line rcol in (* --------------------------------------------------------------------- *) let dots between fn d = @@ -156,83 +234,76 @@ let dots between fn d = | Ast.STARS(l) -> print_between between fn l in -let nest_dots multi fn f d = - let mo s = if multi then "<+"^s else "<"^s in - let mc s = if multi then s^"+>" else s^">" in - match Ast.unwrap d with - Ast.DOTS(l) -> - print_string (mo "..."); f(); start_block(); - print_between force_newline fn l; - end_block(); print_string (mc "...") - | Ast.CIRCLES(l) -> - print_string (mo "ooo"); f(); start_block(); - print_between force_newline fn l; - end_block(); print_string (mc "ooo") - | Ast.STARS(l) -> - print_string (mo "***"); f(); start_block(); - print_between force_newline fn l; - end_block(); print_string (mc "***") +let nest_dots starter ender fn f d = + mcode print_string starter; + f(); start_block(); + (match Ast.unwrap d with + Ast.DOTS(l) -> print_between force_newline fn l + | Ast.CIRCLES(l) -> print_between force_newline fn l + | Ast.STARS(l) -> print_between force_newline fn l); + end_block(); + mcode print_string ender in +let print_disj_list fn l = + print_text "\n(\n"; + print_between (function _ -> print_text "\n|\n") fn l; + print_text "\n)\n" in + (* --------------------------------------------------------------------- *) (* Identifier *) 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) -> pr id - | _ -> raise Impossible - ) - | Ast.MetaFunc(name,_,_,_) -> - handle_metavar name (function - | (Ast_c.MetaFuncVal id) -> pr id - | _ -> raise Impossible - ) - | Ast.MetaLocalFunc(name,_,_,_) -> - handle_metavar name (function - | (Ast_c.MetaLocalFuncVal id) -> pr 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.DisjId(id_list) -> + if generating + then print_disj_list ident id_list + else raise CantBeInPlus + | Ast.OptIdent(_) | Ast.UniqueIdent(_) -> + raise CantBeInPlus in (* --------------------------------------------------------------------- *) (* Expression *) -let print_disj_list fn l = - force_newline(); print_string "("; force_newline(); - print_between - (function _ -> - force_newline(); print_string "|"; force_newline()) - fn l; - force_newline(); print_string ")"; force_newline() in - let rec expression e = match Ast.unwrap e with Ast.Ident(id) -> ident id - | Ast.Constant(const) -> mcode constant const | Ast.FunCall(fn,lp,args,rp) -> - expression fn; mcode print_string_box lp; - dots (function _ -> ()) expression args; - close_box(); mcode print_string rp + expression fn; mcode (print_string_with_hint StartBox) lp; + dots (function _ -> ()) arg_expression args; + mcode (print_string_with_hint EndBox) rp | Ast.Assignment(left,op,right,_) -> - expression left; print_string " "; mcode assignOp op; - print_string " "; expression right + expression left; pr_space(); mcode assignOp op; + pr_space(); expression right | Ast.CondExpr(exp1,why,exp2,colon,exp3) -> - expression exp1; print_string " "; mcode print_string why; - print_option (function e -> print_string " "; expression e) exp2; - print_string " "; mcode print_string colon; expression exp3 + expression exp1; pr_space(); mcode print_string why; + print_option (function e -> pr_space(); expression e) exp2; + pr_space(); mcode print_string colon; pr_space(); expression exp3 | Ast.Postfix(exp,op) -> expression exp; mcode fixOp op | Ast.Infix(exp,op) -> mcode fixOp op; expression exp | Ast.Unary(exp,op) -> mcode unaryOp op; expression exp | Ast.Binary(left,op,right) -> - expression left; print_string " "; mcode binaryOp op; print_string " "; + expression left; pr_space(); mcode binaryOp op; pr_space(); expression right | Ast.Nested(left,op,right) -> failwith "nested only in minus code" | Ast.Paren(lp,exp,rp) -> @@ -255,44 +326,50 @@ let rec expression e = mcode print_string_box lp; fullType ty; close_box(); mcode print_string rp | Ast.TypeExp(ty) -> fullType ty + | Ast.Constructor(lp,ty,rp,init) -> + mcode print_string_box lp; fullType ty; close_box(); + mcode print_string rp; initialiser true init - | Ast.MetaErr(name,_,_,_) -> + | Ast.MetaErr(name,_,_,_) -> failwith "metaErr not handled" | Ast.MetaExpr (name,_,_,_typedontcare,_formdontcare,_) -> handle_metavar name (function - | Ast_c.MetaExprVal exp -> + | Ast_c.MetaExprVal (exp,_) -> pretty_print_c.Pretty_print_c.expression exp | _ -> raise Impossible ) - | Ast.MetaExprList (name,_,_,_) -> + | Ast.MetaExprList (name,_,_,_) -> handle_metavar name (function - | Ast_c.MetaExprListVal args -> + | Ast_c.MetaExprListVal args -> pretty_print_c.Pretty_print_c.arg_list args + | Ast_c.MetaParamListVal _ -> + failwith "have meta param list matching meta exp list\n"; | _ -> raise Impossible ) - | Ast.EComma(cm) -> mcode print_string cm; print_space() + | Ast.EComma(cm) -> mcode print_string cm | Ast.DisjExpr(exp_list) -> if generating then print_disj_list expression exp_list else raise CantBeInPlus - | Ast.NestExpr(expr_dots,Some whencode,multi) when generating -> - nest_dots multi expression - (function _ -> print_string " when != "; expression whencode) + | Ast.NestExpr(starter,expr_dots,ender,Some whencode,multi) + when generating -> + nest_dots starter ender expression + (function _ -> print_text " when != "; expression whencode) expr_dots - | Ast.NestExpr(expr_dots,None,multi) when generating -> - nest_dots multi expression (function _ -> ()) expr_dots - | Ast.NestExpr(_) -> raise CantBeInPlus + | Ast.NestExpr(starter,expr_dots,ender,None,multi) when generating -> + nest_dots starter ender expression (function _ -> ()) expr_dots + | Ast.NestExpr _ -> raise CantBeInPlus | Ast.Edots(dots,Some whencode) | Ast.Ecircles(dots,Some whencode) | Ast.Estars(dots,Some whencode) -> if generating then (mcode print_string dots; - print_string " when != "; + print_text " when != "; expression whencode) else raise CantBeInPlus | Ast.Edots(dots,None) @@ -302,11 +379,20 @@ let rec expression e = then mcode print_string dots else raise CantBeInPlus - | Ast.OptExp(exp) | Ast.UniqueExp(exp) -> + | Ast.OptExp(exp) | Ast.UniqueExp(exp) -> raise CantBeInPlus +and arg_expression e = + match Ast.unwrap e with + Ast.EComma(cm) -> + (* space is only used by add_newline, and only if not using SMPL + spacing. pr_cspace uses a " " in unparse_c.ml. Not so nice... *) + mcode (print_string_with_hint (SpaceOrNewline (ref " "))) cm + | _ -> expression e + and unaryOp = function Ast.GetRef -> print_string "&" + | Ast.GetRefLabel -> print_string "&&" | Ast.DeRef -> print_string "*" | Ast.UnPlus -> print_string "+" | Ast.UnMinus -> print_string "-" @@ -315,7 +401,9 @@ and unaryOp = function and assignOp = function Ast.SimpleAssign -> print_string "=" - | Ast.OpAssign(aop) -> arithOp aop; print_string "=" + | Ast.OpAssign(aop) -> + (function line -> function lcol -> + arithOp aop line lcol; print_string "=" line lcol) and fixOp = function Ast.Dec -> print_string "--" @@ -326,7 +414,7 @@ and binaryOp = function | Ast.Logical(lop) -> logicalOp lop and arithOp = function - Ast.Plus -> print_string "+" + Ast.Plus -> print_string "+" | Ast.Minus -> print_string "-" | Ast.Mul -> print_string "*" | Ast.Div -> print_string "/" @@ -348,8 +436,8 @@ and logicalOp = function | Ast.OrLog -> print_string "||" and constant = function - Ast.String(s) -> print_string "\""; print_string s; print_string "\"" - | Ast.Char(s) -> print_string s + Ast.String(s) -> print_string ("\""^s^"\"") + | Ast.Char(s) -> print_string ("\'"^s^"\'") | Ast.Int(s) -> print_string s | Ast.Float(s) -> print_string s @@ -359,9 +447,7 @@ and constant = function 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 @@ -379,9 +465,9 @@ and typeC ty = 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.Pointer(ty,star) -> fullType ty; ft_space ty; mcode print_string star + | 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; eatspace() | Ast.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) -> print_function_pointer (ty,lp1,star,rp1,lp2,params,rp2) (function _ -> ()) @@ -390,20 +476,25 @@ and typeC ty = | Ast.Array(ty,lb,size,rb) -> fullType ty; mcode print_string lb; print_option expression size; mcode print_string rb - | Ast.EnumName(kind,name) -> mcode print_string kind; print_string " "; - ident name + | Ast.EnumName(kind,name) -> + mcode print_string kind; + print_option_prespace ident name + | Ast.EnumDef(ty,lb,ids,rb) -> + fullType ty; ft_space ty; + mcode print_string lb; + dots force_newline expression ids; + mcode print_string rb | 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; + fullType ty; ft_space ty; mcode print_string lb; dots force_newline declaration decls; mcode print_string rb | Ast.TypeName(name)-> mcode print_string name - | Ast.MetaType(name,_,_) -> + | Ast.MetaType(name,_,_) -> handle_metavar name (function - Ast_c.MetaTypeVal exp -> + Ast_c.MetaTypeVal exp -> pretty_print_c.Pretty_print_c.ty exp | _ -> raise Impossible) @@ -411,37 +502,40 @@ and baseType = function Ast.VoidType -> print_string "void" | Ast.CharType -> print_string "char" | Ast.ShortType -> print_string "short" + | Ast.ShortIntType -> print_string "short int" | Ast.IntType -> print_string "int" | Ast.DoubleType -> print_string "double" + | Ast.LongDoubleType -> print_string "long double" | Ast.FloatType -> print_string "float" | Ast.LongType -> print_string "long" + | Ast.LongIntType -> print_string "long int" | Ast.LongLongType -> print_string "long long" + | Ast.LongLongIntType -> print_string "long long int" + | Ast.SizeType -> print_string "size_t " + | Ast.SSizeType -> print_string "ssize_t " + | Ast.PtrDiffType -> print_string "ptrdiff_t " 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 *) @@ -452,10 +546,10 @@ and print_named_type ty id = (match Ast.unwrap ty1 with Ast.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) -> print_function_pointer (ty,lp1,star,rp1,lp2,params,rp2) - (function _ -> print_string " "; ident id) + (function _ -> pr_space(); ident id) | Ast.FunctionType(am,ty,lp1,params,rp1) -> print_function_type (ty,lp1,params,rp1) - (function _ -> print_string " "; ident id) + (function _ -> pr_space(); ident id) | Ast.Array(_,_,_,_) -> let rec loop ty k = match Ast.unwrap ty with @@ -480,25 +574,54 @@ and print_named_type ty id = and ty_space ty = match Ast.unwrap ty with Ast.Pointer(_,_) -> () - | _ -> print_space() + | _ -> pr_space() and ft_space ty = match Ast.unwrap ty with Ast.Type(cv,ty) -> (match Ast.unwrap ty with Ast.Pointer(_,_) -> () - | _ -> print_space()) - | _ -> print_space() + | Ast.MetaType(name,_,_) -> + (match List.assoc (Ast.unwrap_mcode name) env with + Ast_c.MetaTypeVal (tq,ty) -> + (match Ast_c.unwrap ty with + Ast_c.Pointer(_,_) -> () + | _ -> pr_space()) + | _ -> pr_space()) + | _ -> pr_space()) + | _ -> pr_space() and declaration d = match Ast.unwrap d with - Ast.Init(stg,ty,id,eq,ini,sem) -> + Ast.MetaDecl(name,_,_) -> + handle_metavar name + (function + Ast_c.MetaDeclVal d -> + pretty_print_c.Pretty_print_c.decl d + | _ -> raise Impossible) + | Ast.MetaField(name,_,_) -> + handle_metavar name + (function + Ast_c.MetaFieldVal f -> + pretty_print_c.Pretty_print_c.field f + | _ -> raise Impossible) + + | Ast.MetaFieldList(name,_,_,_) -> + handle_metavar name + (function + Ast_c.MetaFieldListVal f -> + print_between force_newline pretty_print_c.Pretty_print_c.field f + | _ -> raise Impossible) + + | Ast.Init(stg,ty,id,eq,ini,sem) -> print_option (mcode storage) stg; + print_option (function _ -> pr_space()) stg; print_named_type ty id; - print_string " "; mcode print_string eq; - print_string " "; initialiser true ini; mcode print_string sem + 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) -> @@ -510,9 +633,9 @@ and declaration d = mcode print_string stg; fullType ty; typeC id; mcode print_string sem - | Ast.DisjDecl(_) | Ast.MetaDecl(_,_,_) -> raise CantBeInPlus + | Ast.DisjDecl(_) -> raise CantBeInPlus | Ast.Ddots(_,_) -> raise CantBeInPlus - | Ast.OptDecl(decl) | Ast.UniqueDecl(decl) -> + | Ast.OptDecl(decl) | Ast.UniqueDecl(decl) -> raise CantBeInPlus (* --------------------------------------------------------------------- *) @@ -520,33 +643,60 @@ and declaration d = and initialiser nlcomma i = match Ast.unwrap i with - Ast.MetaInit(name,_,_) -> + Ast.MetaInit(name,_,_) -> handle_metavar name (function Ast_c.MetaInitVal ini -> pretty_print_c.Pretty_print_c.init ini | _ -> raise Impossible) + | Ast.MetaInitList(name,_,_,_) -> + handle_metavar name (function + Ast_c.MetaInitListVal ini -> + pretty_print_c.Pretty_print_c.init_list ini + | _ -> raise Impossible) | Ast.InitExpr(exp) -> expression exp - | Ast.InitList(lb,initlist,rb,[]) -> + | Ast.ArInitList(lb,initlist,rb) -> + (match Ast.undots initlist with + [] -> mcode print_string lb; mcode print_string rb + | lst -> + mcode print_string lb; start_block(); + initialiser_list nlcomma lst; + end_block(); mcode print_string rb) + | Ast.StrInitList(_,lb,[],rb,[]) -> + mcode print_string lb; mcode print_string rb + | Ast.StrInitList(_,lb,initlist,rb,[]) -> mcode print_string lb; start_block(); - (* awkward, because the comma is separate from the initialiser *) - let rec loop = function - [] -> () - | [x] -> initialiser false x - | x::xs -> initialiser nlcomma x; loop xs in - loop initlist; + initialiser_list nlcomma initlist; end_block(); mcode print_string rb - | Ast.InitList(lb,initlist,rb,_) -> failwith "unexpected whencode in plus" + | Ast.StrInitList(_,lb,initlist,rb,_) -> + failwith "unexpected whencode in plus" | Ast.InitGccExt(designators,eq,ini) -> - List.iter designator designators; print_string " "; - mcode print_string eq; print_string " "; initialiser nlcomma ini + List.iter designator designators; pr_space(); + mcode print_string eq; pr_space(); initialiser nlcomma ini | Ast.InitGccName(name,eq,ini) -> ident name; mcode print_string eq; initialiser nlcomma ini | Ast.IComma(comma) -> mcode print_string comma; - if nlcomma then force_newline() + if nlcomma then force_newline() else pr_space() + | Ast.Idots(dots,Some whencode) -> + if generating + then + (mcode print_string dots; + print_text " when != "; + initialiser nlcomma whencode) + else raise CantBeInPlus + | Ast.Idots(dots,None) -> + if generating + then mcode print_string dots + else raise CantBeInPlus | Ast.OptIni(ini) | Ast.UniqueIni(ini) -> raise CantBeInPlus +and initialiser_list nlcomma = function + (* awkward, because the comma is separate from the initialiser *) + [] -> () + | [x] -> initialiser false x + | x::xs -> initialiser nlcomma x; initialiser_list nlcomma xs + and designator = function Ast.DesignatorField(dot,id) -> mcode print_string dot; ident id | Ast.DesignatorIndex(lb,exp,rb) -> @@ -564,18 +714,32 @@ and parameterTypeDef p = | Ast.Param(ty,Some id) -> print_named_type ty id | Ast.Param(ty,None) -> fullType ty - | Ast.MetaParam(name,_,_) -> - failwith "not handling MetaParam" - | Ast.MetaParamList(name,_,_,_) -> - failwith "not handling MetaParamList" - - | Ast.PComma(cm) -> mcode print_string cm; print_space() + | Ast.MetaParam(name,_,_) -> + handle_metavar name + (function + Ast_c.MetaParamVal p -> + pretty_print_c.Pretty_print_c.param p + | _ -> raise Impossible) + | Ast.MetaParamList(name,_,_,_) -> + handle_metavar name + (function + Ast_c.MetaParamListVal p -> + pretty_print_c.Pretty_print_c.paramlist p + | _ -> raise Impossible) + + | 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 @@ -584,17 +748,13 @@ in let rec inc_file = function Ast.Local(elems) -> - print_string "\""; - print_between (function _ -> print_string "/") inc_elem elems; - print_string "\"" + print_string ("\""^(String.concat "/" (List.map inc_elem elems))^"\"") | Ast.NonLocal(elems) -> - print_string "<"; - print_between (function _ -> print_string "/") inc_elem elems; - print_string ">" + print_string ("<"^(String.concat "/" (List.map inc_elem elems))^">") and inc_elem = function - Ast.IncPath s -> print_string s - | Ast.IncDots -> print_string "..." + Ast.IncPath s -> s + | Ast.IncDots -> "..." (* --------------------------------------------------------------------- *) (* Top-level code *) @@ -602,94 +762,93 @@ and inc_elem = function and rule_elem arity re = match Ast.unwrap re with Ast.FunHeader(_,_,fninfo,name,lp,params,rp) -> - print_string arity; List.iter print_fninfo fninfo; + pr_arity arity; List.iter print_fninfo fninfo; ident name; mcode print_string_box lp; parameter_list params; close_box(); mcode print_string rp; - print_string " " - | Ast.Decl(_,_,decl) -> print_string arity; declaration decl + pr_space() + | Ast.Decl(_,_,decl) -> pr_arity arity; declaration decl | Ast.SeqStart(brace) -> - print_string arity; mcode print_string brace; start_block() + pr_arity arity; mcode print_string brace; start_block() | Ast.SeqEnd(brace) -> - end_block(); print_string arity; mcode print_string brace + end_block(); pr_arity arity; mcode print_string brace | Ast.ExprStatement(exp,sem) -> - print_string arity; expression exp; mcode print_string sem + pr_arity arity; print_option expression exp; mcode print_string sem | Ast.IfHeader(iff,lp,exp,rp) -> - print_string arity; - mcode print_string iff; print_string " "; mcode print_string_box lp; + pr_arity arity; + mcode print_string iff; pr_space(); mcode print_string_box lp; expression exp; close_box(); mcode print_string rp | Ast.Else(els) -> - print_string arity; mcode print_string els + pr_arity arity; mcode print_string els | Ast.WhileHeader(whl,lp,exp,rp) -> - print_string arity; - mcode print_string whl; print_string " "; mcode print_string_box lp; + pr_arity arity; + mcode print_string whl; pr_space(); mcode print_string_box lp; expression exp; close_box(); mcode print_string rp | Ast.DoHeader(d) -> - print_string arity; mcode print_string d + pr_arity arity; mcode print_string d | Ast.WhileTail(whl,lp,exp,rp,sem) -> - print_string arity; - mcode print_string whl; print_string " "; mcode print_string_box lp; + pr_arity arity; + mcode print_string whl; pr_space(); mcode print_string_box lp; expression exp; close_box(); mcode print_string rp; mcode print_string sem | Ast.ForHeader(fr,lp,e1,sem1,e2,sem2,e3,rp) -> - print_string arity; + pr_arity arity; mcode print_string fr; mcode print_string_box lp; print_option expression e1; mcode print_string sem1; print_option expression e2; mcode print_string sem2; print_option expression e3; close_box(); mcode print_string rp | Ast.IteratorHeader(nm,lp,args,rp) -> - print_string arity; - ident nm; print_string " "; mcode print_string_box lp; + pr_arity arity; + ident nm; pr_space(); mcode print_string_box lp; dots (function _ -> ()) expression args; close_box(); mcode print_string rp | Ast.SwitchHeader(switch,lp,exp,rp) -> - print_string arity; - mcode print_string switch; print_string " "; mcode print_string_box lp; + pr_arity arity; + mcode print_string switch; pr_space(); mcode print_string_box lp; expression exp; close_box(); mcode print_string rp | Ast.Break(br,sem) -> - print_string arity; mcode print_string br; mcode print_string sem + pr_arity arity; mcode print_string br; mcode print_string sem | Ast.Continue(cont,sem) -> - print_string arity; mcode print_string cont; mcode print_string sem + pr_arity arity; mcode print_string cont; mcode print_string sem | Ast.Label(l,dd) -> ident l; mcode print_string dd | Ast.Goto(goto,l,sem) -> mcode print_string goto; ident l; mcode print_string sem | Ast.Return(ret,sem) -> - print_string arity; mcode print_string ret; + pr_arity arity; mcode print_string ret; mcode print_string sem | Ast.ReturnExpr(ret,exp,sem) -> - print_string arity; mcode print_string ret; print_string " "; + pr_arity arity; mcode print_string ret; pr_space(); expression exp; mcode print_string sem - | Ast.Exp(exp) -> print_string arity; expression exp - | Ast.TopExp(exp) -> print_string arity; expression exp - | Ast.Ty(ty) -> print_string arity; fullType ty + | Ast.Exp(exp) -> pr_arity arity; expression exp + | Ast.TopExp(exp) -> pr_arity arity; expression exp + | Ast.Ty(ty) -> pr_arity arity; fullType ty | Ast.TopInit(init) -> initialiser false init | Ast.Include(inc,s) -> - mcode print_string inc; print_string " "; mcode inc_file s + mcode print_string inc; print_text " "; mcode inc_file s + | Ast.Undef(def,id) -> + mcode print_string def; pr_space(); ident id | Ast.DefineHeader(def,id,params) -> - mcode print_string def; print_string " "; ident id; + mcode print_string def; pr_space(); ident id; print_define_parameters params | Ast.Default(def,colon) -> - mcode print_string def; mcode print_string colon; print_string " " + mcode print_string def; mcode print_string colon; pr_space() | Ast.Case(case,exp,colon) -> - mcode print_string case; print_string " "; expression exp; - mcode print_string colon; print_string " " + mcode print_string case; pr_space(); expression exp; + mcode print_string colon; pr_space() | Ast.DisjRuleElem(res) -> if generating then - (print_string arity; - force_newline(); print_string "("; force_newline(); - print_between - (function _ -> force_newline(); print_string "|"; force_newline()) - (rule_elem arity) + (pr_arity arity; print_text "\n(\n"; + print_between (function _ -> print_text "\n|\n") (rule_elem arity) res; - force_newline(); print_string ")") + print_text "\n)") else raise CantBeInPlus | Ast.MetaRuleElem(name,_,_) -> @@ -718,27 +877,26 @@ and print_define_param param = | Ast.DPComma(comma) -> mcode print_string comma | Ast.DPdots(dots) -> mcode print_string dots | Ast.DPcircles(circles) -> mcode print_string circles - | Ast.OptDParam(dp) -> print_string "?"; print_define_param dp - | Ast.UniqueDParam(dp) -> print_string "!"; print_define_param dp + | Ast.OptDParam(dp) -> print_text "?"; print_define_param dp + | Ast.UniqueDParam(dp) -> print_text "!"; print_define_param dp and print_fninfo = function Ast.FStorage(stg) -> mcode storage stg | Ast.FType(ty) -> fullType ty - | Ast.FInline(inline) -> mcode print_string inline; print_string " " - | Ast.FAttr(attr) -> mcode print_string attr; print_string " " in + | Ast.FInline(inline) -> mcode print_string inline; pr_space() + | Ast.FAttr(attr) -> mcode print_string attr; pr_space() in let indent_if_needed s f = match Ast.unwrap s with - Ast.Seq(lbrace,decls,body,rbrace) -> pr_space(); f() + Ast.Seq(lbrace,body,rbrace) -> pr_space(); f() | _ -> (*no newline at the end - someone else will do that*) - start_block(); f(); unindent() in + start_block(); f(); unindent true in let rec statement arity s = match Ast.unwrap s with - Ast.Seq(lbrace,decls,body,rbrace) -> + Ast.Seq(lbrace,body,rbrace) -> rule_elem arity lbrace; - dots force_newline (statement arity) decls; dots force_newline (statement arity) body; rule_elem arity rbrace @@ -748,10 +906,9 @@ let rec statement arity s = | Ast.IfThenElse(header,branch1,els,branch2,_) -> rule_elem arity header; indent_if_needed branch1 (function _ -> statement arity branch1); - print_string " "; + force_newline(); rule_elem arity els; indent_if_needed branch2 (function _ -> statement arity branch2) - | Ast.While(header,body,_) -> rule_elem arity header; indent_if_needed body (function _ -> statement arity body) @@ -765,44 +922,42 @@ let rec statement arity s = | Ast.Iterator(header,body,(_,_,_,aft)) -> rule_elem arity header; indent_if_needed body (function _ -> statement arity body); - mcode (function _ -> ()) ((),Ast.no_info,aft,Ast.NoMetaPos) + mcode (fun _ _ _ -> ()) ((),Ast.no_info,aft,[]) - | Ast.Switch(header,lb,cases,rb) -> - rule_elem arity header; print_string " "; rule_elem arity lb; + | 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 | Ast.Atomic(re) -> rule_elem arity re - | Ast.FunDecl(header,lbrace,decls,body,rbrace) -> + | Ast.FunDecl(header,lbrace,body,rbrace) -> rule_elem arity header; rule_elem arity lbrace; - dots force_newline (statement arity) decls; dots force_newline (statement arity) body; rule_elem arity rbrace | Ast.Define(header,body) -> - rule_elem arity header; print_string " "; + rule_elem arity header; pr_space(); dots force_newline (statement arity) body | Ast.Disj([stmt_dots]) -> if generating then - (print_string arity; + (pr_arity arity; dots force_newline (statement arity) stmt_dots) else raise CantBeInPlus | Ast.Disj(stmt_dots_list) -> (* ignores newline directive for readability *) if generating then - (print_string arity; - force_newline(); print_string "("; force_newline(); - print_between - (function _ -> force_newline();print_string "|"; force_newline()) + (pr_arity arity; print_text "\n(\n"; + print_between (function _ -> print_text "\n|\n") (dots force_newline (statement arity)) stmt_dots_list; - force_newline(); print_string ")") + print_text "\n)") else raise CantBeInPlus - | Ast.Nest(stmt_dots,whn,multi,_,_) when generating -> - print_string arity; - nest_dots multi (statement arity) + | Ast.Nest(starter,stmt_dots,ender,whn,multi,_,_) when generating -> + pr_arity arity; + nest_dots starter ender (statement arity) (function _ -> print_between force_newline (whencode (dots force_newline (statement "")) (statement "")) whn; @@ -812,48 +967,48 @@ let rec statement arity s = | Ast.Dots(d,whn,_,_) | Ast.Circles(d,whn,_,_) | Ast.Stars(d,whn,_,_) -> if generating then - (print_string arity; mcode print_string d; + (pr_arity arity; mcode print_string d; print_between force_newline (whencode (dots force_newline (statement "")) (statement "")) whn; force_newline()) else raise CantBeInPlus - | Ast.OptStm(s) | Ast.UniqueStm(s) -> + | Ast.OptStm(s) | Ast.UniqueStm(s) -> raise CantBeInPlus and whencode notfn alwaysfn = function Ast.WhenNot a -> - print_string " WHEN != "; notfn a + print_text " WHEN != "; notfn a | Ast.WhenAlways a -> - print_string " WHEN = "; alwaysfn a - | Ast.WhenModifier x -> print_string " WHEN "; print_when_modif x + print_text " WHEN = "; alwaysfn a + | Ast.WhenModifier x -> print_text " WHEN "; print_when_modif x | Ast.WhenNotTrue a -> - print_string " WHEN != TRUE "; rule_elem "" a + print_text " WHEN != TRUE "; rule_elem "" a | Ast.WhenNotFalse a -> - print_string " WHEN != FALSE "; rule_elem "" a + print_text " WHEN != FALSE "; rule_elem "" a and print_when_modif = function - | Ast.WhenAny -> print_string "ANY" - | Ast.WhenStrict -> print_string "STRICT" - | Ast.WhenForall -> print_string "FORALL" - | Ast.WhenExists -> print_string "EXISTS" + | Ast.WhenAny -> print_text "ANY" + | Ast.WhenStrict -> print_text "STRICT" + | Ast.WhenForall -> print_text "FORALL" + | Ast.WhenExists -> print_text "EXISTS" and case_line arity c = match Ast.unwrap c with Ast.CaseLine(header,code) -> - rule_elem arity header; print_string " "; + rule_elem arity header; pr_space(); dots force_newline (statement arity) code | Ast.OptCase(case) -> raise CantBeInPlus in let top_level t = match Ast.unwrap t with Ast.FILEINFO(old_file,new_file) -> raise CantBeInPlus - | Ast.DECL(stmt) -> statement "" stmt + | Ast.NONDECL(stmt) -> statement "" stmt | Ast.CODE(stmt_dots) -> dots force_newline (statement "") stmt_dots | Ast.ERRORWORDS(exps) -> raise CantBeInPlus in -(* +(* let rule = print_between (function _ -> force_newline(); force_newline()) top_level in @@ -865,58 +1020,67 @@ let if_open_brace = function "{" -> true | _ -> false in let rec pp_any = function (* assert: normally there is only CONTEXT NOTHING tokens in any *) Ast.FullTypeTag(x) -> fullType x; false - | Ast.BaseTypeTag(x) -> baseType x; false - | Ast.StructUnionTag(x) -> structUnion x; false - | Ast.SignTag(x) -> sign x; false + | Ast.BaseTypeTag(x) -> baseType x unknown unknown; false + | Ast.StructUnionTag(x) -> structUnion x unknown unknown; false + | Ast.SignTag(x) -> sign x unknown unknown; false | Ast.IdentTag(x) -> ident x; false | Ast.ExpressionTag(x) -> expression x; false - | Ast.ConstantTag(x) -> constant x; false - | Ast.UnaryOpTag(x) -> unaryOp x; false - | Ast.AssignOpTag(x) -> assignOp x; false - | Ast.FixOpTag(x) -> fixOp x; false - | Ast.BinaryOpTag(x) -> binaryOp x; false - | Ast.ArithOpTag(x) -> arithOp x; false - | Ast.LogicalOpTag(x) -> logicalOp x; false + | Ast.ConstantTag(x) -> constant x unknown unknown; false + | Ast.UnaryOpTag(x) -> unaryOp x unknown unknown; false + | Ast.AssignOpTag(x) -> assignOp x unknown unknown; false + | Ast.FixOpTag(x) -> fixOp x unknown unknown; false + | Ast.BinaryOpTag(x) -> binaryOp x unknown unknown; false + | Ast.ArithOpTag(x) -> arithOp x unknown unknown; false + | Ast.LogicalOpTag(x) -> logicalOp x unknown unknown; false | Ast.InitTag(x) -> initialiser false x; false | Ast.DeclarationTag(x) -> declaration x; false - | Ast.StorageTag(x) -> storage x; false - | Ast.IncFileTag(x) -> inc_file x; false + | Ast.StorageTag(x) -> storage x unknown unknown; false + | Ast.IncFileTag(x) -> inc_file x unknown unknown; false | Ast.Rule_elemTag(x) -> rule_elem "" x; false | Ast.StatementTag(x) -> statement "" x; false | Ast.CaseLineTag(x) -> case_line "" x; false - | Ast.ConstVolTag(x) -> const_vol x; false - | Ast.Pragma(xs) -> print_between force_newline print_string xs; false - | Ast.Token(x,None) -> print_string x; if_open_brace x - | Ast.Token(x,Some info) -> + | Ast.ConstVolTag(x) -> const_vol x unknown unknown; false + | Ast.Pragma(xs) -> + (match xs with (Ast.Space s)::_ -> pr_space() | _ -> ()); + let rec loop = function + [] -> () + | [Ast.Noindent s] -> unindent false; print_text s + | [Ast.Indent s] -> print_text s + | (Ast.Space s) :: (((Ast.Indent _ | Ast.Noindent _) :: _) as rest) -> + print_text s; force_newline(); loop rest + | (Ast.Space s) :: rest -> print_text s; pr_space(); loop rest + | Ast.Noindent s :: rest -> + unindent false; print_text s; force_newline(); loop rest + | Ast.Indent s :: rest -> + print_text s; force_newline(); loop rest in + loop xs; false + | Ast.Token(x,None) -> print_text x; if_open_brace x + | Ast.Token(x,Some info) -> mcode - (function x -> + (fun x line lcol -> (match x with - "else" -> pr "\n" + "else" -> force_newline() | _ -> ()); - print_string x; - (* if x ==~ Common.regexp_alpha then print_string " "; *) - (match x with - (*"return" |*) "else" -> print_string " " - | _ -> ())) + print_string x line lcol) (let nomcodekind = Ast.CONTEXT(Ast.DontCarePos,Ast.NOTHING) in - (x,info,nomcodekind,Ast.NoMetaPos)); + (x,info,nomcodekind,[])); if_open_brace x | Ast.Code(x) -> let _ = top_level x in false - (* this is not '...', but a list of expr/statement/params, and + (* this is not '...', but a list of expr/statement/params, and normally there should be no '...' inside them *) | Ast.ExprDotsTag(x) -> dots (function _ -> ()) expression x; false | Ast.ParamDotsTag(x) -> parameter_list x; false - | Ast.StmtDotsTag(x) -> dots (function _ -> pr "\n") (statement "") x; false - | Ast.DeclDotsTag(x) -> dots (function _ -> pr "\n") declaration x; false + | Ast.StmtDotsTag(x) -> dots force_newline (statement "") x; false + | Ast.DeclDotsTag(x) -> dots force_newline declaration x; false | Ast.TypeCTag(x) -> typeC x; false | Ast.ParamTag(x) -> parameterTypeDef x; false @@ -924,12 +1088,14 @@ let rec pp_any = function | Ast.SgrepEndTag(x) -> failwith "unexpected end tag" in +(*Printf.printf "start of the function\n";*) + anything := (function x -> let _ = pp_any x in ()); (* todo? imitate what is in pretty_print_cocci ? *) match xxs with [] -> () - | x::xs -> + | x::xs -> (* for many tags, we must not do a newline before the first '+' *) let isfn s = match Ast.unwrap s with Ast.FunDecl _ -> true | _ -> false in @@ -938,14 +1104,18 @@ in (Ast.Token ("}",_)::_) -> true | _ -> false in let prnl x = - (if unindent_before x then unindent()); - pr "\n" in + (if unindent_before x then unindent true); + force_newline() in let newline_before _ = if before =*= After then let hd = List.hd xxs in match hd with - (Ast.StatementTag s::_) when isfn s -> pr "\n\n" + (Ast.Pragma l::_) + when List.for_all (function Ast.Space x -> true | _ -> false) l -> + () + | (Ast.StatementTag s::_) when isfn s -> + force_newline(); force_newline() | (Ast.Pragma _::_) | (Ast.Rule_elemTag _::_) | (Ast.StatementTag _::_) | (Ast.InitTag _::_) @@ -956,10 +1126,12 @@ in then match List.rev(List.hd(List.rev xxs)) with (Ast.StatementTag s::_) -> - if isfn s then pr "\n\n" else pr "\n" + (if isfn s then force_newline()); + force_newline() | (Ast.Pragma _::_) | (Ast.Rule_elemTag _::_) | (Ast.InitTag _::_) - | (Ast.DeclarationTag _::_) | (Ast.Token ("{",_)::_) -> pr "\n" + | (Ast.DeclarationTag _::_) | (Ast.Token ("{",_)::_) -> + force_newline() | _ -> () in (* print a newline at the beginning, if needed *) newline_before(); @@ -970,14 +1142,60 @@ in (if leading_newline then match (indent_needed,unindent_before x) with - (true,true) -> pr "\n" - | (true,false) -> pr "\n"; indent() - | (false,true) -> unindent(); pr "\n" - | (false,false) -> pr "\n"); + (true,true) -> force_newline() + | (true,false) -> force_newline(); indent() + | (false,true) -> unindent true; 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 + | Ast.ExpressionTag(e) -> + (match Ast.unwrap e with + Ast.EComma _ -> + (* space always needed *) + pr_space(); false + | _ -> true) + | t -> 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, eatspace) + generating xxs before = + List.iter + (function env -> + do_all (env, pr, pr_celem, pr_cspace, pr_space, pr_arity, pr_barrier, + indent, unindent, eatspace) + generating xxs before) + envs