Release coccinelle-0.2.5-rc1
[bpt/coccinelle.git] / parsing_c / unparse_cocci.ml
index cda9814..4a75d68 100644 (file)
@@ -33,6 +33,7 @@ exception CantBeInPlus
 (*****************************************************************************)
 
 type pos = Before | After | InPlace
+type nlhint = StartBox | EndBox | SpaceOrNewline of string ref
 
 let unknown = -1
 
@@ -44,8 +45,11 @@ let rec do_all
 (* Just to be able to copy paste the code from pretty_print_cocci.ml. *)
 let print_string s line lcol =
   let rcol = if lcol = unknown then unknown else lcol + (String.length s) in
-  pr s line lcol rcol in
-let print_text s = pr s unknown unknown unknown 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 force_newline _ = print_text "\n" in
 
@@ -144,15 +148,17 @@ let mcode fn (s,info,mc,pos) =
                    | Ast.Indent s -> s in
                  print_string str line col; Some line
              | Some lb when line =|= lb ->
-                 Printf.printf "some, line same case\n";
                  let str = match str with Ast.Noindent s | Ast.Indent s -> s in
                  print_string 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 in
-                 force_newline(); print_string str line col; Some line)
+                 print_string str line col; Some line)
          lb comments in
       let line_before = print_comments None info.Ast.strbef in
       (match line_before with
@@ -221,22 +227,15 @@ 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_text (mo "..."); f(); start_block();
-      print_between force_newline fn l;
-      end_block(); print_text (mc "...")
-  | Ast.CIRCLES(l) ->
-      print_text (mo "ooo"); f(); start_block();
-      print_between force_newline fn l;
-      end_block(); print_text (mc "ooo")
-  | Ast.STARS(l) ->
-      print_text (mo "***"); f(); start_block();
-      print_between force_newline fn l;
-      end_block(); print_text (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
 
 (* --------------------------------------------------------------------- *)
@@ -247,7 +246,7 @@ let rec ident i =
       Ast.Id(name) -> mcode print_string name
     | Ast.MetaId(name,_,_,_) ->
        handle_metavar name (function
-                              | (Ast_c.MetaIdVal id) -> print_text id
+                              | (Ast_c.MetaIdVal (id,_)) -> print_text id
                               | _ -> raise Impossible
                            )
     | Ast.MetaFunc(name,_,_,_) ->
@@ -279,21 +278,16 @@ let rec expression e =
     Ast.Ident(id) -> ident id
   | Ast.Constant(const) -> mcode constant const
   | Ast.FunCall(fn,lp,args,rp) ->
-      expression fn; mcode print_string_box lp;
-      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
+      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; pr_space(); mcode assignOp op;
       pr_space(); expression right
   | Ast.CondExpr(exp1,why,exp2,colon,exp3) ->
       expression exp1; pr_space(); mcode print_string why;
       print_option (function e -> pr_space(); expression e) exp2;
-      pr_space(); mcode print_string colon; expression exp3
+      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
@@ -327,7 +321,7 @@ let rec expression e =
 
   | 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
       )
@@ -336,6 +330,8 @@ let rec expression e =
       handle_metavar name  (function
         | 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
       )
 
@@ -345,13 +341,14 @@ let rec expression e =
       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
+  | 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) ->
@@ -371,6 +368,14 @@ let rec expression e =
   | 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.DeRef -> print_string "*"
@@ -455,8 +460,14 @@ 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; pr_space();
-      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_prespace ident name
   | Ast.StructUnionDef(ty,lb,decls,rb) ->
@@ -480,6 +491,9 @@ and baseType = function
   | Ast.FloatType -> print_string "float"
   | Ast.LongType -> print_string "long"
   | Ast.LongLongType -> print_string "long long"
+  | 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"
@@ -559,7 +573,19 @@ and ft_space ty =
 
 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 d ->
+              pretty_print_c.Pretty_print_c.field d
+          | _ -> 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;
@@ -579,7 +605,7 @@ 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) ->
       raise CantBeInPlus
@@ -595,7 +621,16 @@ and initialiser nlcomma i =
             pretty_print_c.Pretty_print_c.init 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
+      |        _ ->
+         mcode print_string lb; start_block();
+         dots force_newline (initialiser false) initlist;
+         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
@@ -604,7 +639,8 @@ and initialiser nlcomma i =
        | x::xs -> initialiser nlcomma x; loop xs in
       loop 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; pr_space();
       mcode print_string eq; pr_space(); initialiser nlcomma ini
@@ -613,6 +649,17 @@ and initialiser nlcomma i =
   | Ast.IComma(comma) ->
       mcode print_string comma;
       if nlcomma then force_newline()
+  | 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
 
@@ -634,7 +681,11 @@ and parameterTypeDef p =
   | Ast.Param(ty,None) -> fullType ty
 
   | Ast.MetaParam(name,_,_) ->
-      failwith "not handling MetaParam"
+      handle_metavar name
+       (function
+           Ast_c.MetaParamVal p ->
+              pretty_print_c.Pretty_print_c.param p
+          | _ -> raise Impossible)
   | Ast.MetaParamList(name,_,_,_) ->
       failwith "not handling MetaParamList"
 
@@ -864,9 +915,9 @@ let rec statement arity s =
           stmt_dots_list;
         print_text "\n)")
       else raise CantBeInPlus
-  | Ast.Nest(stmt_dots,whn,multi,_,_) when generating ->
+  | Ast.Nest(starter,stmt_dots,ender,whn,multi,_,_) when generating ->
       pr_arity arity;
-      nest_dots multi (statement arity)
+      nest_dots starter ender (statement arity)
        (function _ ->
          print_between force_newline
            (whencode (dots force_newline (statement "")) (statement "")) whn;
@@ -1059,7 +1110,13 @@ in
              | Ast.Token(t,_) when List.mem t ["if";"for";"while";"do"] ->
                  (* space always needed *)
                  pr_space(); false
-             | _ -> true in
+             | Ast.ExpressionTag(e) ->
+                 (match Ast.unwrap e with
+                   Ast.EComma _ ->
+                     (* space always needed *)
+                     pr_space(); false 
+                 | _ -> true)
+             | t -> true in
            let indent_needed =
              let rec loop space_after indent_needed = function
                  [] -> indent_needed