keywords sush as 'depends on', 'using', 'disable'
- better treatment of != 0 in isos, communtativity for ==/!= for all
constants
-- allow adding // comments
+- allow adding // comments and blank lines (even after cocci + code)
- Add support for multiple -I options
** Bugfix:
- correct interaction between virtual rules and included .cocci files
- improvement in treatment of ! in isos, to avoid duplicating + code
-- improvement intreatment of metavars as isos, to avoid duplicating + code
+- improvement in treatment of metavars as isos, to avoid duplicating + code
between toplevel and variable instantiation
- test expression of smpl conditional, etc no longer assumed to have type
int
- better handling of . or .. in -dir name
- allow keywords and metavariable names in identifier constraints (not sure
keywords is very useful, though)
+- no lubtype on arguments of && and || in SmPL
+- allow unknown as type for array indices in SmPL
+- support matching of static annotation on functions that are both static
+ and inline
+- support ENOTDIR error in Common.lfile_exists, to allow for the case where
+ an include file is in a subdirectory that exists but is an ordinary file,
+ not a directory.
+- better management of unbound position variables that appear in
+ constraints
+- cause python parser to skip over // comments, hoping that // is not
+ meaningful inside python
+- require + on every line of a multiline comment
+- correct caluation of line numbers when there is script code
* 0.2.1
** Language:
(new_bindings +>
List.map
(List.filter
- (fun (s,v) ->
- List.mem s r.used_after &&
- not (List.mem s old_variables)))) in
+ (function
+ (* see comment before combine_pos *)
+ (s,Ast_c.MetaPosValList []) -> false
+ | (s,v) ->
+ List.mem s r.used_after &&
+ not (List.mem s old_variables)))) in
List.map
(function new_binding_to_add ->
(List.sort compare
(List.map (function (non_pos,_) -> List.assoc non_pos extended_relevant)
splitted_relevant)
+(* If the negated posvar is not bound at all, this function will
+nevertheless bind it to []. If we get rid of these bindings, then the
+matching of the term the position variable with the constraints will fail
+because some variables are unbound. So we let the binding be [] and then
+we will have to clean these up afterwards. This should be the only way
+that a position variable can have an empty binding. *)
and combine_pos negated_pos_vars others =
List.map
(function posvar ->
- (posvar,
- Ast_c.MetaPosValList
- (List.sort compare
- (List.fold_left
- (function positions ->
- function other_list ->
- try
- match List.assoc posvar other_list with
- Ast_c.MetaPosValList l1 ->
- Common.union_set l1 positions
- | _ -> failwith "bad value for a position variable"
- with Not_found -> positions)
- [] others))))
+ let positions =
+ List.sort compare
+ (List.fold_left
+ (function positions ->
+ function other_list ->
+ try
+ match List.assoc posvar other_list with
+ Ast_c.MetaPosValList l1 ->
+ Common.union_set l1 positions
+ | _ -> failwith "bad value for a position variable"
+ with Not_found -> positions)
+ [] others) in
+ (posvar,Ast_c.MetaPosValList positions))
negated_pos_vars
and process_a_generated_a_env_a_toplevel2 r env = function
-Release coccinelle-0.2.2-rc1
+Release coccinelle-0.2.2-rc2
-Release Candidate 1 for coccinelle-0.2.2
+Release Candidate 2 for coccinelle-0.2.2
| (Unix.S_REG | Unix.S_LNK) -> true
| _ -> false
)
- with Unix.Unix_error (Unix.ENOENT, _, _) -> false
+ with
+ Unix.Unix_error (Unix.ENOENT, _, _) -> false
+ | Unix.Unix_error (Unix.ENOTDIR, _, _) -> false
+ | Unix.Unix_error (error, _, fl) ->
+ failwith
+ (Printf.sprintf "unexpected error %s for file %s"
+ (Unix.error_message error) fl)
let is_directory file =
(Unix.stat file).Unix.st_kind =*= Unix.S_DIR
| Some x, ((stobis, inline)) ->
if equal_storage (term x) stobis
then
- match iistob with
- | [i1] ->
- tokenf x i1 >>= (fun x i1 ->
- return (Some x, ((stobis, inline), [i1]))
- )
- (* or if have inline ? have to do a split_storage_inline a la
- * split_signb_baseb_ii *)
- | _ -> raise Impossible
+ let rec loop acc = function
+ [] -> fail
+ | i1::iistob ->
+ let try1 =
+ tokenf x i1 >>= (fun x i1 ->
+ let rebuilt = (List.rev acc) @ i1 :: iistob in
+ return (Some x, ((stobis, inline), rebuilt))) in
+ let try2 x = loop (i1::acc) iistob x in (* x for laziness *)
+ try1 >||> try2 in
+ loop [] iistob
else fail
)
-
-
-
-
and fullType_optional_allminus allminus tya retb =
match tya with
| None ->
begin
pp "[";
Common.print_between (fun () -> pp ";"; Format.print_cut() )
- (fun ((_,s), kind) -> pp s; pp " --> "; pp_binding_kind kind)
+ (fun ((r,s), kind) ->
+ pp r; pp "."; pp s; pp " --> "; pp_binding_kind kind)
subst;
pp "]";
end
-let version = "0.2.2-rc1"
+let version = "0.2.2-rc2"
let path =
try (Sys.getenv "COCCINELLE_HOME")
" guess what";
"-date", Arg.Unit (fun () ->
- pr2 "version: $Date: 2010/03/05 21:12:11 $";
+ pr2 "version: $Date: 2010/03/09 08:29:04 $";
raise (Common.UnixExit 0)
),
" guess what";
(* --------------------------------------------------------- *)
| [x] when !test_mode ->
begin
+ let prefix = "tests/" in
try
- let prefix = "tests/" in
FC.include_path := [prefix^"include"];
Testing.testone prefix x !compare_with_expected
- with _ ->
- FC.include_path := ["include"];
- Testing.testone "" x !compare_with_expected
+ with error ->
+ let testfile = prefix ^ x ^ ".cocci" in
+ if not (Sys.file_exists testfile) then
+ begin
+ FC.include_path := ["include"];
+ Testing.testone "" x !compare_with_expected
+ end
+ else
+ raise error
end
| [] when !test_all ->
try
main ()
with
- | Unix.Unix_error (_, "stat", filename) ->
- pr2 (spf "ERROR: File %s does not exist" filename);
+ | Unix.Unix_error (e, "stat", filename) ->
+ pr2
+ (spf "ERROR: File %s does not exist: %s"
+ filename (Unix.error_message e));
raise (UnixExit (-1))
(*****************************************************************************)
let rec adjust_indentation xs =
+
let _current_tabbing = ref "" in
let tabbing_unit = ref None in
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
(build_or dependencies rest_info, in_plus, env, locals))
| (Ast.InitialScriptRule (_,deps,_),_)
| (Ast.FinalScriptRule (_,deps,_),_) ->
- (match dependencies env deps with
- False -> (rest_info, in_plus, env, locals)
- | dependencies ->
- (build_or dependencies rest_info, in_plus, env, locals))
+ (* initialize and finalize dependencies are irrelevant to
+ get_constants *)
+ (rest_info, in_plus, env, locals)
| (Ast.CocciRule (nm,(dep,_,_),cur,_,_),neg_pos_vars) ->
let (cur_info,cur_plus) =
rule_fn cur in_plus ((nm,True)::env)
| (D.UNIQUE,_,_) | (D.OPT,_,_) -> ()
| _ -> lexerr "invalid in a nonempty context: " s
+let check_comment s =
+ if not !current_line_started
+ then lexerr "+ expected at the beginning of the line" s
+
let process_include start finish str =
(match !current_line_type with
(D.PLUS,_,_) | (D.PLUSPLUS,_,_) ->
| "/*"
{ start_line true; check_plus_linetype (tok lexbuf);
(* second argument to TPragma is not quite right, because
- it represents only the first token of the comemnt, but that
+ it represents only the first token of the comment, but that
should be good enough *)
TPragma (Ast.Indent("/*"^(comment lexbuf)),
get_current_line_type lexbuf) }
| _ { lexerr "unrecognised symbol: " (tok lexbuf) }
and comment = parse
- | "*/" { start_line true; tok lexbuf }
+ | "*/" { let s = tok lexbuf in check_comment s; start_line true; s }
| ['\n' '\r' '\011' '\012']
- { reset_line lexbuf; let s = tok lexbuf in s ^ comment lexbuf }
+ { let s = tok lexbuf in
+ (* even blank line should have a + *)
+ check_comment s;
+ reset_line lexbuf; s ^ comment lexbuf }
| "+" { pass_zero();
if !current_line_started
then (start_line true; let s = tok lexbuf in s^(comment lexbuf))
- else comment lexbuf }
+ else (start_line true; comment lexbuf) }
(* noteopti: *)
- | [^ '*'] { start_line true; let s = tok lexbuf in s ^ comment lexbuf }
- | [ '*'] { start_line true; let s = tok lexbuf in s ^ comment lexbuf }
+ | [^ '*']
+ { let s = tok lexbuf in
+ check_comment s; start_line true; s ^ comment lexbuf }
+ | [ '*']
+ { let s = tok lexbuf in
+ check_comment s; start_line true; s ^ comment lexbuf }
| _
{ start_line true; let s = tok lexbuf in
Common.pr2 ("LEXER: unrecognised symbol in comment:"^s);
module Ast = Ast_cocci
exception Lexical of string
let tok = Lexing.lexeme
+let inc_line _ = Lexer_cocci.line := !Lexer_cocci.line + 1
}
(* ---------------------------------------------------------------------- *)
(* tokens *)
-let myrule = [^'"''@']+
+let myrule = [^'"''@''/''\n''\r''\011''\012']+
rule token = parse
- | myrule { TScriptData (tok lexbuf) }
+ | myrule { TScriptData (tok lexbuf) }
+ | ['\n' '\r' '\011' '\012'] { inc_line(); TScriptData (tok lexbuf) }
| "@@" { TArobArob }
| "@" { TArob }
+ | "/" { TScriptData (tok lexbuf) }
| "//" [^ '\n']* { token lexbuf } (* skip SmPL comments *)
| '"' { TScriptData (Printf.sprintf "\"%s\"" (string lexbuf)) }
| eof { EOF }
Ast0.set_type exp1 ty; Ast0.set_type exp2 ty; ty in
(match Ast0.unwrap_mcode op with
Ast.Arith(op) -> same_type (ty1, ty2)
+ | Ast.Logical(Ast.AndLog) | Ast.Logical(Ast.OrLog) ->
+ Some(bool_type)
| Ast.Logical(op) ->
let ty = lub_type ty1 ty2 in
- Ast0.set_type exp1 ty; Ast0.set_type exp2 ty;
- Some(bool_type))
+ Ast0.set_type exp1 ty; Ast0.set_type exp2 ty;
+ Some(bool_type))
| Ast0.Paren(lp,exp,rp) -> Ast0.get_type exp
| Ast0.ArrayAccess(exp1,lb,exp2,rb) ->
(match strip_cv (Ast0.get_type exp2) with
None -> Ast0.set_type exp2 (Some(int_type))
| Some(ty) when is_int_type ty -> ()
+ | Some(Type_cocci.Unknown) ->
+ (* unknown comes from param types, not sure why this
+ is not just None... *)
+ Ast0.set_type exp2 (Some(int_type))
| Some ty -> err exp2 ty "bad type for an array index");
(match strip_cv (Ast0.get_type exp1) with
None -> None
*)
+(*
+ * Copyright 2005-2010, Ecole des Mines de Nantes, University of Copenhagen
+ * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
+ * This file is part of Coccinelle.
+ *
+ * Coccinelle is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, according to version 2 of the License.
+ *
+ * Coccinelle 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
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The authors reserve the right to distribute this or future versions of
+ * Coccinelle under other licenses.
+ *)
+
+
(*
* Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix