> > > #ifdef UNITTESTS
> > > ...
> > > #endif
> > >
> > > I would like to be able to not do matches on this part of the code. Is
> > > their an easy way to do so ?
> >
> > No.  The matching process doesn't see the ifdefs.  There is a notion of
> > skipping code that is under #if 0.  It could indeed be nice to generalize
> > that to other constants.  Ideally, we would do partial evaluations as
> > well, ie if we know that X is undefined, then perhaps X && Y is also
> > undefined.  I can look into it.
>
> That could be great. I'm sure it could help in a lot of situation for
> example changing API for a single OS on a complex project.

Attached is a patch that works for #ifdef and #ifndef.  In your case, you
would give spatch the argument --undefined UNITTESTS.  It should then
ignode the code under #ifdef UNITTESTS.  You can also specify several
names, eg --defined FOO,BAR,XXX.  The names should be separated by commas,
but not spaces.

Interpretation of #if is not supported.  Actually, the arguments to #if
are not parsed, so it would be quite a bit more work.  But it is probably
not impossible to handle as well.

julia
diff --git a/parsing_c/lexer_c.mll b/parsing_c/lexer_c.mll
index 1feebe0..80e609e 100644
--- a/parsing_c/lexer_c.mll
+++ b/parsing_c/lexer_c.mll
@@ -490,10 +490,20 @@ rule token = parse
 
 
   (* can have some ifdef 0  hence the letter|digit even at beginning of word *)
-  | "#" [' ''\t']* "ifdef"  [' ''\t']+ (letter|digit) ((letter|digit)*) [' ''\t']*
-      { TIfdef (no_ifdef_mark(), tokinfo lexbuf) }
-  | "#" [' ''\t']* "ifndef" [' ''\t']+ (letter|digit) ((letter|digit)*) [' ''\t']*
-      { TIfdef (no_ifdef_mark(), tokinfo lexbuf) }
+  | "#" [' ''\t']* "ifdef"  [' ''\t']+
+    (((letter|digit) ((letter|digit)*)) as x) [' ''\t']*
+      { if List.mem x !Flag_parsing_c.undefined
+        then TIfdefBool (false, no_ifdef_mark(), tokinfo lexbuf)
+        else if List.mem x !Flag_parsing_c.defined
+        then TIfdefBool (true, no_ifdef_mark(), tokinfo lexbuf)
+        else TIfdef (no_ifdef_mark(), tokinfo lexbuf) }
+  | "#" [' ''\t']* "ifndef" [' ''\t']+
+     (((letter|digit) ((letter|digit)*)) as x) [' ''\t']*
+      { if List.mem x !Flag_parsing_c.defined
+        then TIfdefBool (false, no_ifdef_mark(), tokinfo lexbuf)
+        else if List.mem x !Flag_parsing_c.undefined
+        then TIfdefBool (true, no_ifdef_mark(), tokinfo lexbuf)
+        else TIfdef (no_ifdef_mark(), tokinfo lexbuf) }
   | "#" [' ''\t']* "if" [' ' '\t']+
       { let info = tokinfo lexbuf in
         TIfdef (no_ifdef_mark(), info +> tok_add_s (cpp_eat_until_nl lexbuf))
diff --git a/parsing_c/flag_parsing_c.ml b/parsing_c/flag_parsing_c.ml
index cdb5df1..6b17c34 100644
--- a/parsing_c/flag_parsing_c.ml
+++ b/parsing_c/flag_parsing_c.ml
@@ -169,6 +169,11 @@ let disable_add_typedef = ref false
 let if0_passing = ref true
 let add_typedef_root = ref true
 
+(* defined and undefined constants *)
+let add c s = c := (Str.split (Str.regexp ",") s) @ !c
+let defined = ref ([] : string list)
+let undefined = ref ([] : string list)
+
 let cmdline_flags_parsing_algos () = [
 
     "--directive-passing",              Arg.Set cpp_directive_passing,
diff --git a/main.ml b/main.ml
index 129c390..ef131eb 100644
--- a/main.ml
+++ b/main.ml
@@ -565,8 +565,10 @@ let other_options = [
 
     "--disable-multi-pass", Arg.Set Flag_parsing_c.disable_multi_pass, " ";
 
-    "--noif0-passing",      Arg.Clear Flag_parsing_c.if0_passing,
-    " ";
+    "--noif0-passing",      Arg.Clear Flag_parsing_c.if0_passing, " ";
+    "--defined", Arg.String (Flag_parsing_c.add Flag_parsing_c.defined), " ";
+    "--undefined", Arg.String
+        (Flag_parsing_c.add Flag_parsing_c.undefined), " ";
     "--noadd-typedef-root", Arg.Clear Flag_parsing_c.add_typedef_root, " ";
     (* could use Flag_parsing_c.options_algo instead *)
 
_______________________________________________
Cocci mailing list
[email protected]
http://lists.diku.dk/mailman/listinfo/cocci
(Web access from inside DIKUs LAN only)

Reply via email to